106 votes

JavaScript DOM : Trouver l'index d'un élément dans un conteneur

J'ai besoin de trouver l'index d'un élément dans son conteneur par référence d'objet. Bizarrement, je ne trouve pas de méthode simple. Pas de jQuery s'il vous plaît - seulement DOM.

UL
 LI
 LI
 LI - my index is 2
 LI

Oui, je pourrais attribuer des ID à chaque élément et parcourir en boucle tous les nœuds pour faire correspondre l'ID, mais cela semble une mauvaise solution. N'y a-t-il pas quelque chose de plus agréable ?

Ainsi, disons que j'ai une référence d'objet au troisième LI comme dans l'exemple ci-dessus. Comment puis-je savoir qu'il s'agit de l'indice 2 ?

Merci.

118voto

jAndy Points 93076

Vous pouvez faire usage de Array.prototype.indexOf . Pour cela, il faut en quelque sorte "couler" le HTMLNodeCollection en un véritable Array . Par exemple :

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

Alors nous pourrions juste 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>

95voto

Julien BONNIN Points 740

Voici comment je procède (version 2018 ?) :

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

Tadaaaam. Et, si jamais vous voulez considérer les nœuds de texte brut aussi, vous pouvez faire ceci à la place :

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

J'ai réparti les enfants dans un tableau car ils sont une HTMLCollection (donc ils ne fonctionnent pas avec indexOf).

Faites attention à ce que vous utilisiez Babel ou à ce que la couverture du navigateur soit suffisante pour ce que vous devez réaliser (pensez à l'opérateur spread qui est fondamentalement un Array.from behind the scene).

54voto

Tim Down Points 124501

Mise à jour de 2017

La réponse originale ci-dessous suppose que le PO souhaite inclure des nœuds de texte non vides et d'autres types de nœuds ainsi que des éléments. La question ne me semble pas claire quant à la validité de cette hypothèse.

En supposant qu'à la place vous voulez juste l'index de l'élément, previousElementSibling est maintenant bien supporté (ce qui n'était pas le cas en 2012) et est le choix évident maintenant. Ce qui suit (qui est le même que certaines autres réponses ici) fonctionnera dans toutes les versions majeures sauf IE <= 8.

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

Réponse originale

Il suffit d'utiliser previousSibling jusqu'à ce que tu atteignes null . Je suppose que vous voulez ignorer les nœuds de texte avec espace blanc uniquement ; si vous voulez filtrer d'autres nœuds, ajustez-les en conséquence.

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

26voto

Alexander Guiness Points 366
Array.prototype.indexOf.call(this.parentElement.children, this);

Ou utilisez let déclaration.

10voto

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

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

Cela permet par exemple d'enregistrer 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X