49

Best way to find out if element is a descendant of another there is another question, very similiar to this one but its jquery.

so, how do I do it in js ? I have divs a, b, c, d nested in this order. also, not sure if matters, there is another a, b, c... and another. its not just a single element. there is many by same id/class.

so I want to see if d has a parent(no matter how deep it is nested, as long as there is some parent on top its ok) called a.

edit: also, I had this idea that I could check childnodes of "a" and see if "d" is one of them, but couldnt implement it. if someone can get it working, itd be awesome.

Community
  • 1
  • 1
purplecircles
  • 553
  • 2
  • 6
  • 8

6 Answers6

119

You can use node.contains to check if a node contains another node. https://developer.mozilla.org/en-US/docs/Web/API/Node.contains

vsr
  • 3,138
  • 1
  • 19
  • 14
41

If you want to use pure javascript use node.contains.

e.g.

var a = document.getElementById('a');
var d = document.getElementById('d')
if (a.contains(d)) {
    alert('d is a descendant of a');
}

Fiddle: http://jsfiddle.net/FlameTrap/pwVPC/

Jay Wick
  • 12,325
  • 10
  • 54
  • 78
Josh
  • 2,835
  • 1
  • 21
  • 33
  • But this needs for the elements to be identified by 'id' - not by class. – Pedro Ferreira Mar 04 '16 at 18:51
  • @PedroFerreira you sure? It seems to be working with the elements that don't have any IDs as well. – ᴍᴇʜᴏᴠ Jul 08 '16 at 21:08
  • @The Sexiest Man in Jamaica: so how do you identify them? By class...(getElementsByClassName) ? Doesn't work. – Pedro Ferreira Jul 10 '16 at 02:27
  • @PedroFerreira I'm comparing an `onClick` target element with a `getElementsByTagName` array in a loop. It actually worked so I guess JavaScript has a way to identify elements without relying on classes and IDs. – ᴍᴇʜᴏᴠ Jul 10 '16 at 09:07
  • @The Sexiest Man in Jamaica that's right. What I was refering to is getting elements by CLASS - not unique. – Pedro Ferreira Jul 16 '16 at 14:32
  • 4
    @PedroFerreira This question isn't about how to get elements, just to check if one is a descendant of the other. The example code in this answer is just to show you what to do *after* you have gotten references to two elements. Feel free to use any method you like to get the references. `document.querySelectorAll`, or `getElementsById` or `getElementsByTagName`, or anything you like! – ErikE Feb 21 '17 at 03:37
  • @ErikE: I'm not talking about the question. This answer IS getting (unique) elements. – Pedro Ferreira Feb 22 '17 at 10:42
8

The method closest() might also be useful in such cases. This method returns the closest ancestor element of an element that matches a given selector (e.g. a class or id). If there is no such element, the method returns null.

let d = document.getElementById("d");
// if there is no ancestor with the id 'a', the method returns null and this evaluates to false:
if(d.closest("#a")){
   alert("d is a descendant of an element with the id 'a'");
}

You can find further description and more usage examples on MDN.

zunnzunn
  • 366
  • 1
  • 5
  • 12
5
// x is the element we are checking
while (x = x.parentNode) { 
    if (x.id == "a") console.log("FOUND");
}
Roy J
  • 42,522
  • 10
  • 78
  • 102
tohava
  • 5,344
  • 1
  • 25
  • 47
  • Thank you. Didn't know about the [parentElement](http://stackoverflow.com/questions/8685739/difference-between-dom-parentnode-and-parentelement#8685780). +1 – Stano Jul 21 '13 at 16:38
  • 3
    You should use parentNode instead of parentElement. parentElement is an old Internet Explorer thing that is no longer supported. – BrianK Apr 28 '16 at 07:16
  • 12
    better to use `node.contains` (see answer below) – mb21 Feb 16 '17 at 15:07
  • @mb21 It is not checking deeply. – atilkan Dec 05 '19 at 08:43
  • @atilkan from MDN: "indicating whether a node is a descendant of a given node, i.e. the node itself, one of its direct children (childNodes), one of the children's direct children, and so on." – mb21 Dec 05 '19 at 16:20
  • @mb21 It says direct children. Not if children's children or grandchild. – atilkan Dec 05 '19 at 17:44
  • @atilkan I just tried it and node.contains will check deeply. a > b > c a.contains(c) is true. – Tomáš Hübelbauer Jul 12 '20 at 06:56
  • @mb21 Can you share the example, please? – atilkan Jul 12 '20 at 22:41
  • @BrianK You're thinking of the old (**old!**) `parentElement` property from IE5 (1999) whereas [the modern `parentElement` has been part of the W3C/WHATWG standard DOM since around 2008](https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement) – Dai Oct 02 '20 at 13:15
0

edit: also, I had this idea that I could check childnodes of "a" and see if "d" is one of them, but couldnt implement it. if someone can get it working, itd be awesome.

For each ancestor, call querySelector, querySelectorAll, getElementsByClassName and so on.

let ancestors = document.querySelectorAll('ancestor a');
for(let i = 0; i < ancestors.length; i++){
    let a = ancestors[i];
    if(a.querySelector('descendant d')) {
        console.log(a);
    }
}

Or

let ancestors = document.querySelectorAll('ancestor a');
for(let i = 0; i < ancestors.length; i++){
    let a = ancestors[i];
    let descendants = a.querySelectorAll('descendant d');
    if(descendants.length > 0) {
        console.log(a);
    }
}
happynow
  • 11
  • 1
0

Here is another one. Oh this is the old-fashioned way. It works but do not use. Use the contains() method of html nodes instead.

function isDescendentOf(element, parent) {
  while (element) {
    if (element === parent) {
      return true;
    }
    element = element.parentElement;
  }
  return false;
}
shrekuu
  • 1,716
  • 1
  • 23
  • 38