0

So in my code, when you click on an element it will alert the name of the tag.

What I really want to do is find the path, so I could reference that element again later.

So for example, if I clicked the text "World" I'd get something like

DIV(2) > UL > LI (2)

I don't want to do this in jQuery, just plain old vanilla.

document.addEventListener("click", eOnClick, true);

function eOnClick(e) {
  alert(e.target.tagName);
}
div {
  border: 1px solid red;
}
ul {
  border: 1px solid green;
}
li {
  border :1px solid blue;
}
<div>
  <div>
    <ul>
      <li>Hello
      <li>World
    </ul>
  </div>
</div>
Daniel Williams
  • 2,195
  • 7
  • 32
  • 53
  • Maybe this will help: http://stackoverflow.com/questions/8729193/how-to-get-all-parent-nodes-of-given-element-in-pure-javascript – BenShelton Mar 16 '17 at 08:08
  • Thing you are searching for is called "XPath". Check this: http://stackoverflow.com/questions/2661818/javascript-get-xpath-of-a-node – plvice Mar 16 '17 at 08:12

3 Answers3

2

If I understood you correctly this is what you need to do:

Updated

document.addEventListener("click", eOnClick, true);

function eOnClick(e) {
var target =e.target;
var index = calculateIndex(target)
var path=target.tagName+"["+index+"]";
while(target.parentNode)
{
  target= target.parentNode;
if(target.parentNode != undefined){
  index = calculateIndex(target)
    path = target.tagName+"["+index+"]"+" > "+path;
    }
}
  alert(path);
}

function calculateIndex(element){
var ix=0;
 var siblings= element.parentNode.childNodes;
    for (var i= 0; i<siblings.length; i++) {
        var sibling= siblings[i];
        if (sibling.nodeType===1 && sibling.tagName === element.tagName) 
            ix++;

        if (sibling===element)
          return ix;
    }
}
div {
  border: 1px solid red;
}
ul {
  border: 1px solid green;
}
li {
  border :1px solid blue;
}
<div>
  <div>
    <ul>
      <li>Hello
      <li>World
    </ul>
  </div>
</div>

What this does is - it loops up through parent nodes until it hits undefined.

Community
  • 1
  • 1
Max Novich
  • 1,169
  • 9
  • 20
0

var html = "<div><ul><li>1</li><li>2</li><li>3</li></ul><ol><li>1</li><li>2</li><li>3</li></ol></div><div><ul><li>1</li><li>2</li><li>3</li></ul><ol><li>1</li><li>2</li><li>3</li></ol></div>";
document.body.innerHTML += html;

function nodelistToArray(nodelist) {
  return Array.prototype.slice.call(nodelist);
}

function traverse(target, chain) {
  if (chain === void 0) {
    chain = [];
  }
  var index = nodelistToArray(target.parentNode.children).filter(function(a) {
    return a.nodeName == target.nodeName;
  }).indexOf(target);
  chain.push({
    element: target,
    index: index
  });
  if (target.nodeName.toLowerCase() == "html") {
    return chain.reverse();
  } else {
    return traverse(target.parentNode, chain);
  }
}
document.body.onclick = function(evt) {
  var chain = traverse(evt.target);
  console.log(chain);
  alert(chain.map(function(elm) {
    return elm.element.nodeName + ' [' + (elm.index).toString() + ']';
  }).join(' > '));
};
Emil S. Jørgensen
  • 6,216
  • 1
  • 15
  • 28
0

Use the following complex solution:

document.addEventListener("click", eOnClick, true);

function eOnClick(e) {
    var el = e.target, 
    path = [], 
    tagName = "", 
    closest = e.target.parentNode;
  
    while (el.parentNode && el.parentNode !== document) {         
        tagName = el.parentNode.tagName, last = path[path.length - 1];
        
        // if it's the closest parent - analyzing sibling nodes 
        if (closest === el.parentNode) {
           for (var i = 0, childs = closest.childNodes, len = childs.length, c = 1; i < len; i++) {
              if (childs[i] !== el && childs[i].tagName === el.tagName) c++;
           }
           if (c > 1) path.push(el.tagName + c);
        }

        if (!last || (last !== tagName && last.indexOf(tagName) !== 0)) {
     path.push(tagName);        
        } else {
          var num = last.match(/\d+$/);
            last = tagName + ((num)? Number(num) + 1 : 2);
          path[path.length - 1] = last;
        }
        el = el.parentNode;
    }
    path = path.reverse().map(function(v){ return v.replace(/(\d+)$/, "($1)"); }).join(' > ');
    alert(path);
}
div {
  border: 1px solid red;
}
ul {
  border: 1px solid green;
}
li {
  border :1px solid blue;
}
<div>
  <div>
    <ul>
      <li>Hello
      <li>World
    </ul>
  </div>
</div>
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105