JavaScript DOM: Find Element Index In Container

You could make usage of Array.prototype.indexOf. For that, we need to somewhat "cast" the HTMLNodeCollection into a true Array. For instance:

var nodes = Array.prototype.slice.call( document.getElementById('list').children );

Then we could just call:

nodes.indexOf( liNodeReference );

Example:

var nodes = Array.prototype.slice.call( document.getElementById('list').children ),
    liRef = document.getElementsByClassName('match')[0];

console.log( nodes.indexOf( liRef ) );
<ul id="list">
    <li>foo</li>
    <li class="match">bar</li>
    <li>baz</li>    
</ul>

Here is how I do (2018 version ?) :

const index = [...el.parentElement.children].indexOf(el);

Tadaaaam. And, if ever you want to consider raw text nodes too, you can do this instead :

const index = [...el.parentElement.childNodes].indexOf(el);

I spread the children into an array as they are an HTMLCollection (thus they do not work with indexOf).

Be careful that you are using Babel or that browser coverage is sufficient for what you need to achieve (thinkings about the spread operator which is basically an Array.from behind the scene).


2017 update

The original answer below assumes that the OP wants to include non-empty text node and other node types as well as elements. It doesn't seem clear to me now from the question whether this is a valid assumption.

Assuming instead you just want the element index, previousElementSibling is now well-supported (which was not the case in 2012) and is the obvious choice now. The following (which is the same as some other answers here) will work in everything major except IE <= 8.

function getElementIndex(node) {
    var index = 0;
    while ( (node = node.previousElementSibling) ) {
        index++;
    }
    return index;
}

Original answer

Just use previousSibling until you hit null. I'm assuming you want to ignore white space-only text nodes; if you want to filter other nodes then adjust accordingly.

function getNodeIndex(node) {
    var index = 0;
    while ( (node = node.previousSibling) ) {
        if (node.nodeType != 3 || !/^\s*$/.test(node.data)) {
            index++;
        }
    }
    return index;
}

Array.prototype.indexOf.call(this.parentElement.children, this);

Or use let statement.


For just elements this can be used to find the index of an element amongst it's sibling elements:

function getElIndex(el) {
    for (var i = 0; el = el.previousElementSibling; i++);
    return i;
}

Note that previousElementSibling isn't supported in IE<9.