JavaScript DOM: Find Element Index In Container

Je dois trouver un index d'élément dans son conteneur par référence d'objet. Curieusement, je ne peux pas trouver un moyen facile. Non jQuery s'il vous plaît – seulement DOM.

UL LI LI LI - my index is 2 LI 

Oui, je pourrais attribuer des identifiants à chaque élément et boucler tous les noeuds pour qu'ils correspondent à l'ID, mais cela semble être une mauvaise solution. N'y a-t-il pas quelque chose de plus agréable?

Donc, disons que j'ai une référence d'objet à la troisième LI comme dans l'exemple ci-dessus. Comment puis-je savoir que c'est l'index 2?

Merci.

Vous pouvez utiliser Array.prototype.indexOf . Pour cela, nous devons plutôt "lancer" le HTMLNodeCollection dans un véritable Array . Par exemple:

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

Ensuite, nous pourrions simplement appeler:

 nodes.indexOf( liNodeReference ); 

Exemple:

 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> 

Mise à jour 2017

La réponse d'origine ci-dessous suppose que l'OP veut inclure des nœuds de texte non-vides et d'autres types de nœuds ainsi que des éléments. Il ne me paraît pas évident de savoir s'il s'agit d'une hypothèse valable.

En supposant que vous voulez juste l'indice d'élément, previousElementSibling est maintenant bien pris en charge (ce qui n'était pas le cas en 2012) et est le choix évident maintenant. Ce qui suit (qui est le même que d'autres réponses ici) fonctionnera dans tout ce qui est important sauf IE <= 8.

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

Réponse originale

Il suffit d'utiliser la version previousSibling jusqu'à ce que vous atteigniez null . Je suppose que vous voulez ignorer les noeuds de texte en espace blanc uniquement; Si vous souhaitez filtrer d'autres nœuds, ajustez-le en conséquence.

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

Vous pouvez l'utiliser pour trouver l'index d'un élément:

Array.prototype.indexOf.call(yourUl, yourLi)

Ceci, par exemple, enregistre tous les indices:

 var lis = yourList.getElementsByTagName('li'); for(var i = 0; i < lis.length; i++) { console.log(Array.prototype.indexOf.call(lis, lis[i])); }​ 

JSFIDDLE

Pour les éléments simples, cela peut être utilisé pour trouver l'index d'un élément parmi ses éléments de fratrie:

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

Notez que previousElementSibling n'est pas pris en charge dans IE <9.

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

Ou utilisez la déclaration let .

Un exemple de création d'un tableau de HTMLCollection

 <ul id="myList"> <li>0</li> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> <script> var tagList = []; var ulList = document.getElementById("myList"); var tags = ulList.getElementsByTagName("li"); //Dump elements into Array while( tagList.length != tags.length){ tagList.push(tags[tagList.length]) }; tagList.forEach(function(item){ item.addEventListener("click", function (event){ console.log(tagList.indexOf( event.target || event.srcElement)); }); }); </script> 

Un autre exemple en utilisant une boucle de base et un contrôle d'index

HTML

 <ul id="foo"> <li>0</li> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> 

JavaScript fonctionne sous charge / prêt ou après ul est rendu

 var list = document.getElementById("foo"), items = list.getElementsByTagName("li"); list.onclick = function(e) { var evt = e || window.event, src = evt.target || evt.srcElement; var myIndex = findIndex(src); alert(myIndex); }; function findIndex( elem ) { var i, len = items.length; for(i=0; i<len; i++) { if (items[i]===elem) { return i; } } return -1; } 

Exemple de fonctionnement

JsFiddle

Passez simplement la référence d'objet à la fonction suivante et vous obtiendrez l'indice

 function thisindex(elm) { var the_li = elm; var the_ul = elm.parentNode; var li_list = the_ul.childNodes; var count = 0; // Tracks the index of LI nodes // Step through all the child nodes of the UL for( var i = 0; i < li_list.length; i++ ) { var node = li_list.item(i); if( node ) { // Check to see if the node is a LI if( node.nodeName == "LI" ) { // Increment the count of LI nodes count++; // Check to see if this node is the one passed in if( the_li == node ) { // If so, alert the current count alert(count-1); } } } } } 

Si vous souhaitez écrire ce compact, tout ce dont vous avez besoin est:

 var i = 0; for (;yourElement.parentNode[i]!==yourElement;i++){} indexOfYourElement = i; 

Nous parcourons simplement les éléments du noeud parent, en nous arrêtant lorsque nous trouvons votre élément.

Vous pouvez également facilement:

 for (;yourElement.parentNode.getElementsByTagName("li")[i]!==yourElement;i++){} 

Si c'est tout ce que vous voulez regarder à travers.

Vous pouvez itérer via <li> s dans le <ul> et arrêtez-vous lorsque vous trouvez le bon.

 function getIndex(li) { var lis = li.parentNode.getElementsByTagName('li'); for (var i = 0, len = lis.length; i < len; i++) { if (li === lis[i]) { return i; } } } 

Démonstration