Paul Browne
Paul Browne

Reputation: 787

Return an array of all the DOM elements, sorted by depth

In Javascript How do you create an Array of all the elements in the DOM, ordered by their depth, so it something like this...

<body>
  <1stChild>
    <1stGrandchild>
  <2ndChild>
  <3rdChild>
    <2ndGrandchild>
    <3rdGrandchild>
      <1stGreatgrandchild>
      <2stGreatgrandchild>
    <4thGrandchild>
  <4thChild>
  <etc etc>

would look like this...

["body", "1stChild", "2ndChild", "...", "lastChild", "1stGrandchild", "...", "lastGrandchild", "1stGreatgrandchild", "...", "lastGreatgrandchild" "etc. etc."]

I have a jQuery solution but would like a pure javascript one

Upvotes: 0

Views: 263

Answers (2)

Paul Browne
Paul Browne

Reputation: 787

Ok, I figured it out myself, it was pretty simple in the end.

    // Every Element in the DOM.

var allElements = document.getElementsByTagName('*'),

    // All the Element's children sorted by depth, 
    // ie. body, then body's children, grandchildren,
    // so on and so forth.

    sortedByDepth = [];

    // for every element

for(var i = 0; i<allElements.length; ++i) {

    // grab Its children

    var allChildren = allElements[i].children;

    // for every grabbed child

    for(var j = 0; j<allChildren.length; ++j){

        // Add it to the sortedByDepth array

        sortedByDepth = sortedByDepth.concat(allChildren[j]);
    }   
}
console.log(sortedByDepth);

Upvotes: 0

jdphenix
jdphenix

Reputation: 15445

This modifies Crockford's walkTheDOM() to accomplish what you're needing.

var output = [], 
    currentCount = 0, 
    depth = 0;

function walkTheDOM(node, func) {
    currentCount++;
    depth++;
    func(node);
    node = node.firstChild;
    while (node) {
        walkTheDOM(node, func);
        node = node.nextSibling;
    }
    depth--;
}

function getDepths(node) { 
    if (node.nodeType !== 3) {
        output.push ({ 
            node: node, 
            depth: depth, 
            encountered: currentCount
        }); 
    }
}

walkTheDOM(document.body, getDepths); 

output.sort(function(a, b) { 
    return a.depth === b.depth ? 
        a.encountered - b.encountered : 
        a.depth - b.depth; 
}); 

console.log(output);
<div class="first">
  <div class="second">
    <div class="third"></div>
    <div class="fourth">
      <div class="fifth"></div>
    </div>
  </div>
  <div class="sixth"></div>
  <div class="seventh">
    <div class="eighth"></div>
  </div>
  <div class="ninth"></div>
</div>
<div class="tenth"></div>

Upvotes: 1

Related Questions