34

As per the jQuery api, the complementary operation to .get(), which accepts an index and returns a DOM node, .index() can take a DOM node and returns an index. Suppose we have a simple unordered list on the page:

<ul>
  <li id="foo">foo</li>
  <li id="bar">bar</li>
  <li id="baz">baz</li>
</ul>

.index() will return the position of the first element within the set of matched elements in relation to its siblings:

alert('Index: ' + $('#bar').index();

We get back the zero-based position of the list item:

Index: 1

I just want to know, how can we do the same using JavaScript??

vsync
  • 118,978
  • 58
  • 307
  • 400
palaѕн
  • 72,112
  • 17
  • 116
  • 136
  • I'm not suggesting you should always use jQuery, but out of curiosity, why do you want to do this in pure JS? – Bojangles Dec 01 '12 at 09:17
  • 2
    @JamWaffles: I use jQuery mostly, due to its "The Write Less, Do More" nature. So, I had asked this question just for my knowledge and let others know, what "The Write Less, Do More" really means from this example. Hope you got my point! – palaѕн Dec 01 '12 at 10:45
  • possible duplicate of [Finding DOM node index](http://stackoverflow.com/questions/378365/finding-dom-node-index) – Andrew Whitaker Dec 01 '12 at 17:53
  • 1
    @AndrewWhitaker It should be noted that the answers in the listed duplicate look for the index without testing the type of the node (which may be a text for example). That's why they don't return the same result than jquery's index (as is the question) which is what is generally useful. – Denys Séguret Dec 03 '12 at 07:58

5 Answers5

22

You can build your own function :

function indexInParent(node) {
    var children = node.parentNode.childNodes;
    var num = 0;
    for (var i=0; i<children.length; i++) {
         if (children[i]==node) return num;
         if (children[i].nodeType==1) num++;
    }
    return -1;
}

Demonstration (open the console)

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • This was immensely helpful. Thanks! – SwankyLegg Jun 08 '14 at 22:59
  • Really like this answer! Why do you need to end off with `return -1`? The code will never hit that. If you pass an invalid element, you will get an error. – Jessica Jan 20 '16 at 19:10
  • 1
    @Jessica The usual convention for `index` functions is to return `-1` when an element isn't found, not an error (or `undefined` as it would be without the last line) – Denys Séguret Jan 20 '16 at 19:21
  • Thanks! Do you know the source for jquery's `index()` is? – Jessica Jan 20 '16 at 19:24
  • Why not use parentNode.children instead of parentNode.childNodes? It could allow using indexOf instead of increasing num manually. – Teo M May 18 '16 at 16:57
22

I've modified Travis J answer to not include TextNodes and made a function out of it.

You can run it in the console and see (on stackoverflow).

Classic way:

function getNodeIndex( elm ){ 
    var c = elm.parentNode.children, 
        i = c.length;
        
    while(i--) 
      if( c[i] == elm ) 
        return i
}

With ES2015:

const getNodeIndex = elm => [...elm.parentNode.children].findIndex(c => c == elm)

// or

const getNodeIndex = elm => [...elm.parentNode.children].indexOf(elm)

Demo:

const getNodeIndex = elm => [...elm.parentNode.children].indexOf(elm)
<button onclick="console.log(  getNodeIndex(this)  )">get index</button>
<button onclick="console.log(  getNodeIndex(this)  )">get index</button>
<button onclick="console.log(  getNodeIndex(this)  )">get index</button>

I also want to point to another thread on the same matter, which has a great answer (for people seeking older IE support)

vsync
  • 118,978
  • 58
  • 307
  • 400
10

No loops needed, call Array#indexOf on .parentElement.children:

const element = document.querySelector('#baz');

[].indexOf.call(element.parentElement.children, element);
// => 2

You can even call it on a random list of elements, just like you can in jQuery:

const list = document.querySelectorAll('li');
const element = document.querySelector('#baz');

[].indexOf.call(list, element);
// => 2
fregante
  • 29,050
  • 14
  • 119
  • 159
  • 1
    This should be more highly upvoted, it accomplishes the same thing as all of the other answers do in a single line of code - brilliant – KoldBane May 09 '22 at 15:26
1

You can find this information out by going up the dom tree using previousElementSibling and incrementing.

var getElementIndex(element) {
    if (!element) {
        return -1;
    }
    var currentElement = element,
        index = 0;

    while(currentElement.previousElementSibling) {
        index++;
        currentElement = currentElement.previousElementSibling;
    }
    return index
}

getElementIndex(document.getElementById('#bar'));

here is the browser support for previousElementSibling:

https://developer.mozilla.org/en-US/docs/Web/API/NonDocumentTypeChildNode/previousElementSibling

Corey Young
  • 520
  • 4
  • 10
0

Index can be found in this way

    Array.from(children).findIndex(element => element.id === "bar")