views:

49

answers:

3

Say I've selected a span tag in a large html document. If I treat the entire html document as a big nested array, I can find the position of the span tag through array indexes. How can I output the index path to that span tag? eg: 1,2,0,12,7 using JavaScript.

Also, how can I select the span tag by going through the index path?

A: 

Using jquery:

var tag = $('#myspan_id');
var index_path = [];
while(tag) {
  index_path.push(tag.index());
  tag = tag.parent();
}
index_path = index_path.reverse();
gustavogb
A: 

Using the DOM

node = /*Your span element*/;
var currentNode = node;
var branch = [];
var cn; /*Stores a Nodelist of the current parent node's children*/
var i;
while (currentNode.parentNode !== null)
    {
    cn = currentNode.parentNode.childNodes;
    for (i=0;i<cn.length;i++)
        {
        if (cn[i] === currentNode)
            {
            branch.push(i);
            break;
            }
        }
    currentNode = currentNode.parentNode;
    }
cn = document.childNodes;
for (i=0;i<cn.length;i++)
    {
    if (cn[i] === currentNode)
        {
        branch.push(i);
        break;
        }
    }
node.innerHTML = branch.reverse().join(",");
Andrew Dunn
I think IE requires non-standard `parentElement` instead of `parentNode`.
no
IE has supported `parentNode` since IE5 buddy :p
Andrew Dunn
hmm, really? Must be something else that screws it up.. been doing the parentElement||parentNode thing for as long as I can remember
no
BTW is this the documentation for that? http://msdn.microsoft.com/en-us/library/ms534328 ... Do they show what version of their js engine parentNode first appears in somewhere?
no
I'm just going off the O'Reilly Javascript Reference which is included with Dreamweaver.
Andrew Dunn
A: 

This will work. It returns the path as an array instead of a string.

Updated per your request.

You can check it out here: http://jsbin.com/isata5/edit (hit preview)

// get a node's index.
function getIndex (node) {
  var parent=node.parentElement||node.parentNode, i=-1, child;
  while (parent && (child=parent.childNodes[++i])) if (child==node) return i;
  return -1;
}

// get a node's path.
function getPath (node) {
  var parent, path=[], index=getIndex(node);
  (parent=node.parentElement||node.parentNode) && (path=getPath(parent));
  index > -1 && path.push(index);
  return path;
}

// get a node from a path.
function getNode (path) {
  var node=document.documentElement, i=0, index;
  while ((index=path[++i]) > -1) node=node.childNodes[index];
  return node;
}

This example should work on this page in your console.

var testNode=document.getElementById('comment-4007919');
console.log("testNode: " + testNode.innerHTML);

var testPath=getPath(testNode);
console.log("testPath: " + testPath);

var testFind=getNode(testPath);
console.log("testFind: " + testFind.innerHTML);
no
thanks for the answer. How would I get the object/element from the path? // 0,1,16,1,0,3
Rana
you could get it by recursively finding someNode.`childNodes`[pathIndex], where someNode starts out as the document element (`window.document.documentElement`). I'll update the answer in a minute.
no
thanks for the update. have another question. why node.parentElement || node.parentNode? whats the difference between them?
Rana
You can probably just use parentNode, it's an old habit I use because some old browser or other would only accept non-standard parentElement, but it's probably long gone. Most browsers accept either one; moz only accepts parentNode I think, which is the standard.
no