jQuery custom selector for text nodes

泄露秘密 提交于 2019-12-06 11:32:03

问题


I would like to extract text from a DOM element using a jQuery custom selector. It should only select the text node without it's tagged siblings (much like /text() in XPath).

Background: I am working on a Firefox extension, that extracts some specific information (e.g. a username) on very different websites. Now I want my users to be able to dynamically add path definitions for new websites over a form as simple as possible:

Add new Website:

URL: ________________ (e.g. "http://stackoverflow.com/questions/")

Path: ________________ (e.g. ".user-details>a:eq(0)" for the name of the user asking a question)

On stackoverflow for instance, $(path).text() will return the username as text. But on some other sites the username is available only as text node with tagged siblings, as in this example:

<div id="person">
    johndoe <span id="age">(57)</span>
    <span id="description">Lorem ipsum dolor sit amet…</span>
</div>

Since jQuery doesn't provide a selector for text nodes (like /text() in XPath), I was hoping to find a solution creating a custom selector.

I know how to get the text node the 'non-selector' way:

var textNode = $('#person').contents().filter(function(){
    return this.nodeType == 3;
}).text();

alert(textNode); // gives me "johndoe"

How would I translate this into a custom selector? The following obviously doesn't work, since it always returns the complete element as soon as one part of it is a text node (as @VinayC explains in his answer):

$.extend($.expr[':'],{
    getText: function(element){
        return $(element).contents().filter(function() {return this.nodeType == 3;}).text();
    }
});

alert($('#person:getText')); //returns the whole DIV element

See my jsfiddle

Maybe it's not possible to do this with jQuery custom selectors. That's why I'm thinking about going 'back' to XPath which seems more versatile.

Thanks for your help.


回答1:


What you are doing is to create a jquery selector and the selector function is supposed to return boolean to indicate if the passed node has matched or not. So your current function returns a "true" for "#person" div ((actual return value is text within div which is non-empty and hence considered as true) and hence you get the div element as result.

You may try getText: function(node){ return node.nodeType == 3;} but this will work only jquery engine passes all document nodes including text nodes via selector functions (I am unaware if it does or does not). Alternate is to create an helper function instead of custom selector.

EDIT: how about extending jquery object? For example,

$.fn.extend({
    getText: function() {
        return this.contents().filter(function() {return this.nodeType == 3;}).text();
    }
});

alert($('#person').getText());


来源:https://stackoverflow.com/questions/5866763/jquery-custom-selector-for-text-nodes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!