1

I have the following HTML markup:

<body>
   <div class="wrapper">
      <div class="head">
         <p class="title">title</p>
         <a href="#" class="logo"></a>
      </div>
   </div>
</body

I need to get something like the following - the "A" element with class "logo" is the seconde childNode of the div element with class "head". The div element with class "head" is the first childNode of the div element with class "wrapper", the div element with class "wrapper" is the first childNode of body. Then I would get the location of the link with class "logo" as follows:

var a = [1, 1, 2]

So, if I go in the opposite direction using the array above, I will find the link with class "logo" in the DOM starting from the body element. Could anybody tell me how can this be achieved with JavaScript?

Thanks in advance.

3
  • 2
    You should be aware that white space between element nodes in most implementations results in text nodes existing as additional child nodes e.g. in your sample the div class="head" has a text child node, an element child node, a text child node, an element child node and a text child node in most implementations. Attempting to index element nodes in the childNodes collection can therefore be more difficult than you currently think. These days however there is a children collection that only contains element child nodes, so depending on your needs you might consider to use that collection. Commented Nov 2, 2011 at 10:18
  • Thank you. Any examples? I just can't get how that can be counted. Commented Nov 2, 2011 at 10:43
  • 1
    @cycero you can't. You should avoid making assumptions about position in .childNodes based on HTML. Commented Nov 2, 2011 at 12:20

2 Answers 2

2

Here's a pair of functions adapted from some existing code of mine to turn a node into an array of nested positions within a node and back again.

Live demo: http://jsfiddle.net/DSNUv/

Code:

function getNodeIndex(node) {
    var i = 0;
    while( (node = node.previousSibling) ) {
        i++;
    }
    return i;
}

function nodeToPath(node, rootNode) {
    var path = [], n = node;
    rootNode = rootNode || document.documentElement;
    while (n && n != rootNode) {
        path.push(getNodeIndex(n));
        n = n.parentNode;
    }
    return path;
}

function pathToNode(path, rootNode) {
    rootNode = rootNode || document.documentElement;
    var node = rootNode;
    var i = path.length, nodeIndex;

    while (i--) {
        nodeIndex = path[i];
        if (nodeIndex < node.childNodes.length) {
            node = node.childNodes[nodeIndex];
        } else {
            throw new Error("Child node index out of range: " + nodeIndex);
        }
    }

    return node;
}

Example use:

var a = document.getElementsByTagName("a")[0];

var path = nodeToPath(a, document.body);
alert(path);

var el = pathToNode(path, document.body);
alert(el.className);
Sign up to request clarification or add additional context in comments.

Comments

1

Given the following HTML:

<body>
   <div class="wrapper">
      <div class="head">
         <p class="title">title</p>
         <a href="#" class="logo"></a>
      </div>
   </div>
</body

var el = document.body; // body
var div = document.body.firstChild; // div.wrapper
el === div.parentNode; // body === body
var div2 = div.firstElementChild; // div.head
div2.parentNode.parentNode === el; // body === body
var p = div2.firstElementChild; // p.title
var a = p.nextElementSibling; // a.logo
div2.children[1] === a; // a === a

I'm not quite sure what your trying to achieve. But I recommend you just walk the tree rather then construct relation ships in some kind of array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.