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

时间:2011-05-03 08:06:11

标签: jquery jquery-selectors css-selectors textnode

我想使用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,这似乎更通用。

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

你正在做的是创建一个jquery选择器,并且选择器函数应该返回boolean来指示传递的节点是否匹配。所以你的当前函数为“#person”div返回一个“true”((实际返回值是div中的文本,它是非空的,因此被认为是真的),因此你得到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());