web-dev-qa-db-fra.com

JavaScript DOM: rechercher un index dans un conteneur

J'ai besoin de trouver un index d'élément dans son conteneur par référence d'objet. Étrangement, je ne peux pas trouver un moyen facile. Pas de jQuery s'il vous plaît - seulement DOM.

UL
 LI
 LI
 LI - my index is 2
 LI

Oui, je pouvais attribuer des identifiants à chaque élément et parcourir tous les nœuds pour faire correspondre l'identifiant, mais cela semble 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 savoir si c'est l'index 2?

Merci.

63
Vad

Vous pourriez utiliser Array.prototype.indexOf. Pour cela, nous devons "lancer" un peu le HTMLNodeCollection dans un vrai 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>
76
jAndy

mise à jour 2017

La réponse originale ci-dessous suppose que l'OP souhaite inclure des nœuds de texte non vides et d'autres types de nœuds ainsi que des éléments. La question de savoir si cette hypothèse est valable ne me semble pas claire.

En supposant que vous souhaitiez simplement l'index de l'élément, previousElementSibling est maintenant bien pris en charge (ce qui n'était pas le cas en 2012) et constitue le choix évident pour le moment. Ce qui suit (qui est le même que d’autres réponses ici) fonctionnera dans tout ce qui est majeur sauf IE <= 8.

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

réponse originale

Utilisez simplement previousSibling jusqu'à ce que vous appuyiez sur null. Je suppose que vous voulez ignorer les nœuds de texte contenant uniquement des espaces; si vous souhaitez filtrer d'autres nœuds, ajustez en conséquence.

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

Voici comment je fais (version 2018?):

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

Tadaaaam. Et, si vous souhaitez également prendre en compte les nœuds de texte brut, vous pouvez le faire à la place:

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

Je répartis les enfants dans un tableau car ils constituent une collection HTMLC (ils ne fonctionnent donc pas avec indexOf).

Veillez à utiliser Babel ou à ce que la couverture du navigateur soit suffisante pour atteindre vos objectifs (réflexions sur l'opérateur de diffusion, qui est fondamentalement un Array.from en coulisse).

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

Ou utilisez l'instruction let.

13
Alexander Abashkin

Pour des éléments seulement, cela peut être utilisé pour trouver l'index d'un élément parmi ses éléments frères:

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.

9
Web_Designer

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

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

Ceci enregistre par exemple tous les index:

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

[~ # ~] jsfiddle [~ # ~]

8
rsplak

Une approche native moderne pourrait utiliser 'Array.from ()' - par exemple: `

const el = document.getElementById('get-this-index')
const index = Array.from(document.querySelectorAll('li')).indexOf(el)
document.querySelector('h2').textContent = `index = ${index}`
<ul>
  <li>zero
  <li>one
  <li id='get-this-index'>two
  <li>three
</ul>
<h2></h2>

`

2
calipoop

Exemple de création d'un tableau à partir 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>
2
berandomsen

Si vous voulez écrire cela de manière compacte, tout ce dont vous avez besoin est:

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

Nous nous contentons de parcourir les éléments du nœud parent, en nous arrêtant lorsque nous trouvons votre élément.

Vous pouvez aussi facilement faire:

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

si c'est tout ce que vous voulez regarder.

1
Ada

Vous pouvez parcourir le <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émo

1
Rocket Hazmat

Il suffit de passer la référence de l'objet à la fonction suivante et vous obtiendrez l'index

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);
                }
            }
        }
    }
}
0
Clyde Lobo
    const nodes = Array.prototype.slice.call( el.parentNode.childNodes );
    const index = nodes.indexOf(el);
    console.log('index = ', index);
0
Nguyen Anh Vu

Un autre exemple utilisant simplement une vérification basique de boucle et d'index

[~ # ~] html [~ # ~]

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

JavaScript s'exécute le chargement/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 en cours d'exécution

jsFiddle

0
epascarello