文本节点的 jQuery 自定义选择器

发布于 2024-11-04 21:18:52 字数 1580 浏览 3 评论 0原文

我想使用 jQuery 自定义选择器从 DOM 元素中提取文本。它应该只选择没有标记同级的文本节点(很像 XPath 中的 /text())。

背景:我正在开发一个 Firefox 扩展,它可以在非常不同的网站上提取一些特定信息(例如用户名)。现在我希望我的用户能够通过尽可能简单的表单动态添加新网站的路径定义:

添加新网站:

网址:________________(例如“http://stackoverflow.com/questions/”)

路径:________________(例如“.user-details>a:eq(0)”代表提出问题的用户的姓名)

例如,在 stackoverflow 上,$(path).text() 将以文本形式返回用户名。但在其他一些网站上,用户名只能作为带有标记同级的文本节点使用,如下例所示:

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

由于 jQuery 不提供文本节点选择器(如 XPath 中的 /text()),我希望找到解决方案创建自定义选择器。

我知道如何以“非选择器”方式获取文本节点:

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

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

如何将其转换为自定义选择器?以下显然不起作用,因为只要元素的一部分是文本节点,它总是返回完整的元素(正如 @VinayC 在他的回答中解释的那样):

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

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

请参阅我的 jsfiddle

也许无法使用 jQuery 自定义选择器来做到这一点。这就是为什么我正在考虑“回到”XPath,因为它看起来更通用。

感谢您的帮助。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

想你的星星会说话 2024-11-11 21:18:52

您正在做的是创建一个 jquery 选择器,选择器函数应该返回布尔值以指示传递的节点是否匹配。因此,您当前的函数为“#person”div 返回“true”((实际返回值是 div 中的文本,它非空,因此被视为 true),因此您得到 div 元素作为结果。

您可以尝试 getText: function(node){ return node.nodeType == 3;} 但这仅适用于 jquery 引擎通过选择器函数传递所有文档节点,包括文本节点(我不知道它是否有效)。另一种方法是创建一个辅助函数而不是自定义选择器

:扩展 jquery 对象怎么样?

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

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

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());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文