【问题标题】:jQuery selector for an element that directly contains text?直接包含文本的元素的jQuery选择器?
【发布时间】:2011-10-25 22:04:27
【问题描述】:

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

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

将选择下面的两个 div:

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

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

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

更新:

澄清一下,如果我正在搜索文本“其他”而不是“测试”,那么我只想找到父 div。

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    $('div&gt;: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);
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      只是为了完成知识库。如果您需要获取正文中包含特定文本或字符的所有 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

      【讨论】:

        【解决方案3】:

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

        edit:上面的 sn-p 只是为了测试元素,在实现中它看起来更像这样: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');
        

        【讨论】:

        • 不是用于生产的东西,但用于调试目的却出奇的快。
        • 请注意,由于这会克隆元素,因此您无法对它们执行任何有用的更改,因为您正在更改克隆。
        【解决方案4】:

        尝试添加大于:

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

        【讨论】:

        • div 也匹配内部 div,这并不重要,除了 &gt; 外部 div 不会测试其内容
        • 关闭但不完全在那里。如果你将它切换到$('div&gt;:contains("something else")'),它会在应该提醒 1 时提醒 0。jsfiddle.net/TT7dR/4
        • @genesis 谢谢。根据你所说的,我不明白在这种情况下这是如何工作的。我们正在尝试获取包含“test”的 div,而不是为其子级(它没有)。
        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          这似乎对我有用:

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

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

          这会强制匹配的 :contains 选择器成为 &lt;div&gt; 元素的直接子元素

          【讨论】:

          • 关闭但不完全在那里。如果你将它切换到$('div&gt;:contains("something else")'),它会在应该提醒 1 时提醒 0。jsfiddle.net/TT7dR/4
          【解决方案7】:

          尝试以下方法:

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

          【讨论】:

          • did>div 是指父div 包含test 且父div 仅有一个子元素的div 子元素。
          【解决方案8】:

          添加更多选择:

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

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

          Reference

          【讨论】:

            【解决方案9】:

            您可以简单地选择没有您的元素的元素

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

            【讨论】:

              【解决方案10】:

              要编写的代码更少(但有一点限制):

              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”。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-03-27
                • 2011-01-05
                • 1970-01-01
                • 2017-09-20
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多