Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate through HTML DOM and get depth

How is it possible to iterate through the HTML DOM and list all nodes with there depth in javascript.

Example:

<div>
    <img src="foo.jpg">
    <p>
        <span>bar</span>
    </p>
</div>

would result in

  • div 0
  • img 1
  • p 1
  • span 2
like image 801
Ka Rl Avatar asked Nov 24 '15 21:11

Ka Rl


People also ask

How do I iterate through a DOM element?

To loop through all DOM elements: Use the getElementsByTagName() method to get an HTMLCollection containing all DOM elements. Use a for...of loop to iterate over the collection.

How do you get an array of all the DOM elements with a certain selector?

To get all DOM elements by an attribute, use the querySelectorAll method, e.g. document. querySelectorAll('[class="box"]') . The querySelectorAll method returns a NodeList containing the elements that match the specified selector.

What is the fastest way to query DOM?

getElementById is the fastest.

How do you traverse through DOM?

We can also traverse up the DOM tree, using the parentNode property. while (node = node. parentNode) DoSomething(node); This will traverse the DOM tree until it reaches the root element, when the parentNode property becomes null.


2 Answers

Write a recursive function which tracks the depth:

function element_list(el,depth) {
    console.log(el+' '+depth);
    for(var i=0; i<el.children.length; i++) {
        element_list(el.children[i],depth+1);
    }
}
element_list(document,0);

As CodeiSir points out, this will also list text nodes, but we can filter them out by testing the nodeType. Variations on this code will allow/ignore other node types as desired.

function element_list(el,depth) {
   if (el.nodeType === 3) return;
like image 193
Blazemonger Avatar answered Sep 22 '22 05:09

Blazemonger


Yes, you can! You would have to iterate and some logic to create this tree, but for your example, you could do something like:

var tracker = {};
Array.from(document.querySelectorAll("*")).forEach(node => {
    if (!tracker[node.tagName]) tracker[node.tagName] = 1;
    else tracker[node.tagName]++;
});
console.log(tracker);

You can modify this to run on a recrusive subset of childNodes. This just iterates the entire document.

Check this fiddle and open the console to see the output of tracker which counts and lists tag names. To add the depth, just grab the parentNode.length all the way up.

Here's an updated script which I think does the depth count propery;

var tracker = {};
var depth = 0;
var prevNode;
Array.from(document.querySelectorAll("*")).forEach(node => {
    if (!tracker[node.tagName]) tracker[node.tagName] = 1;
    else tracker[node.tagName]++;
    console.log("Node depth:", node.tagName, depth);
    if (node.parentNode != prevNode) depth++;
    prevNode = node;
});
console.log(tracker);
like image 40
Sterling Archer Avatar answered Sep 24 '22 05:09

Sterling Archer