Node.contains: Check if a Node is a Child of Another Node

By  on  

There are loads of basic, native JavaScript methods that many developers don't know about.  Many people don't know about the Element.classList API, for example, so className management becomes another case for needing a JavaScript toolkit for even the most basic tasks.  Another case is checking for node parenting -- developers believe it requires a toolkit or a loop checking parentNode up the chain;  no so!  Nodes provide a contains method to check if one node if a parent of another:

function(parentNode, childNode) {
	if('contains' in parentNode) {
		return parentNode.contains(childNode);
	}
	else {
		return parentNode.compareDocumentPosition(childNode) % 16;
	}
}

You'll note we check for the contains method before using it, as you would probably expect, and use the rarely-known compareDocumentPosition in the case that contains isn't supported (Firefox < 9).  This method would be helpful when creating a drag & drop widget and determining moves between lists.  Anyways, before you jump to the conclusion that you need a toolkit for something that seems basic, do some quick research and hopefully you find an easier way!

Recent Features

  • By
    Interview with a Pornhub Web Developer

    Regardless of your stance on pornography, it would be impossible to deny the massive impact the adult website industry has had on pushing the web forward. From pushing the browser's video limits to pushing ads through WebSocket so ad blockers don't detect them, you have...

  • By
    CSS vs. JS Animation: Which is Faster?

    How is it possible that JavaScript-based animation has secretly always been as fast — or faster — than CSS transitions? And, how is it possible that Adobe and Google consistently release media-rich mobile sites that rival the performance of native apps? This article serves as a point-by-point...

Incredible Demos

  • By
    MooTools Window Object Dumping

    Ever want to see all of the information stored within the window property of your browser? Here's your chance. The XHTML We need a wrapper DIV that we'll consider a console. The CSS I like making this look like a command-line console. The MooTools JavaScript Depending on what you have loaded...

  • By
    Create a Spinning, Zooming Effect with CSS3

    In case you weren't aware, CSS animations are awesome.  They're smooth, less taxing than JavaScript, and are the future of node animation within browsers.  Dojo's mobile solution, dojox.mobile, uses CSS animations instead of JavaScript to lighten the application's JavaScript footprint.  One of my favorite effects...

Discussion

  1. MaxArt

    I’m not sure this works. Shouldn’t the function always return a boolean?

    If I compare an element with one of its children, with compareDocumentPosition I get 4. If I compare an element with its parent, I get 2.

    That’s how I used to polyfill the function:

    // 16 === Node.DOCUMENT_POSITION_CONTAINED_BY
    Node.prototype.contains = function(node) {
        return (this.compareDocumentPosition(node) & 16) !== 0 || this === node;
    }
    
    • Nick Williams

      You’re right, compareDocumentPosition returns a bitmask, so it can represent multiple values at once. e.g.

      var parent = document.createElement("div");
      var child = document.createElement("div");
      parent.appendChild(child);
      
      // as the article has it
      parent.compareDocumentPosition(child) % 8; // 4, truthy
      child.compareDocumentPosition(parent) % 8; // 2, truthy
      
      // how it should be
      parent.compareDocumentPosition(child) & 16; // 16, truthy
      child.compareDocumentPosition(parent) & 16; // 0, falsy
      

      John Resig’s article covers this in detail: http://ejohn.org/blog/comparing-document-position/

    • Updated, thank you!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!