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

26

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

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

将同时选择下面的两个 div 元素:

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

fiddle: http://jsfiddle.net/TT7dR/

如何选择“直接”包含文本的 div 元素?即在上述示例中,只有子 div 元素将被选择。

更新:

仅作澄清,如果我想要查找的文本是“something else”而不是“test”,那么我只想找到父 div 元素。

10个回答

12

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

实际上,目前没有选择器可以仅选择包含目标文本的文本节点的直接父元素。要实现这一点,您需要自己遍历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);
        }
    }
}

9

为了完善知识库,如果您需要获取包含特定文本或字符的中的所有DOM元素(不仅限于

),您可以使用以下方法:

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

6

如果有人发现一个选择器可以过滤掉子元素,那么您可能需要进行低效的查询。不要使用此解决方案: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');

不是用于生产,但出乎意料地快速用于调试目的。 - Mahn
1
请注意,由于这会克隆元素,因此您无法对它们进行任何有用的更改,因为您正在更改克隆。 - mrbellek

3

尝试添加大于符号:

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

div 匹配内部的 div,这并不重要,除非使用 >,否则外部的 div 不会被测试其内容。 - ThiefMaster
接近了但还不太对。如果你把它改成 $('div>:contains("something else")'),当它应该弹出1时,它会弹出0。http://jsfiddle.net/TT7dR/4/ - Abe Miessler
1
@genesis 谢谢。根据你所说的,我不明白这在这种情况下如何起作用。我们正在尝试获取包含“test”的* div,而不是它的子元素(它没有任何子元素)。 - Nick Rolando

1
查找特定元素,但不包括其父级元素。
var elementsContainingText = ($(':contains("' + text + '")', target)).filter(function() {
    return $(this).contents().filter(function() {return this.nodeType === 3 && this.nodeValue.indexOf(text) !== -1; }).length > 0;
});

0

这对我来说似乎有效:

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

http://jsfiddle.net/TT7dR/1/

这将强制匹配的:contains选择器成为<div>元素的直接子元素


2
接近了但还不太对。如果你把它改成 $('div>:contains("something else")'),当它应该弹出1时,它会弹出0。http://jsfiddle.net/TT7dR/4/ - Abe Miessler

0

请尝试以下方法:

$("div>div:contains(test):only-of-type")

did>div 指的是父元素为 div,包含 test 的 div 子元素,并且该子元素是其父元素 div 的唯一子元素。 - Yuvaraj Gunisetti

0

增加更多的替代方案:

if($(selector).text().trim().length) {
   var thetext = $(selector).contents().filter(function(){
     return this.nodeType === 3;                     
   }).text().trim();    

  console.log(thetext);             

}

它将仅选择文本并删除任何带有标签的元素!

参考资料


0

写的代码更少(但有一些限制):

let selector = $('div:contains("test")');
selector.not(selector.has('div:contains("test")'))

只需使用jQuery函数(.has),因为css的:has是实验性的: https://developer.mozilla.org/en-US/docs/Web/CSS/:has#Browser_compatibility


限制:

当您有这样的结构时:

<div>
<div>test</div>
test
</div>

只有内部的div元素才会被这个解决方案找到。这是因为div仍然有一个子元素,其中包含字符串“test”。


0

你可以简单地选择不包含你的元素的元素

$('div:contains("test"):not(:has(> div))')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接