Devima
Devima

Reputation: 1566

Get text of nested childnodes javascript

Although I have read many posts on this subject, I am unable to get the desired result.
My goal is to get text of nested childnodes in pure JavaScript. with this code

function GetChildNodes () {
    var container = document.getElementById ("find");
    for (var i = 0; i < container.childNodes.length; i++) {
        var child = container.childNodes[i];
        if (child.nodeType == 3) {
           var str=child.nodeValue
           console.log(str)
        }
        else {
            if (child.nodeType == 1) {
                var str=child.childNodes[0].nodeValue
                console.log(str)                        
            }
        }
    }
}

GetChildNodes()

I can get the text if html is

<div id="find">
    aaa
    <div>aaa</div>
    <div>aaa</div>
    <div>aaa</div>
    <div>aaa</div>
</div>

But with html code like this

<div id="find">
    aaa
    <div>aaa<div>bbb</div></div>
    <div>aaa<div>bbb</div></div>
    <div>aaa</div>
    <div>aaa</div>
</div>

...is wrong.
Could you please give me a solution?

Upvotes: 5

Views: 8791

Answers (4)

milahu
milahu

Reputation: 3529

a short version of Paul's answer

function getText(node) {
  if (node.nodeType == 3) return node.data; // text node
  if (!node.childNodes) return '';
  let s = '';
  for (let i = 0; i < node.childNodes.length; i++) {
    s += getText(node.childNodes[i]);
  }
  return s;
}

Upvotes: 0

Devima
Devima

Reputation: 1566

Since my purpose was also to change the text in nested elements if the text is equal to a string,
thanks to the advice of Paul S I could solve my problem this way

<script type="text/javascript">
function GetChildNodes (container) {
    function recursor(container){
            for (var i = 0; i < container.childNodes.length; i++) {
                var child = container.childNodes[i];
                if(child.nodeType !== 3&&child.childNodes){
                    recursor(child);
                }else{
                    var str=child.nodeValue;
                    if(str.indexOf('bbb')>-1){child.nodeValue='some other text'};
                    };
             };
    };
    recursor(container);
};
var container = document.getElementById ("find");
GetChildNodes(container);
</script>

Thanks again Paul !

Upvotes: 2

Paul S.
Paul S.

Reputation: 66304

If you don't need to get the text node-by-node you can get all of it from the ancestor with node.textContent,

var str = document.getElementById('find').textContent;
console.log(str);

Otherwise, you'll need to iterate or recurse through the DOM tree looking for nodeType 3 and accessing .data or .childNodes otherwise, e.g. recursing

function getText(node) {
    function recursor(n) {
        var i, a = [];
        if (n.nodeType !== 3) {
            if (n.childNodes)
                 for (i = 0; i < n.childNodes.length; ++i)
                     a = a.concat(recursor(n.childNodes[i]));
        } else
            a.push(n.data);
        return a;
    }
    return recursor(node);
}
// then
console.log(getText(document.getElementById('find')));

Upvotes: 6

Amit Joki
Amit Joki

Reputation: 59232

It is because you're checking only for the childNodes of find, and not the childnodes of the childnodes and it goes on.

There is not limit of number of childs an element can have, and so you should have a for loop every time or a recursive function.

Why don't you just do: document.getElementById('find').textContent; ?

Upvotes: 0

Related Questions