No library solutions, please, though if you know of one that does this, I'm happy to take a look at how they do it. Not terribly concerned with fall-backs and cross browser support.
I have a hierarchy (that will change):
<body>
<div></div>
<div>
<div></div>
<div></div>
<div>
<a>Click Me!</a>
</div>
</div>
</body>
I have an event listener on <a>Click Me!</a>
and get an event object back. That much works. YEY!
I want the event.target
dom hierarchy numerical index. basically, [0][1][2][0]
(though it would probably return as an array, [0,1,2,0]
, and that's okay with me).
I know this can be done with iterating through the parent elements. I'm trying to avoid that iteration, if possible.
EDIT Redacting my last edit as an act of idiocy.
No library solutions, please, though if you know of one that does this, I'm happy to take a look at how they do it. Not terribly concerned with fall-backs and cross browser support.
I have a hierarchy (that will change):
<body>
<div></div>
<div>
<div></div>
<div></div>
<div>
<a>Click Me!</a>
</div>
</div>
</body>
I have an event listener on <a>Click Me!</a>
and get an event object back. That much works. YEY!
I want the event.target
dom hierarchy numerical index. basically, [0][1][2][0]
(though it would probably return as an array, [0,1,2,0]
, and that's okay with me).
I know this can be done with iterating through the parent elements. I'm trying to avoid that iteration, if possible.
EDIT Redacting my last edit as an act of idiocy.
Share Improve this question edited Oct 30, 2012 at 21:14 Randy Hall asked Oct 30, 2012 at 20:34 Randy HallRandy Hall 8,17721 gold badges84 silver badges171 bronze badges 10- 2 Um, how are you going to calculate the location of the element including the parents' locations if you don't iterate through the parents? I am not sure that's possible. – Ryan Bigg Commented Oct 30, 2012 at 20:39
-
I'm not sure either, I am hoping there is some magical way to do this. Perhaps treating the DOM as an array, and getting the index of the
event.target
? These intricacies are beyond my understanding of javascript =) – Randy Hall Commented Oct 30, 2012 at 20:42 - Perhaps another way to look at this question: does the element know its deep position in the dom in a way that can be accessed? – Randy Hall Commented Oct 30, 2012 at 20:47
-
I can't think of a way to deal with that problem without iterating. In jQuery you have the
index()
method to get the position, but I'm pretty sure it iterates in maybe some smart way. But I must ask this: the hierarchy is generated by whom? In which way?Or, in other terms, how much can you alter its elements by giving them classes or other attributes? – Polmonite Commented Oct 30, 2012 at 21:15 - 1 Maybe the right question is: what's the point of knowing the hierarchy index, and isn't there another way to achieve your real goal? – Christophe Commented Oct 30, 2012 at 21:34
3 Answers
Reset to default 6A way to get an index without explicit iteration is to use the array indexOf method.
Here is what it would look like, e being your event:
function getIndex(e){
var t=e.target;
return Array.prototype.indexOf.call(t.parentNode.childNodes,t);
}
There's a number of gotchas with this technique. First, indexOf is only supported by the most recent browsers. Second, you need the call trick because a NodeList is not an array. Third, childNodes might return more nodes than expected and then you'll have to filter by node type.
To get the whole hierarchy index, just rince and repeat as you climb up the DOM hierarchy with parentNode.
For the record, e.target is not cross-browser either, but I see this is what you're already using.
[Update] The full code, using children instead of childNodes:
function getIndex(e) {
var index=[],
t=e.target;
while (t!==document.body) {
index.unshift(Array.prototype.indexOf.call(t.parentElement.children,t));
t=t.parentElement;
}
return index;
}
I know you want to avoid iteration, but it's probably the most straight forward strategy:
$(document).on('click','a', function(e){
var result=[];
var count = function(e){
if(e.parentNode != document.body ){
result.push(e);
count(e.parentNode);
}else {
return result;
}
};
count(e.target)
console.log(result);
});
For what reasons are you trying to avoid iteration? Is the dom huge or something?
You say that "The elements will dynamically change on the page quite rapidly" and that you are "attempting to create an array in javascript that mimics the position of elements in the dom". It means that you'll need to recalculate not only the index path of the element(s) that moved, but also the index path of the ones that didn't move.
Bottom line: instead of calculating the path of an individual element, it makes sense to me to iterate through the whole hierarchy, as anyway you'll need to recalculate not one, but all index paths.