33

The NodeList don't have a indexOf(element) method? So, how can I get the element index?

1
  • 6
    can you un-accept the accepted answer please? The person who wrote it even agrees it's not the best answer Commented Dec 23, 2019 at 22:22

5 Answers 5

78

You can use Array.prototype.indexOf.call() like this

let nodes = document.getElementsByTagName('*');
Array.prototype.indexOf.call(nodes, document.body);
Sign up to request clarification or add additional context in comments.

2 Comments

To make it mega obvious, usage is like Array.prototype.indexOf.call(haystack, needle);
definitely works, but I like the ES6 approach below better since it does not rely on future compatibility guess. My guess is that calling built-in functions on random stuff is more likely to get deprecated than Array.from(NodeList)...
33

The NodeList object is an Array-like object. So it's possible to "convert" it into an Array using Array.prototype.slice.call()

var arr = Array.prototype.slice.call(yourNodeListObject); // Now it's an Array.
arr.indexOf(element); // The index of your element :)

On browsers that support ES6 you can also do this with Array.from()

const arr = Array.from(yourNodeListObject);

or using the spread operator ...

const arr = [...yourNodeListObject];

1 Comment

You can use it like this: var listOfElements = Array.prototype.slice.call(node.parentElement.children), // Now it's an Array. indexInList = listOfElements.indexOf(node);
15

By iterating over the elements, and checking if it matches.

Generic code that finds the index of the element within it's parents childNodes collection.

function index(el) {
    var children = el.parentNode.childNodes,
        i = 0;
    for (; i < children.length; i++) {
        if (children[i] == el) {
            return i;
        }
    }
    return -1;
}

Usage:

// should return 4
var idx = index(document.body.childNodes[4]);

EDIT: I can't delete an accepted answer, but @kennebec's answer below is much better, which I'll quote verbatim:

You can use Array.prototype.indexOf.call() like this

let nodes = document.getElementsByTagName('*');
Array.prototype.indexOf.call(nodes, document.body);

3 Comments

is there a design reason the nodelist doesn't have an indexof operation?
use Array.prototype.indexOf.call(NodeList, element)
I wish I could upvote your username other than the answer @try-catch-finally
4

Just add one line in your script:

NodeList.prototype.indexOf = Array.prototype.indexOf;   // for IE11

Then use indexOf as usual:

var index = NodeList.indexOf(NodeElement);

3 Comments

it seems to work, OK. But why ? could you explain ?
More explanation would be nice. But on face value it seems to be just a roundabout way of casting into an array which is why it works the same way as the answers above.
@Chrysotribax It works because: 1. First line just copies reference to indexOf method of Array into NodeList prototype. 2. Since indexOf method reference already in NodeList prototype you can invoke it from NodeList instance. Internal implementation of indexOf works well with pseudo-arrays. Anyway, it isn't the best solution. Better solutions you can find above.
1

Let us say you have the following line:

const list=document.querySelectAll('.some_class .someother_class');

list will be a nodelist. So we can convert the nodelist to an array and create a new array of indexes as follows:

const indexArr= [...list].map( element => return [...list].indexOf(element) );

indexArr contains all the indexes of elements in the original list.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.