代码之家  ›  专栏  ›  技术社区  ›  Christian Oudard

如何使用jQuery选择文本节点?

  •  374
  • Christian Oudard  · 技术社区  · 17 年前

    我想获取元素的所有子代文本节点,作为jQuery集合。最好的方法是什么?

    11 回复  |  直到 17 年前
        1
  •  266
  •   Tim Down    11 年前

    jQuery没有一个方便的函数来实现这一点。你需要合并 contents() ,它将只提供子节点,但包含文本节点,带有 find()

    var getTextNodesIn = function(el) {
        return $(el).find(":not(iframe)").addBack().contents().filter(function() {
            return this.nodeType == 3;
        });
    };
    
    getTextNodesIn(el);
    

    注意:如果您使用的是jQuery1.7或更早版本,上面的代码将不起作用。要解决此问题,请替换 addBack() 具有 andSelf() andSelf() 反对赞成 从1.8开始。

    ugly workaround for jQuery's overloading of its contents() function (感谢注释中的@rabidsnail指出了这一点),因此这里是使用简单递归函数的非jQuery解决方案。这个 includeWhitespaceNodes 参数控制输出中是否包含空白文本节点(在jQuery中,它们会自动过滤掉)。

    更新:修复了includeWhitespaceNodes为falsy时的错误。

    function getTextNodesIn(node, includeWhitespaceNodes) {
        var textNodes = [], nonWhitespaceMatcher = /\S/;
    
        function getTextNodes(node) {
            if (node.nodeType == 3) {
                if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
                    textNodes.push(node);
                }
            } else {
                for (var i = 0, len = node.childNodes.length; i < len; ++i) {
                    getTextNodes(node.childNodes[i]);
                }
            }
        }
    
        getTextNodes(node);
        return textNodes;
    }
    
    getTextNodesIn(el);
    
        2
  •  215
  •   James Westgate    14 年前

    Jauco在评论中发布了一个很好的解决方案,因此我将其复制到这里:

    $(elem)
      .contents()
      .filter(function() {
        return this.nodeType === 3; //Node.TEXT_NODE
      });
    
        3
  •  18
  •   He Nrik    14 年前
    $('body').find('*').contents().filter(function () { return this.nodeType === 3; });
    
        4
  •  8
  •   Salman Arshad    10 年前

    jQuery.contents() 可用于 jQuery.filter 查找所有子文本节点。稍微扭转一下,您也可以找到孙子文本节点。不需要递归:

    $(function() {
      var $textNodes = $("#test, #test *").contents().filter(function() {
        return this.nodeType === Node.TEXT_NODE;
      });
      /*
       * for testing
       */
      $textNodes.each(function() {
        console.log(this);
      });
    });
    div { margin-left: 1em; }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    
    <div id="test">
      child text 1<br>
      child text 2
      <div>
        grandchild text 1
        <div>grand-grandchild text 1</div>
        grandchild text 2
      </div>
      child text 3<br>
      child text 4
    </div>

    jsFiddle

        5
  •  4
  •   Alex W    12 年前

    我用接受的过滤函数得到了很多空文本节点。如果您只对选择包含非空白的文本节点感兴趣,请尝试添加 nodeValue 有条件的 filter 函数,就像一个简单的 $.trim(this.nodevalue) !== ''

    $('element')
        .contents()
        .filter(function(){
            return this.nodeType === 3 && $.trim(this.nodeValue) !== '';
        });
    

    http://jsfiddle.net/ptp6m97v/

    &shy; 字符、换行符 \n ,选项卡等),可以尝试使用正则表达式。例如 \S 将匹配任何非空白字符:

    $('element')
            .contents()
            .filter(function(){
                return this.nodeType === 3 && /\S/.test(this.nodeValue);
            });
    
        6
  •  3
  •   colllin spam_eggs    15 年前

    要将所有子文本节点作为jquery集合获取,请执行以下操作:

    $('selector').clone().children().remove().end().contents();
    

    要获取删除了非文本子元素的原始元素的副本,请执行以下操作:

    $('selector').clone().children().remove().end();
    
        7
  •  2
  •   iConnor    12 年前

    出于某种原因 contents() 对我不起作用,所以如果对你不起作用,这是我制定的解决方案,我创造的 jQuery.fn.descendants 选择是否包含文本节点

    用法


    获取所有子体,包括文本节点和元素节点

    jQuery('body').descendants('all');
    

    获取仅返回文本节点的所有子体

    jQuery('body').descendants(true);
    

    获取仅返回元素节点的所有子体

    jQuery('body').descendants();
    

    咖啡原稿

    jQuery.fn.descendants = ( textNodes ) ->
    
        # if textNodes is 'all' then textNodes and elementNodes are allowed
        # if textNodes if true then only textNodes will be returned
        # if textNodes is not provided as an argument then only element nodes
        # will be returned
    
        allowedTypes = if textNodes is 'all' then [1,3] else if textNodes then [3] else [1]
    
        # nodes we find
        nodes = []
    
    
        dig = (node) ->
    
            # loop through children
            for child in node.childNodes
    
                # push child to collection if has allowed type
                nodes.push(child) if child.nodeType in allowedTypes
    
                # dig through child if has children
                dig child if child.childNodes.length
    
    
        # loop and dig through nodes in the current
        # jQuery object
        dig node for node in this
    
    
        # wrap with jQuery
        return jQuery(nodes)
    

    插入式Javascript版本

    var __indexOf=[].indexOf||function(e){for(var t=0,n=this.length;t<n;t++){if(t in this&&this[t]===e)return t}return-1}; /* indexOf polyfill ends here*/ jQuery.fn.descendants=function(e){var t,n,r,i,s,o;t=e==="all"?[1,3]:e?[3]:[1];i=[];n=function(e){var r,s,o,u,a,f;u=e.childNodes;f=[];for(s=0,o=u.length;s<o;s++){r=u[s];if(a=r.nodeType,__indexOf.call(t,a)>=0){i.push(r)}if(r.childNodes.length){f.push(n(r))}else{f.push(void 0)}}return f};for(s=0,o=this.length;s<o;s++){r=this[s];n(r)}return jQuery(i)}
    

    http://pastebin.com/cX3jMfuD

    这是跨浏览器,一个小的 Array.indexOf

        8
  •  1
  •   Mr_Green    13 年前

    也可以这样做:

    var textContents = $(document.getElementById("ElementId").childNodes).filter(function(){
            return this.nodeType == 3;
    });
    

    上面的代码从给定元素的直接子节点过滤textNodes。

        9
  •  0
  •   Rahen Rangan    15 年前

    String.prototype.stripTags=function(){
    var rtag=/<.*?[^>]>/g;
    return this.replace(rtag,'');
    }
    

    用法:

    var newText=$('selector').html().stripTags();
    
        10
  •  0
  •   davenpcj    13 年前

    对我来说,老得很 .contents()

    例如,这将使用 pre 没有问题。

    jQuery("#resultTable td").content().wrap("<pre/>")
    
        11
  •  0
  •   iConnor    12 年前

    代码:

    $.fn.nextNode = function(){
      var contents = $(this).parent().contents();
      return contents.get(contents.index(this)+1);
    }
    

    用法:

    $('#my_id').nextNode();
    

    就像 next()