用于直接包含文本的元素的 jQuery 选择器?

IT技术 javascript jquery
2021-03-14 02:24:51

我能够使用:contains选择器使其部分工作,但我的问题是如果一个元素包含一个包含它仍然返回的文本的元素。例如:

$('div:contains("test")')

将选择以下两个 div:

<div>something else
   <div>test</div>
</div>

小提琴:http : //jsfiddle.net/TT7dR/

如何仅选择“直接”包含文本的 div?这意味着在上面的例子中只会选择子 div。

更新:

只是为了澄清,如果我要搜索文本“别的东西”而不是“测试”,那么我只想找到父 div。

6个回答

$('div>:contains("test")')不是通用解决方案,它仅适用于您的特定示例。它仍然匹配其后代包含文本的任何元素test,只要其父元素div

事实上,目前没有选择器只选择包含目标文本的文本节点的直接父节点。为此,您必须自己遍历 DOM 树,检查为目标文本找到的每个文本节点,或者编写一个插件来执行相同操作。它会很慢,但不会像现在那样慢:contains(它不是标准的 CSS 选择器,因此您无法获得浏览器原生的快速选择器支持)。

这是一个简单的 DOM 函数,您可以将其用作起点。在相邻(非规范化)文本节点中查找文本或将其隐藏在插件/选择器扩展中可能会得到改进。

function findElementsDirectlyContainingText(ancestor, text) {
    var elements= [];
    walk(ancestor);
    return elements;

    function walk(element) {
        var n= element.childNodes.length;
        for (var i= 0; i<n; i++) {
            var child= element.childNodes[i];
            if (child.nodeType===3 && child.data.indexOf(text)!==-1) {
                elements.push(element);
                break;
            }
        }
        for (var i= 0; i<n; i++) {
            var child= element.childNodes[i];
            if (child.nodeType===1)
                walk(child);
        }
    }
}

只是为了完成知识库。如果您需要获取包含特定文本或字符的正文中的所有 DOM 元素(不仅是 DIV),您可以使用:

function getNodesThatContain(text) {
    var textNodes = $(document).find(":not(iframe, script)")
      .contents().filter( 
          function() {
           return this.nodeType == 3 
             && this.textContent.indexOf(text) > -1;
    });
    return textNodes.parent();
};

console.log(getNodesThatContain("test"));

希望有帮助。

jsfiddle:http : //jsfiddle.net/85qEh/2/

学分:DMoses

您可能必须执行效率低下的查询。如果有人找到一个可以过滤掉子元素的选择器,请不要使用此解决方案:http : //viralpatel.net/blogs/2011/02/jquery-get-text-element-without-child-element.html

$("div:contains('test')")
    .clone()    //clone the element
    .children() //select all the children
    .remove()   //remove all the children
    .end()  //again go back to selected element
    .filter(":contains('test')")

编辑:上面的片段只是为了测试元素,在实现中它看起来更像这样:http : //jsfiddle.net/rkw79/TT7dR/6/

$("div:contains('test')").filter(function() {
    return (
    $(this).clone() //clone the element
    .children() //select all the children
    .remove() //remove all the children
    .end() //again go back to selected element
    .filter(":contains('test')").length > 0)
}).css('border', 'solid 1px black');
请注意,由于这会克隆元素,因此您无法对它们执行任何有用的更改,因为您正在更改克隆。
2021-05-03 02:24:51
不是用于生产的东西,但用于调试目的的速度非常快。
2021-05-04 02:24:51

尝试添加大于:

$('div>:contains("test")')
div也匹配内部 div,这并不重要,只是>外部 div 不会测试其内容
2021-04-22 02:24:51
关闭但不完全在那里。如果你把它切换到$('div>:contains("something else")')它会在它应该提醒 1 时提醒0。jsfiddle.net/TT7dR/4
2021-04-28 02:24:51
@genesis 谢谢。根据你所说的,我不明白在这种情况下这是如何工作的。我们正在试图获得 div包含“测试”,而不是它的孩子(它现在没有的)。
2021-04-29 02:24:51

查找特定元素,但不查找父元素

var elementsContainingText = ($(':contains("' + text + '")', target)).filter(function() {
    return $(this).contents().filter(function() {return this.nodeType === 3 && this.nodeValue.indexOf(text) !== -1; }).length > 0;
});