Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `childNodes` return a number larger than I expect?

Could you please look at this jsFiddle example, and tell me why the number '11' is alerted rather than '5' (the number of <li> elements)?

From jsFiddle:

HTML

<ul id="list">
    <li>milk</li>
    <li>butter</li>
    <li>eggs</li>
    <li>orange juice</li>
    <li>bananas</li>
</ul>

JavaScript

var list = document.getElementById('list');
var list_items = list.childNodes;
alert(list_items.length);
like image 786
Web_Designer Avatar asked Aug 16 '11 00:08

Web_Designer


2 Answers

The childNodes, depending on the browser used, will return the text nodes, as well as the tags that are children of the parent node. So technically, the whitespace in between the <li> tags will also be counted among the childNodes.

To avoid processing them, you may check that nodeType != 3. Here is a list of node types.

var list = document.getElementById('list');
var list_items = list.childNodes;
var li_items = [];
for (var i=0; i<list_items.length; i++) {
  console.log(list_items[i].nodeType);

  // Add all the <li> nodes to an array, skip the text nodes
  if (list_items[i].nodeType != 3) {
    li_items.push(list_items[i]);
  }
}
like image 52
Michael Berkowski Avatar answered Oct 19 '22 10:10

Michael Berkowski


You have text nodes there.

You can skip them while iterating with...

for (var i = 0, length = list_items.length; i < length; i++) {
    if (list_items[i].nodeType != 1) {
        continue;
    }
    // Any code here that accesses list_items[i] will sure to be an element.
}

jsFiddle.

Alternatively, you could do it in a more functional way...

list_items = Array.prototype.filter.call(list_items, function(element) { 
                 return element.nodeType == 1;
             });

jsFiddle.

You must use convert it to a proper array to use the filter() method. childNodes property returns a NodeList object.

like image 38
alex Avatar answered Oct 19 '22 08:10

alex