The DOM (Document Object Model) Tree
Traversal, parents, siblings, and children
The DOM (Document Object Model) is a tree-like structure model of the page that is created by the browser when a web page is loaded. It’s a W3C (World Wide Web Consortium) standard that defines a standard for accessing documents:
The W3C Document Object Model (DOM) is a platform and language-neutral interface that allows programs and scripts to dynamically access and update the content, structure, and style of a document.
The W3C DOM standard is separated into 3 different parts:
- Core DOM - standard model for all document types
- XML DOM - standard model for XML documents
- HTML DOM - standard model for HTML documents
The HTML DOM model is constructed as a tree of Objects, where the document node is at the root of the tree. It allows JavaScript to create dynamic HTML so that it can:
- Change the HTML elements & attributes in the page
- Change the CSS styles in the page
- Add / remove existing HTML elements and attributes
- React to existing HTML events in the page
- Create new HTML events in the page
<html>
<body>
<h1> Heading 1</h1>
<p> Paragraph </p>
<h2> Heading 2 </h2>
<p> Paragraph 2 </p>
</body>
</html>
Walking the DOM
A neat aspect to the HTML DOM tree is that it follows the structure of a classic binary tree. So in terms of traversing the DOM, this means that we have at our disposal all of the traversal methods (pre, in, and post-order) that come with BSTs.
What’s more is that it means we can use a function that allows us to ‘walk’ the DOM recursively; to go through the tree and visit all the nodes in order, and do 'something useful' (i.e. apply a function to) at each node visited.
This function was created by Douglas Crockford:
var domTraversal = function(node, func) {
func(node);
node = node.firstChild;
while (node) {
domTraversal(node, func);
node = node.nextSibling;
}
};
The first step is to call the function on the root node. Then, look to see if the node has a firstChild. If it does, call the function recursively on that node. When the result of this call comes back, then look to see if it has a nextSibling. Keep doing this process until the whole tree has been walked through.
getElementsByClassName
Let's look at an example where this might be practically useful. The getElementsByClassName function is a really useful function because it allows us to identify tags in a document’s class and do something on all of them.
function getElementsByClassName(className) {
var elements = [];
domTraversal(document.documentElement, function(node) {
if ($(node).hasClass(className)){
elements.push(node);
}
});
return elements;
}
Stepping through this implementation of the function, first we declare an array in which to store the elements. Then, call the domTraversal function with the document.documentElement property - remember, this is the root element of the document and the node at which we'd logically want to start traversing the tree from. We also pass in a a function that checks whether the node has the className provided using jQuery .hasClass(). If it does, simply push it onto the elements array. Finally, return the elements.