JS: Compare Document Position

I’ve been doing some fairly intense work with a responsive “parallax”* scrolling homepage, including IE8, iOS and mobile support. Being easily able to get your head round positioning and animation relative to document top vs. viewport is very handy.

 

Most of the heavy lifting had been done already thanks to a pretty-damn cool plugin – though it had it’s limitations. More on the plugin and my hacks to make it properly responsive and inherit between breakpoints later.

 

This preamble really is just to explain why I was interested to spot this from Web Tools Weekly:

 

There’s a somewhat complex but useful DOM method called compareDocumentPosition() that lets you compare the position of a specific node in a document with the position of another node.

 

Suppose we have the following HTML:

 

Assuming these elements are inside a regular HTML page, we can run the following checks usingcompareDocumentPosition():

(Demo) As you can see, the compareDocumentPosition() method is called on one node and then another node is passed in as the only argument. The return is compared to an integer, which is actually something called a bitmask. A bitmask, as explained by John Resig is “a way of storing multiple points of data within a single number”.

In that example, I’m testing the position of the “one” element in comparison to the “two” element, but I’m also checking the position of the head element in comparison to the body. This can be done with any elements, these are just examples.

The possible return values for this method are shown in the list below, with the numbers representing the values you’d test against:

  • Node.DOCUMENT_POSITION_DISCONNECTED: 1
  • Node.DOCUMENT_POSITION_PRECEDING: 2
  • Node.DOCUMENT_POSITION_FOLLOWING: 4
  • Node.DOCUMENT_POSITION_CONTAINS: 8
  • Node.DOCUMENT_POSITION_CONTAINED_BY: 16
  • Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 32

You’ll notice in the code example above, I checked for a value of “20”, which is not in the list above. This is because a node that contains another node also precedes that node, so it gets a value of 16 + 4 (a combination of two of the above).

It’s kind of bizarre, to be honest, but to fully understand this method, you just have to fiddle around with the values and do a number of different tests. I think this method could come in handy if you want to check if some user-generated or dynamically-generated HTML is well-formed, or if it complies with some set of standards. This is an old method, so browsers support seems to be full, including old IE.

More info:

* “Parallax” my arse… Almost nothing people call parallax actually is. And, more annoyingly, they don’t like being told this.