Avdept
Avdept

Reputation: 2289

Simple dom inspector script counts incorrectly child nodes

I have simple js function that returns me dom path to clicked element. However sometimes some element(usually the one i have clicked) counts twice

so if i have following code

<ul>
<li><a href ='#'>Some link</a></li>
</ul>

the output could be like ul:nth-child(1) > li:nth-child(1) > a:nth-child(2) while a should be 1 child.

Here is the code of function

var getDomPath;

getDomPath = function(el) {
  var count, element, nth, path, selector, sib;
  element = el;
  if (!(el instanceof Element)) {
    return;
  }
  path = [];
  while (el.nodeType === Node.ELEMENT_NODE && el.id !== "jobs") {
    selector = el.nodeName.toLowerCase();
    if (el.id) {
      selector += "#" + el.id;
    } else if (el.className) {
      selector += "." + el.className;
    } else {
      sib = el;
      nth = 1;
      count = 1;
      while (sib.nodeType === Node.ELEMENT_NODE && (sib = sib.previousSibling) && $(el).prev().prop('tagName') !== "STYLE" && $(el).prev().prop('tagName') !== null) {

        count += $(el).prevAll().size();
      }
      selector += ":nth-child(" + count + ")";
    }
    path.unshift(selector);
    el = el.parentNode;
  }
  return path.join(" > ");
};

Code was converted from coffee to javascript, so might looks a little bad

here is html that im trying to get path to

<td width="50%"><strong>Leveringssadresse</strong>
<br>
Hans Andersen
<br>
Andevej 123
<br>
1234 Andeby
<br>
Denmark
<br>
Telefon: 31122345
<br>
Mobiltelefon: 12232345
<br>
<a href="mailto:[email protected]">[email protected]</a>
<br>
</td>

Here when i click on a element i expect it to be nth-child(8), but somehow i'm getting it 17(16 + 1 as increment by 1 in my code)

Upvotes: 2

Views: 193

Answers (2)

Gabriele Petrioli
Gabriele Petrioli

Reputation: 196002

Just noticed you use jQuery.

Why not simplify it to just

function getDomPath(element){
    var path = $(element).parents().andSelf().map(function(){
        var index = $(this).index() + 1;
        return this.nodeName.toLowerCase() + ':nth-child('+ index +')';
    }).get();

  return path.join(' > ');
}

Demo at http://jsfiddle.net/BEUrn/3/

Upvotes: 2

lonesomeday
lonesomeday

Reputation: 237905

The problem is with this line:

while (sib.nodeType === Node.ELEMENT_NODE && (sib = sib.previousSibling) && $(el).prev().prop('tagName') !== "STYLE" && $(el).prev().prop('tagName') !== null) {

I have read this line multiple times, and I can't work out what you're trying to do.

Your code says:

  • make sure that the currently examined node is an element
  • set the currently examined node to be its previous sibling
  • check that the element before the original node has a tag name that isn't STYLE

I have no idea what that sequence of steps is intended to be, but if the final condition passes, it will calculate n * (x + 1) + 1, where n is the number of preceding element siblings and x is the number of immediately preceding element siblings without intervening text nodes.

The next line is this:

count += $(el).prevAll().size();

This, surely, should only be run once, with the conditional not necessary at all.

count = $(el).prevAll().length + 1;

jsFiddle with working code.

Upvotes: 1

Related Questions