I have a function I've been using for years that retrieves the index of an HTML element within its parent element, or, if a second argument is passed to it, the index of an HTML element within the collection of elements of the same name in that parent:
var childindex=function(node){
var index=0;
while(node.previousSibling){
if(arguments.length==childindex.length||node.previousSibling.nodeName.toLowerCase()==arguments[1])index++;
node=node.previousSibling;
}
return index;
}
However, in a recent overhaul of my JavaScript library, I went over all these old functions to try to improve upon them and this is what I came up with to replace the above:
let childindex=(node,...selectors)=>
Array.from(selectors.length?node.parentNode.querySelectorAll(`:scope>${selectors.join(",:scope>")}`):node.parentNode.children).indexOf(node);
I'm pretty happy with the result, especially as it gives me the added ability to get the index of the element within any collection of selectors by passing each selector as a new argument and also ignores text nodes even when no additional arguments are passed to it.
I'm wondering, though, if anyone can see anywhere I can improve on it further, either in efficiency or conciseness of code.
Here's a working example to show it in action:
(()=>{
let item=document.getElementById("getthis"),
childindex=(node,...selectors)=>
Array.from(selectors.length?node.parentNode.querySelectorAll(`:scope>${selectors.join(",:scope>")}`):node.parentNode.children).indexOf(node);
//Gets index of `item` within all child elements of <section>
console.log(childindex(item)); // 5
//Gets index of `item` within all child <article> elements of <section>
console.log(childindex(item,"article")); // 3
//Gets index of `item` within all child elements of <section> with .class
console.log(childindex(item,".class")); // 2
//Gets index of `item` within all child <article> & <header> elements of <section>
console.log(childindex(item,"header","article")); // 4
})();
<section>
<header class="class"></header>
<article></article>
<article></article>
<aside class="class"></aside>
<article></article>
<article class="class" id="getthis"></article>
<footer></footer>
</section>