Mozilla

DOM Traversal in Firefox 3.5

Firefox 3.5 includes new support for two W3C DOM traversal specifications. The first, the Element Traversal API, focuses on making element-by-element traversal easier, the second, the NodeIterator interface which makes finding all node types much easier.

Element Traversal API

The purpose of the Element Traversal API is to make it easier for developers to traverse through DOM elements without having to worry about intermediary text nodes, comment nodes, etc. This has long been a bane of web developers, in particular, with cases like document.documentElement.firstChild yielding different results depending on the whitespace structure of a document.

The Element Traversal API introduces a number of new DOM node properties which can make this traversing much simpler.

Here’s a full break-down of the existing DOM node properties and their new counterparts:

Purpose All DOM Nodes Just DOM Elements
First .firstChild .firstElementChild
Last .lastChild .lastElementChild
Previous .previousSibling .previousElementSibling
Next .nextSibling .nextElementSibling
Length .childNodes.length .childElementCount

These properties provide a fairly simple addition to the DOM specification (and, honestly, they’re something that should’ve been in the specification to begin with).

There is one property that is conspicuously absent, though: .childElements (as a counterpart to .childNodes). This property (which contained a live NodeSet of the child elements of the DOM element) was in previous iterations of the specification but it seems to have gone on the cutting room floor at some point in the interim.

But all is not lost. Right now Internet Explorer, Opera, and Safari all support a .children property which provides a super-set of the functionality that was supposed to have been made possible by .childElements. When support for the Element Traversal API was finally landed for Firefox 3.5, support for .children was included. This means that every major browser now supports this property (far in advance of all browsers supporting the rest of the true Element Traversal specification).

Some examples of the Element Traversal API (and .children) in action:

Show next element when a click occurs:

someElement.addEventListener("click", function(){
    this.nextSiblingElement.style.display = "block";
}, false);

Add classes to all of the child elements:

for ( var i = 0; i < someElement.children.length; i++ ) {
    someElement.children[ i ].className = "active";
}

NodeIterator API

NodeIterator is a relatively old API that hasn’t seen wide adoption, and has just been implemented in Firefox 3.5. Specifically, the NodeIterator API is designed to allow for easy traversal of all nodes in a DOM document (this includes text nodes, comments, etc.).

The API itself is rather convoluted (containing a number of features that aren’t immediately important to most developers) but if you wish to use it for some simpler tasks it be quite easy.

The API works by creating a NodeIterator (using document.createNodeIterator) and passing in a series of filters. The NodeIterator is capable of returning all nodes in a document (or within the context of a given node) thus you’ll want to filter it down to only show the ones that you desire. A simple example of this can be found below.

Construct a NodeIterator for iterating through all the comment nodes in a document.

var nodeIterator = document.createNodeIterator(
    document,
    NodeFilter.SHOW_COMMENT,
    null,
    false
);
 
var node;
 
while ( (node = nodeIterator.nextNode()) ) {
    node.parentNode.removeChild( node );
}

Once constructed the NodeIterator is bi-directional (you can move in any direction, using previousNode or nextNode).

Perhaps the best use of the API is in traversing over commonly-used (but difficult to traverse) nodes like comments and text nodes. Since there already exist a few APIs for traversing DOM elements (such as getElementsByTagName) this does come as a welcomed respite to the normal means of node traversal.

12 comments

Comments are now closed.

  1. steve wrote on June 19th, 2009 at 07:36:

    I thought that the document.all collection in IE wasn’t a live collection? e.g. when I add new elements to the DOM (after page load) with id/name attributes they aren’t necessarily added to the collection.

    Or am I missing something with regards to how IE is being handled before fully supporting this?

  2. Horia Dragomir wrote on June 19th, 2009 at 07:38:

    I remember these issues with Nodes vs. Elements used to be a great pain back before the great frameworks rules the internet. Oh, I remember them well…

    Aside from the comfort that comes with this enhancement, I’m guessing there might be an increase in speed and dependability too, right?

    Let’s just see how fast the other browsers implement this.

  3. steve wrote on June 19th, 2009 at 07:38:

    yikes! ignore me… I somehow read that all wrong… pulling in the word “all” from elsewhere in the sentence… oh Internet Eraser.. where are you when I need you!

  4. Gilberto Ramos wrote on June 19th, 2009 at 07:43:

    looks very useful!

  5. Pingback from John Resig - Unimpressed by NodeIterator on June 19th, 2009 at 08:53:

    […] just posted a run down of some of the new DOM Traversal APIs in Firefox 3.5. The first half of the post is mostly a recap of my old Element Traversal API […]

  6. Elijah Grey wrote on June 19th, 2009 at 09:05:

    Should the document type only have a .nextSibling property and not a .nextElementSibling property?

    document.firstChild.nextSibling === document.documentElement and document.firstChild.nextElementSibling === undefined for me.

  7. Илья Казначеев wrote on June 19th, 2009 at 09:16:

    “This has long been a bane of web developers” until there were Prototype, and now it’s down().
    Why bother bloating DOM when it’s already figured out?

  8. Pingback from Ajaxian » NodeIterator.areYou(IMPRESSED | WHOCARES | WHA?) on June 19th, 2009 at 12:05:

    […] Resig has posted on the DOM traversal methods now in Firefox 3.5 and then a spin out post on the merits of the NodeIterator API. He isn’t impressed: This API is, […]

  9. Erik wrote on June 20th, 2009 at 03:07:

    In the list of API functions you call a function ‘nextElementSibling’, but in the example it is ‘nextSiblingElement’. Which one is correct?

  10. Pingback from 颠覆网络35天 ─ Firefox 3.5中的DOM遍历 < MJiA on June 22nd, 2009 at 00:41:

    […] 原文地址:DOM Traversal in Firefox 3.5 系列地址:颠覆网络35天 […]

  11. MJiA wrote on June 22nd, 2009 at 01:13:

    Should “this.nextSiblingElement.style.display = “block”;” in first code snippet be “this.nextElementSibling.style.display = “block”;
    “?

  12. Pingback from Mozilla Hacks: Przechodzenie po drzewie DOM w Firefoksie 3.5 « marcoos.techblog on July 29th, 2009 at 04:32:

    […] serii tłumaczeń artykułów z bloga Mozilla Hacks, przedstawiam dzisiaj tłumaczenie artykułu DOM Traversal in Firefox 3.5 autorstwa Johna Resiga (znanego m. in. jako twórca biblioteki […]

Comments are closed for this article.