Using .text() to retrieve only text not nested in child tags

后端 未结 25 1715
隐瞒了意图╮
隐瞒了意图╮ 2020-11-21 05:55

If I have html like this:

  • This is some text First span text
  • 相关标签:
    25条回答
    • 2020-11-21 06:43

      I am not a jquery expert, but how about,

      $('#listItem').children().first().text()
      
      0 讨论(0)
    • 2020-11-21 06:44

      isn't the code:

      var text  =  $('#listItem').clone().children().remove().end().text();
      

      just becoming jQuery for jQuery's sake? When simple operations involve that many chained commands & that much (unnecessary) processing, perhaps it is time to write a jQuery extension:

      (function ($) {
          function elementText(el, separator) {
              var textContents = [];
              for(var chld = el.firstChild; chld; chld = chld.nextSibling) {
                  if (chld.nodeType == 3) { 
                      textContents.push(chld.nodeValue);
                  }
              }
              return textContents.join(separator);
          }
          $.fn.textNotChild = function(elementSeparator, nodeSeparator) {
          if (arguments.length<2){nodeSeparator="";}
          if (arguments.length<1){elementSeparator="";}
              return $.map(this, function(el){
                  return elementText(el,nodeSeparator);
              }).join(elementSeparator);
          }
      } (jQuery));
      

      to call:

      var text = $('#listItem').textNotChild();
      

      the arguments are in case a different scenario is encountered, such as

      <li>some text<a>more text</a>again more</li>
      <li>second text<a>more text</a>again more</li>
      
      var text = $("li").textNotChild(".....","<break>");
      

      text will have value:

      some text<break>again more.....second text<break>again more
      
      0 讨论(0)
    • 2020-11-21 06:45

      I presume this would be a fine solution also - if you want to get contents of all text nodes that are direct children of selected element.

      $(selector).contents().filter(function(){ return this.nodeType == 3; }).text();
      

      Note: jQuery documentation uses similar code to explain contents function: https://api.jquery.com/contents/

      P.S. There's also a bit uglier way to do that, but this shows more in depth how things work, and allows for custom separator between text nodes (maybe you want a line break there)

      $(selector).contents().filter(function(){ return this.nodeType == 3; }).map(function() { return this.nodeValue; }).toArray().join("");
      
      0 讨论(0)
    • 2020-11-21 06:46

      To be able to trim the result, use DotNetWala's like so:

      $("#foo")
          .clone()    //clone the element
          .children() //select all the children
          .remove()   //remove all the children
          .end()  //again go back to selected element
          .text()
          .trim();
      

      I found out that using the shorter version like document.getElementById("listItem").childNodes[0] won't work with jQuery's trim().

      0 讨论(0)
    • 2020-11-21 06:47

      I propose to use the createTreeWalker to find all texts elements not attached to html elements (this function can be used to extend jQuery):

      function textNodesOnlyUnder(el) {
        var resultSet = [];
        var n = null;
        var treeWalker  = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, function (node) {
          if (node.parentNode.id == el.id && node.textContent.trim().length != 0) {
            return NodeFilter.FILTER_ACCEPT;
          }
          return NodeFilter.FILTER_SKIP;
        }, false);
        while (n = treeWalker.nextNode()) {
          resultSet.push(n);
        }
        return resultSet;
      }
      
      
      
      window.onload = function() {
        var ele = document.getElementById('listItem');
        var textNodesOnly = textNodesOnlyUnder(ele);
        var resultingText = textNodesOnly.map(function(val, index, arr) {
          return 'Text element N. ' + index + ' --> ' + val.textContent.trim();
        }).join('\n');
        document.getElementById('txtArea').value = resultingText;
      }
      <li id="listItem">
          This is some text
          <span id="firstSpan">First span text</span>
          <span id="secondSpan">Second span text</span>
      </li>
      <textarea id="txtArea" style="width: 400px;height: 200px;"></textarea>

      0 讨论(0)
    • 2020-11-21 06:48

      This is a good way for me

         var text  =  $('#listItem').clone().children().remove().end().text();
      
      0 讨论(0)
    提交回复
    热议问题