DOM Nodes

The Document Object Model (DOM) is a model for HTML documents that represents the document as a tree of nodes containing elements, attributes and content.  The DOM is completely cross-browser compatible.

Node Relationships

Human family relationship names are used to describe relationships between nodes in the DOM.  For example, we say the <head> and the <body> elements are children of the <html> element and that the <html> element is the parent of the <head> and <body> elements.

Each node has read-only properties (given below) that allow access to various other nodes that have a relationship to it.

  • ownerDocument
  • parentNode
  • previousSibling
  • nextSibling
  • childNodes
  • firstChild
  • lastChild

The relationships for these properties is illustrated in the diagram below.

Each of these properties holds either null, a reference to another node in the tree or in the case of childNodes, a reference to a NodeList containing references to nodes.  The properties ownerDocument, parentNode, previousSibling, nextSibling, firstChild, and lastChild may be null.  The ownerDocument property points to the document’s root node and is null for the root node.

The childNodes property contains a (possibly empty) NodeList object. A NodeList is an ordered list whose elements are accessible by position in the same way elements in an array are accessible.  A NodeList object also has a length property which can be used to determine the number of children that a node has.

var node = ...

var len = node.childNodes.length;            
for (var i = 0; i < len; i++) {
    var child = node.childNodes[i];
    ...
}

The hasChildNodes() method returns true if childNodes.length > 0, false otherwise.

Node Properties

The DOM contains ALL of the information necessary to render a web page.  With JavaScript, we can inspect the DOM and manipulate the DOM causing the page to change without being reloaded.

To see the plethora of information stored in the DOM run the JavaScript shown below in a simple web page.  Try it on jsbin.com.  The window.document property holds the root node of the DOM tree. The function named recursivePrintChild() traverses the entire tree and prints out all of the information stored in each node of the tree.

var doc = window.document;
recursivePrintChild(doc);

function recursivePrintChild(node) {
    var len = node.childNodes.length;
    for (let i = 0; i < len; i++) {
        console.log(node.childNodes[i]);
        recursivePrintChild(node.childNodes[i]);
    }
}

nodeType, nodeName, and nodeValue

Each node in the DOM is an object and has a type; each type having its own properties and methods.  All node types inherit from the Node type, which defines a set of methods that all types must implement.

Every node has a nodeType property that holds a Number to indicate the type of node that it is.

  • ELEMENT_NODE (1)                                        <html><head><body>…
  • ATTRIBUTE_NODE (2)
  • TEXT_NODE (3)                                                    “hello world”
  • CDATA_SECTION_NODE (4)
  • ENTITY_REFERENCE_NODE (5)
  • ENTITY_NODE (6)
  • PROCESSING_INSTRUCTION_NODE (7)
  • COMMENT_NODE (8)
  • DOCUMENT_NODE (9)                                       window.document
  • DOCUMENT_TYPE_NODE (10)                         <!DOCTYPE html>
  • DOCUMENT_FRAGMENT_NODE (11)
  • NOTATION_NODE (12)

Each node also has a nodeName and nodeValue property.  Their semantics of these properties depend on the node’s type.  For element nodes, the nodeName is equivalent to the tag name of the element.  For text node, the nodeName is “#text”.

Below is script code that prints the nodeType and nodeName for each node in the tree.  As it traverses the DOM it adds tabs to the beginning of the output string so you see the hierarchy of the tree.

var doc = window.document; 
recursivePrintChild(doc, 0); 

function recursivePrintChild(node, level) { 
    var len = node.childNodes.length; 
    for (let i = 0; i < len; i++) {
        var type =node.childNodes[i].nodeType;
        var name = node.childNodes[i].nodeName;
        var prefix = '';
        for (let j = 0; j < level; j++) {
            prefix += '\t\t';
        }
        console.log(prefix + "(" + type + ") " + name); 
        recursivePrintChild(node.childNodes[i], level + 1); 
    } 
}

When you run the script you see that most of the nodes in the tree are element and text nodes. Which makes sense.  But there seems to be extra text nodes where no text appears in the HTML.  Well actually, the text is there, in the form of whitespace (spaces, tabs, and new line characters).  Any whitespace between HTML elements will be represented in the DOM as a #text nodes.  If you delete the whitespace from the HTML the number of DOM nodes is lessened considerably.

When we print the nodeValue property for each element, we see that the entire document’s HTML, CSS, and JavaScript text is stored in the DOM.  Below is a script that will show you the text stored in the DOM.

var doc = window.document; 
recursivePrintChild(doc);

function recursivePrintChild(node) { 
    var len = node.childNodes.length; 
    for (let i = 0; i < len; i++) {
        var name = node.childNodes[i].nodeName;
        var value = node.childNodes[i].nodeValue;
        console.log("(" + name + ")" + value); 
        recursivePrintChild(node.childNodes[i]); 
    }
}

When running the script we see that the only nodes with that have a non-null nodeValue property are text nodes.