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
    JavaScript Promise API

    While synchronous code is easier to follow and debug, async is generally better for performance and flexibility. Why "hold up the show" when you can trigger numerous requests at once and then handle them when each is ready?  Promises are becoming a big part of the JavaScript world...

  • By
    Creating Scrolling Parallax Effects with CSS

    Introduction For quite a long time now websites with the so called "parallax" effect have been really popular. In case you have not heard of this effect, it basically includes different layers of images that are moving in different directions or with different speed. This leads to a...

Incredible Demos

  • By
    Select Dropdowns, MooTools, and CSS Print

    I know I've harped on this over and over again but it's important to enhance pages for print. You can do some things using simple CSS but today's post features MooTools and jQuery. We'll be taking the options of a SELECT element and generating...

  • By
    Web Audio API

    The Web Audio API allows developers to load and decode audio on demand using JavaScript.  The more I evaluate awesome games for Firefox OS TVs, the more I get to learn about these APIs that I normally wouldn't touch.  The following is a very basic introduction to the WebAudio API...

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!