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

时间:2022-10-31 17:51:57

I would like to get all descendant text nodes of an element, as a jQuery collection. What is the best way to do that?

我希望将元素的所有后代文本节点作为jQuery集合。最好的方法是什么?

11 个解决方案

#1


236  

jQuery doesn't have a convenient function for this. You need to combine contents(), which will give just child nodes but includes text nodes, with find(), which gives all descendant elements but no text nodes. Here's what I've come up with:

jQuery并没有一个方便的函数。您需要合并contents(),它只提供子节点,但包含文本节点,find()提供所有子代元素,但没有文本节点。以下是我的想法:

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

getTextNodesIn(el);

Note: If you're using jQuery 1.7 or earlier, the code above will not work. To fix this, replace addBack() with andSelf(). andSelf() is deprecated in favour of addBack() from 1.8 onwards.

注意:如果您使用的是jQuery 1.7或更早,上面的代码将不起作用。要修复这个问题,请用andSelf()替换addBack()。andSelf()从1.8开始就不赞成使用addBack()。

This is somewhat inefficient compared to pure DOM methods and has to include an ugly workaround for jQuery's overloading of its contents() function (thanks to @rabidsnail in the comments for pointing that out), so here is non-jQuery solution using a simple recursive function. The includeWhitespaceNodes parameter controls whether or not whitespace text nodes are included in the output (in jQuery they are automatically filtered out).

与纯粹的DOM方法相比,这有点低效,而且还必须包含一个很难看的方法,因为jQuery的内容()函数的重载(感谢@rabidsnail在注释中指出),所以这里是使用简单递归函数的非jQuery解决方案。includeWhitespaceNodes参数控制是否将空白文本节点包含在输出中(在jQuery中它们被自动过滤掉)。

Update: Fixed bug when includeWhitespaceNodes is 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


198  

Jauco posted a good solution in a comment, so I'm copying it here:

Jauco在评论中发布了一个很好的解决方案,所以我在这里复制它:

$(elem)
  .contents()
  .filter(function() {
    return this.nodeType === 3; //Node.TEXT_NODE
  });

#3


14  

$('body').find('*').contents().filter(function () { return this.nodeType === 3; });

#4


3  

I was getting a lot of empty text nodes with the accepted filter function. If you're only interested in selecting text nodes that contain non-whitespace, try adding a nodeValue conditional to your filter function, like a simple $.trim(this.nodevalue) !== '':

我得到了很多空的文本节点,它们具有可接受的过滤功能。如果您只对选择包含非空格的文本节点感兴趣,请尝试添加一个nodeValue条件,如一个简单的$.trim(this.nodevalue) !== "

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

http://jsfiddle.net/ptp6m97v/

http://jsfiddle.net/ptp6m97v/

Or to avoid strange situations where the content looks like whitespace, but is not (e.g. the soft hyphen &shy; character, newlines \n, tabs, etc.), you can try using a Regular Expression. For example, \S will match any non-whitespace characters:

或者避免出现内容看起来像空格的奇怪情况,但不是(例如:软连字符和害羞);字符、换行符、标签等等),您可以尝试使用正则表达式。例如,\S将匹配任何非空白字符:

$('element')
        .contents()
        .filter(function(){
            return this.nodeType === 3 && /\S/.test(this.nodeValue);
        });

#5


3  

jQuery.contents() can be used with jQuery.filter to find all child text nodes. With a little twist, you can find grandchildren text nodes as well. No recursion required:

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

$(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

jsFiddle

#6


2  

If you can make the assumption that all children are either Element Nodes or Text Nodes, then this is one solution.

如果您可以假设所有的子节点都是元素节点或文本节点,那么这就是一个解决方案。

To get all child text nodes as a jquery collection:

将所有子文本节点作为jquery集合获取:

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

To get a copy of the original element with non-text children removed:

要获取原始元素的副本,并删除非文本的子元素:

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

#7


1  

Can also be done like this:

也可以这样做:

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

The above code filters the textNodes from direct children child nodes of a given element.

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

#8


1  

For some reason contents() didn't work for me, so if it didn't work for you, here's a solution I made, I created jQuery.fn.descendants with the option to include text nodes or not

由于某些原因,内容()对我不起作用,所以如果它对您不起作用,那么这里有一个我创建的解决方案,我创建了jquery.fn .后代,可以选择包含文本节点。

Usage

使用


Get all descendants including text nodes and element nodes

获取所有的后代,包括文本节点和元素节点。

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

Get all descendants returning only text nodes

让所有的后代只返回文本节点。

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

Get all descendants returning only element nodes

让所有的后代只返回元素节点。

jQuery('body').descendants();

Coffeescript Original:

Coffeescript原创:

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)

Drop In Javascript Version

减少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)}

Unminified Javascript version: http://pastebin.com/cX3jMfuD

Unminified Javascript版本:http://pastebin.com/cX3jMfuD

This is cross browser, a small Array.indexOf polyfill is included in the code.

这是交叉浏览器,一个小数组。代码中包含了polyfill的索引。

#9


0  

if you want to strip all tags, then try this

如果你想去掉所有标签,那么试试这个。

function:

功能:

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

usage:

用法:

var newText=$('selector').html().stripTags();

#10


0  

For me, plain old .contents() appeared to work to return the text nodes, just have to be careful with your selectors so that you know they will be text nodes.

对于我来说,plain old .contents()似乎是用来返回文本节点的,所以必须小心选择您的选择器,以便您知道它们将是文本节点。

For example, this wrapped all the text content of the TDs in my table with pre tags and had no problems.

例如,它将TDs的所有文本内容用pre标记包装起来,并且没有问题。

jQuery("#resultTable td").content().wrap("<pre/>")

#11


0  

I had the same problem and solved it with:

我遇到了同样的问题,用:

Code:

代码:

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

Usage:

用法:

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

Is like next() but also returns the text nodes.

与next()类似,但也返回文本节点。

#1


236  

jQuery doesn't have a convenient function for this. You need to combine contents(), which will give just child nodes but includes text nodes, with find(), which gives all descendant elements but no text nodes. Here's what I've come up with:

jQuery并没有一个方便的函数。您需要合并contents(),它只提供子节点,但包含文本节点,find()提供所有子代元素,但没有文本节点。以下是我的想法:

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

getTextNodesIn(el);

Note: If you're using jQuery 1.7 or earlier, the code above will not work. To fix this, replace addBack() with andSelf(). andSelf() is deprecated in favour of addBack() from 1.8 onwards.

注意:如果您使用的是jQuery 1.7或更早,上面的代码将不起作用。要修复这个问题,请用andSelf()替换addBack()。andSelf()从1.8开始就不赞成使用addBack()。

This is somewhat inefficient compared to pure DOM methods and has to include an ugly workaround for jQuery's overloading of its contents() function (thanks to @rabidsnail in the comments for pointing that out), so here is non-jQuery solution using a simple recursive function. The includeWhitespaceNodes parameter controls whether or not whitespace text nodes are included in the output (in jQuery they are automatically filtered out).

与纯粹的DOM方法相比,这有点低效,而且还必须包含一个很难看的方法,因为jQuery的内容()函数的重载(感谢@rabidsnail在注释中指出),所以这里是使用简单递归函数的非jQuery解决方案。includeWhitespaceNodes参数控制是否将空白文本节点包含在输出中(在jQuery中它们被自动过滤掉)。

Update: Fixed bug when includeWhitespaceNodes is 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


198  

Jauco posted a good solution in a comment, so I'm copying it here:

Jauco在评论中发布了一个很好的解决方案,所以我在这里复制它:

$(elem)
  .contents()
  .filter(function() {
    return this.nodeType === 3; //Node.TEXT_NODE
  });

#3


14  

$('body').find('*').contents().filter(function () { return this.nodeType === 3; });

#4


3  

I was getting a lot of empty text nodes with the accepted filter function. If you're only interested in selecting text nodes that contain non-whitespace, try adding a nodeValue conditional to your filter function, like a simple $.trim(this.nodevalue) !== '':

我得到了很多空的文本节点,它们具有可接受的过滤功能。如果您只对选择包含非空格的文本节点感兴趣,请尝试添加一个nodeValue条件,如一个简单的$.trim(this.nodevalue) !== "

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

http://jsfiddle.net/ptp6m97v/

http://jsfiddle.net/ptp6m97v/

Or to avoid strange situations where the content looks like whitespace, but is not (e.g. the soft hyphen &shy; character, newlines \n, tabs, etc.), you can try using a Regular Expression. For example, \S will match any non-whitespace characters:

或者避免出现内容看起来像空格的奇怪情况,但不是(例如:软连字符和害羞);字符、换行符、标签等等),您可以尝试使用正则表达式。例如,\S将匹配任何非空白字符:

$('element')
        .contents()
        .filter(function(){
            return this.nodeType === 3 && /\S/.test(this.nodeValue);
        });

#5


3  

jQuery.contents() can be used with jQuery.filter to find all child text nodes. With a little twist, you can find grandchildren text nodes as well. No recursion required:

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

$(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

jsFiddle

#6


2  

If you can make the assumption that all children are either Element Nodes or Text Nodes, then this is one solution.

如果您可以假设所有的子节点都是元素节点或文本节点,那么这就是一个解决方案。

To get all child text nodes as a jquery collection:

将所有子文本节点作为jquery集合获取:

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

To get a copy of the original element with non-text children removed:

要获取原始元素的副本,并删除非文本的子元素:

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

#7


1  

Can also be done like this:

也可以这样做:

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

The above code filters the textNodes from direct children child nodes of a given element.

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

#8


1  

For some reason contents() didn't work for me, so if it didn't work for you, here's a solution I made, I created jQuery.fn.descendants with the option to include text nodes or not

由于某些原因,内容()对我不起作用,所以如果它对您不起作用,那么这里有一个我创建的解决方案,我创建了jquery.fn .后代,可以选择包含文本节点。

Usage

使用


Get all descendants including text nodes and element nodes

获取所有的后代,包括文本节点和元素节点。

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

Get all descendants returning only text nodes

让所有的后代只返回文本节点。

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

Get all descendants returning only element nodes

让所有的后代只返回元素节点。

jQuery('body').descendants();

Coffeescript Original:

Coffeescript原创:

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)

Drop In Javascript Version

减少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)}

Unminified Javascript version: http://pastebin.com/cX3jMfuD

Unminified Javascript版本:http://pastebin.com/cX3jMfuD

This is cross browser, a small Array.indexOf polyfill is included in the code.

这是交叉浏览器,一个小数组。代码中包含了polyfill的索引。

#9


0  

if you want to strip all tags, then try this

如果你想去掉所有标签,那么试试这个。

function:

功能:

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

usage:

用法:

var newText=$('selector').html().stripTags();

#10


0  

For me, plain old .contents() appeared to work to return the text nodes, just have to be careful with your selectors so that you know they will be text nodes.

对于我来说,plain old .contents()似乎是用来返回文本节点的,所以必须小心选择您的选择器,以便您知道它们将是文本节点。

For example, this wrapped all the text content of the TDs in my table with pre tags and had no problems.

例如,它将TDs的所有文本内容用pre标记包装起来,并且没有问题。

jQuery("#resultTable td").content().wrap("<pre/>")

#11


0  

I had the same problem and solved it with:

我遇到了同样的问题,用:

Code:

代码:

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

Usage:

用法:

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

Is like next() but also returns the text nodes.

与next()类似,但也返回文本节点。