handris
handris

Reputation: 2109

Find distance between elements in the DOM

There is a root element in the DOM tree and there is another element inside this root element nested somewhere. How do I calculate how nested is this another element inside the root element?

What I would like to know is essentially how many times I have to get the parent element of the nested element until I get to the root element. So I can solve this problem by iterating on the parents until I get to the root element, like in this fiddle.

const first = document.getElementById('search-target-1');

let parent = first.parentElement;
let level = 0;
do {
  parent = parent.parentElement;
  level++;
}
while (!parent.classList.contains('root'))

console.log(`The first element is ${level} levels deep inside the root div.`);

const second = document.getElementById('search-target-2');

parent = second.parentElement;
level = 0;
do {
  parent = parent.parentElement;
  level++;
}
while (!parent.classList.contains('root'));

console.log(`The second element is ${level} level deep inside the root div.`);
<div class="root">
  <div class="first-level">
    <div class="second-level" id="search-target-1">
      <!-- How deep is this element? -->
    </div>
  </div>
  <div class="first-level"></div>
  <div class="first-level">
    <div class="second-level">
      <div class="third-level" id="search-target-2">
        <!-- And this one? -->
      </div>
    </div>
  </div>
</div>

Is there a better way of achieving this? I am looking for a javascript api to get the same result.

The element.matchesSelector does not solve my problem, as I know the target element is inside the root element, but I don't know how deep it is.

Upvotes: 2

Views: 1616

Answers (2)

Mark Lyons
Mark Lyons

Reputation: 1422

You could use jQuery's .parentsUntil() function to accomplish this:

var searchDistance_1 = $("#search-target-1").parentsUntil(".root").length; // 1
var searchDistance_2 = $("#search-target-2").parentsUntil(".root").length; // 2

That gives you the number of parents in between the child and root you are looking for. If you're looking for the number of jumps up the hierarchy needed to get to the parent, you can just add 1.

If you need to do this in vanilla JS, you could look through the source code for this function on GitHub.

Upvotes: 3

RobG
RobG

Reputation: 147383

Your code works, but as Niet the Dark Absol said you need to take care of cases where the descendent isn't a descendent, e.g.

function getLevel(parent, child) {
  let level = 0;
  while (child && parent != child) {
    level++;
    child = child.parentNode;
  }
  return child? level : null;
}

var parent = document.getElementById('parent');
var child = document.getElementById('child');
var notChild = document.getElementById('notChild');

console.log(getLevel(parent, child));     // 3
console.log(getLevel(parent, notChild));  // null
<div id="parent">
  <div>
    <div>
      <div id="child"></div>
    </div>
  </div>
</div>
<div id="notChild"></div>

Without the guarding condition to stop when the loop runs out of parnetNodes, it will throw an error if child isn't a descendant of parent.

Upvotes: 0

Related Questions