有没有jQuery / sizzle的替代品支持textNodes作为选择器中的头等公民?

我发现我需要完全支持jQuery不提供的DOM textNode的选择器。

jQuery忽略了文本节点,可能是因为大多数页面在各种浏览器可以区别对待的标签之间有大量不相关的空白。

关于文本节点的jQuery问题的大多数答案归结为使用.contents()函数,该函数返回所选项的所有子节点,包括文本节点 – 所有其他jQuery API忽略文本节点。

通常你不需要一些不能轻易建立起来的东西.contents()但我发现自己处于这样的境地。

我的用例是我想找到并在第三方网页中包装我无法控制的任意文本。 (想想浏览器扩展或用户脚本。)

到目前为止,我一直很乐意遍历DOM寻找所有文本节点或找到包含我感兴趣的所有文本节点的包装元素,并使用.contents()来迭代它们。

但是现在我发现我有时需要jQuery / sizzle选择器的全部function来将我的注意力缩小到类中的类的某些可能性等。

我考虑了使用textNode选择器扩展jQuery的方法,但这似乎是不可能的,因为忽略文本节点的普遍规则会在我的扩展被调用之前过滤掉其中的许多节点。

因此,我正在寻找一些其他JavaScript工具,它提供类似选择器的东西,但允许选择在其选择器表达式语法中任意混合的文本节点。

这是我可能需要做的一个例子:

 $('.ii:even > div > TXT, .ii:even > div > div.im > TXT') 

这是我个人尚未需要但可以轻易想象的一个例子:

 $('#something .somethingElse TXT') 

当你可以寻址(选择)textNodes的直接父代时,迭代它们的.contents()很容易,当你只能识别一些任意的祖先但是想要下面的所有文本节点时,这当然不是这样,这当然是元素节点很简单。

这是你可以做的事情:

 jQuery.fn.getTextNodes = function(val,_case) { var nodes = [], noVal = typeof val === "undefined", regExp = !noVal && jQuery.type(val) === "regexp", nodeType, nodeValue; if (!noVal && _case && !regExp) val = val.toLowerCase(); this.each(function() { if ((nodeType = this.nodeType) !== 3 && nodeType !== 8) { jQuery.each(this.childNodes, function() { if (this.nodeType === 3) { nodeValue = _case ? this.nodeValue.toLowerCase() : this.nodeValue; if (noVal || (regExp ? val.test(nodeValue) : nodeValue === val)) nodes.push(this); } }); } }); return this.pushStack(nodes, "getTextNodes", val || ""); }; 

然后你可以使用以下内容:

 $("selector").getTextNodes("selector"); 

这是一个JSFiddle。

.getTextNodes()工作原理非常简单。 如果未传递参数,则返回所有文本节点。 如果传递一个字符串,它将返回具有完全相同nodeValue文本节点。 如果要传递一个字符串,请将第二个参数设置为truthy值,以进行不区分大小写的检查。 第一个参数也可以是与nodeValue匹配的正则表达式。

希望这可以帮助。


编辑 :请注意,您也可以使用$("selector").getNodes("selector").end() ,因为它使用.pushStack()