How to use jQuery to select text nodes?

I want to get all the descendent text nodes of an element as a jQuery collection. What's the best way?

#1 building

You can also do this:

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

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

#2 building

For me, normal old-fashioned. contents() seems to return text nodes, just be careful with selectors so you know they will be text nodes.

For example, this wraps all the text content of TD in my table with the pre tag, no problem.

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

#3 building

jQuery.contents() May and jQuery.filter Use together to find all child text nodes. With a few changes, you can find the grandchildren text node. No recursion required:

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

#4 building

For some reason, contents() doesn't work for me, so if it doesn't work for you, it's a solution I've made, and I created jQuery.fn.descendants to choose whether to include text nodes or not

usage

Get all descendants, including text and element nodes

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

Get the descendants of all text only nodes

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

Get all the descendants of the returned element nodes only

jQuery('body').descendants();

Coffee script Original:

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)

Insert Javascript version

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

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

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

#5 building

I got a lot of blank text nodes with acceptable filter capabilities. If you are only interested in selecting text nodes that contain non spaces, try adding the nodeValue of the conditional condition to the filter function, such as the simple $. trim(this.nodevalue)! = = '':

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

http://jsfiddle.net/ptp6m97v/

Or, to avoid strange situations where the content looks blank but is not blank (for example, soft hyphen & shy; characters, line breaks \ \ n, tabs, etc.), you can try using regular expressions. For example, \ \ S will match any non white space characters:

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

Tags: JQuery Javascript

Posted on Thu, 13 Feb 2020 00:57:42 -0500 by realjumper