DOM Levels 2 and 3

Introduction

We covered DOM level 1 in the previous section now lets take a look at DOM Levels 2 and 3 which build on level1, which consist of the following

XML Namespaces

This allows elements from different XML based languages to be mixed together in a single well-formed document without fear of name clashes, levels 2 and 3 introduced the following properties and methods that can be used for namespaces

XML namespace examples
console.log(document.body.isDefaultNamespace("http://www.w3.org/1999/xhtml"));
console.log(svg.lookupPrefix("http://www.w3.org/2000/svg"));
console.log(svg.lookupNamespaceURI("s"));

There are also a number of properties and methods for changes to documents and changes to elements regarding namespaces such as createElementNS(), getAttributeNS, etc

Styles

DOM level 2 styles allows you to change styles within a document

Styles example
let myDiv = document.getElementById("myDiv");

// set the background color
myDiv.style.backgroundColor = "red";

// change the dimensions
myDiv.style.width = "100px";
myDiv.style.height = "200px";

// assign a border
myDiv.style.border = "1px solid black";

// retrieve a style
console.log(myDiv.style.backgroundColor);

There are also a number of properties and emthoids that can used such as cssText, length, getPropertyCSSValue(), getPropertyValue(), etc.

Traversals

DOM Levels 2 and 3 allow you to traverse the DOM at a starting point, you can then go in either direction, there are two types that allow you to do this NodeIterator and TreeWalker.

The NodeIterator has four arguments one of which is whatToShow which is a numerical code indicating which nodes should be visited, this argument has many possible values like SHOW_ALL, SHOW_ELEMENT, etc.

let filter = {
    acceptNode(node) {
        return node.tagName.toLowerCase() == "p" ?
        NodeFilter.FILTER_ACCEPT :
        NodeFilter.FILTER_SKIP;
    }
};

let iterator = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT, filter, false);

TreeWalker is a more advanced traversal walker than NodeIterator, it is very similar and had additional methods which makes it more advance

TreeWalker
var rootnode=document.getElementById("div1");

var walker=document.createTreeWalker(rootnode, NodeFilter.SHOW_ELEMENT, null, false);

// The starting node Tree Walker currently points to (root node)
console.log(walker.currentNode.tagName);             //DIV (with id=div1)

//Step through all the child nodes
while (walker.nextNode())
    console.log(walker.currentNode.tagName);

// Go back to the first child node of the collection
walker.currentNode=rootnode;                         //reset TreeWalker pointer to point to root node
console.log(walker.firstChild().tagName);

Ranges

A range can be used to select a asection within the document wothout any node boundaries, you create a range using the createRange() constructor, you can define a number of position ranges

You can get very complex with ranges as there are many methods likes selectNode, selectNodeContents, setStartBefore(), setStartAfter(), setEndBefore(), setEndAfter(), collapse() and many more, here are some examples

Simple Selection
// <p id="p1"><b>Hello</b> world!</p>

let range1 = document.createRange();
let range2 = document.createRange();

p1 = document.getElementById("p1");                // <p id="p1"><b>Hello</b> world!</p>

range1.selectNode(p1);
range2.selectNodeContents(p1);                     // <b>Hello</b> world! 
Complex example
let range1 = document.createRange(),
range2 = document.createRange(),
p1 = document.getElementById("p1"),
p1Index = -1,
i,
len;

for (i = 0, len = p1.parentNode.childNodes.length; i < len; i++) {
    if (p1.parentNode.childNodes[i] === p1) {
        p1Index = i;
        break;
    }
}

range1.setStart(p1.parentNode, p1Index);
range1.setEnd(p1.parentNode, p1Index + 1);
range2.setStart(p1, 0);
range2.setEnd(p1, p1.childNodes.length);