Getting the coordination of a node in DOM.

This is a function that takes a DOM node, and returns the offset of that node. What’s the “offset” ? It’s the ordinal number in its siblings, the number “n” of node.parentNode.childNodes[n]. Sadly there’s no easy way to do this with DOM API, basically it’s just iterating over all its siblings and keep counting.

getNodeOffset = function(node) {
    var p = node.parentNode;
    if (p == null) return;
    for (var i = 0, l = p.childNodes.length; i < l ; i++ ) {
        if (p.childNodes[i] == node) break;+    }
    return i;
}

Here’s one other interesting function, I called it “getNodeCoordination”. Since each node must have a parent node, it can always be traced all the way up to document.body. This forms a simple coordination system. You can use a list of numbers like:

[3,0,0,1]

To uniquely locate a node. The example above can be translated into this horrible English: “The 1st child of the 0th child of the 0th child of the 3rd child of document.body”. Or this elegant XPath representation:

//body/*[4]/*[1]/*[1]/*[2]

Those numbers are offset by one for obvious reason. Here’s the code of that “getNodeCoordation” function.

getNodeCoordination = function(node, baseNode) {
    if (baseNode == null) baseNode = window.document.body;
    var coord = [];
    var p = node;
    while (p != baseNode) {
        var offset = getNodeOffset(p);
        if (offset == null) break;
        coord.unshift(offset);
        p = p.parentNode;
    }
    if (p != baseNode) return null;
    return coord;
}

Obviously the return value is very fragile against DOM change. Any DOM modification can invalid a previously stored coordination value. However, If you ever need to bookmark the location of a node and serialize it for storage, this is one approach.


About this entry