是否有替代jQuery / sizzle支持textNodes作为选择器中的一流公民? [英] Is there an alternative to jQuery / sizzle that supports textNodes as first class citizens in selectors?

查看:146
本文介绍了是否有替代jQuery / sizzle支持textNodes作为选择器中的一流公民?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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



通常你不需要一些不容易被建立在 .contents()但我有发现自己在这样的情况。



我的用例是我想定位,然后包装任意运行的文本在第三方网页,我无法控制。 (Think浏览器扩展或用户脚本。)



到目前为止,我一直很高兴走DOM查找所有文本节点或查找包含所有文本节点的包装元素我有兴趣使用 .contents()来遍历它们。



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



我考虑了使用 textNode selector,但这似乎是不可能的,因为忽略了在我的扩展名被调用之前过滤它们的文本节点的普遍规则。



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



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

  $('。ii:even> div> T,.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 ||);
};

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

  $( 选择)getTextNodes( 选择)。 

这里是一个JSFiddle。



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



希望这有帮助。 p>




修改:请注意,您也可以使用 $(selector ).getNodes(selector)。end(),因为它使用 .pushStack()


I've discovered that I have a need for selectors with full support for DOM textNodes that jQuery doesn't provide.

jQuery ignores text nodes, probably because most pages have tons of irrelevant blank ones between tags that the various browsers can treat differently.

Most answers to jQuery questions about text nodes come down to using the .contents() function which returns all the child nodes for the selected items, including text nodes - all other jQuery APIs ignore text nodes.

Often you don't need something that can't easily be built upon .contents() but I have found myself in such a situation.

My use case is that I want to locate and then wrap arbitrary runs of text in 3rd-party web pages over which I have no control. (Think browser extension or userscript.)

So far I've been happy to walk the DOM looking for all text nodes or find a wrapper element that contains all the text nodes I'm interested in and use .contents() to iterate through them.

But now I have found that I sometimes need the full power of jQuery/sizzle selectors to narrow my focus down to certain possibilities of classes within classes etc.

I considered ways to extend jQuery with a textNode selector but that seems to be impossible due to a pervasive rule of ignoring text nodes which would filter many of them out before my extension gets called.

Thus I'm looking for some other JavaScript tool which offers something like selectors but allows selecting text nodes arbitrarily mixed in its selector expression syntax.

Here's an example of what I might need to do:

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

Here's an example I personally haven't needed yet but can easily imagine:

$('#something .somethingElse TXT')

When you can address (select) the immediate parent(s) of the textNodes, iterating over their .contents() is easy, not so when you can only identify some arbitrary ancestor but want all the text nodes below this, which is of course trivial for element nodes.

解决方案

Here is something you could do:

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 || "");
};

Then you could use the following:

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

Here is a JSFiddle.

How .getTextNodes() works is very simple. If you don't pass an argument, it returns all text nodes. If you pass it a string, it returns text nodes with that exact same nodeValue. If you are passing it a string, set the second argument to a truthy value for a case-insensitive check. The first argument can also be a regular expression against which the nodeValue is matched.

Hope this helps.


Edit: Note that you can also use $("selector").getNodes("selector").end(), since it uses .pushStack().

这篇关于是否有替代jQuery / sizzle支持textNodes作为选择器中的一流公民?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆