180 votes

Obtenir l'index de l'élément en tant qu'enfant par rapport au parent

Disons que j'ai cette balise :

<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Et j'ai ce jQuery :

$("#wizard li").click(function () {
    // alert index of li relative to ul parent
});

Comment puis-je obtenir l'index de l'enfant li par rapport à son parent, lorsque l'on clique sur ce dernier. li ?

Par exemple, lorsque vous cliquez sur "Étape 1", une alert avec "0" devrait apparaître.

276voto

redsquare Points 47518
$("#wizard li").click(function () {
    console.log( $(this).index() );
});

Cependant, plutôt que d'attacher un gestionnaire de clic pour chaque élément de la liste, il est préférable (du point de vue des performances) d'utiliser la fonction delegate qui ressemblerait à ceci :

$("#wizard").delegate('li', 'click', function () {
    console.log( $(this).index() );
});

Dans jQuery 1.7+, vous devez utiliser on . L'exemple ci-dessous lie l'événement au #wizard qui fonctionne comme un événement délégué :

$("#wizard").on("click", "li", function() {
    console.log( $(this).index() );
});

3 votes

Salut Redsquare Je m'entraîne avec jQuery, je suis un peu n00b sur le délégué :D pourquoi le délégué est mieux que d'attacher des événements directement sur les éléments ?

1 votes

@steweb - Hé - parce qu'un seul gestionnaire d'événements est de loin préférable à plusieurs. Attacher des événements au dom peut être coûteux si vous avez de grandes listes, donc en règle générale, j'essaie d'utiliser ce qui précède lorsque cela est possible plutôt que des gestionnaires individuels sur chaque élément. Un article qui va plus loin est briancrescimanno.com/2008/05/19/ - Cherchez aussi sur Google "délégation d'événements en javascript".

0 votes

Ok, donc, gérer les événements de cette façon c'est quelque chose de plus léger que le classique 'dom attachment' :) ..merci !

45voto

Mash Points 836

Quelque chose comme :

$("ul#wizard li").click(function () {
  var index = $("ul#wizard li").index(this);
  alert("index is: " + index)
});

10 votes

Excellent ajout - nous pouvons trouver l'index par rapport au sélecteur parent. +1

1 votes

Je préfère cette réponse car elle répond réellement à la question plutôt qu'à une solution possible pour l'exemple.

11voto

CertainPerformance Points 110949

Il n'est pas nécessaire d'avoir recours à une grande bibliothèque comme jQuery pour accomplir cette tâche, si vous ne le souhaitez pas. Pour réaliser cela avec la manipulation intégrée du DOM, obtenez une collection de l'élément li dans un tableau, et au moment du clic, vérifiez les éléments suivants indexOf l'élément cliqué dans ce tableau.

const lis = [...document.querySelectorAll('#wizard > li')];
lis.forEach((li) => {
  li.addEventListener('click', () => {
    const index = lis.indexOf(li);
    console.log(index);
  });
});

<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Ou, avec la délégation d'événements :

const lis = [...document.querySelectorAll('#wizard li')];
document.querySelector('#wizard').addEventListener('click', ({ target }) => {
  // Make sure the clicked element is a <li> which is a child of wizard:
  if (!target.matches('#wizard > li')) return;

  const index = lis.indexOf(target);
  console.log(index);
});

<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Ou, si les éléments enfants peuvent changer dynamiquement (comme dans le cas d'une liste de tâches), vous devrez construire le tableau des éléments suivants li à chaque clic, plutôt qu'à l'avance :

const wizard = document.querySelector('#wizard');
wizard.addEventListener('click', ({ target }) => {
  // Make sure the clicked element is a <li>
  if (!target.matches('li')) return;

  const lis = [...wizard.children];
  const index = lis.indexOf(target);
  console.log(index);
});

<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

9voto

Kimtho6 Points 3897

Jetez un coup d'œil à ceci exemple .

$("#wizard li").click(function () {
    alert($(this).index()); // alert index of li relative to ul parent
});

3voto

Jimmy Points 3962

Delegate et Live sont faciles à utiliser, mais si vous n'avez pas l'intention d'ajouter d'autres li:s de manière dynamique, vous pouvez également utiliser la déliaison d'événements avec un bind/click normal. Il devrait y avoir un gain de performance en utilisant cette méthode puisque le DOM n'aura pas à être surveillé pour les nouveaux éléments correspondants. Je n'ai pas de chiffres précis, mais c'est logique :)

$("#wizard").click(function (e) {
    var source = $(e.target);
    if(source.is("li")){
        // alert index of li relative to ul parent
        alert(source.index());
    }
});

Vous pouvez le tester sur jsFiddle : http://jsfiddle.net/jimmysv/4Sfdh/1/

1 votes

À quoi faites-vous référence lorsque vous dites que "le DOM n'aura pas à être surveillé" ? Le délégué jq ne surveille pas le DOM.

0 votes

@redsquare J'avais l'impression que Delegate était juste une variante plus efficace de Live. Ceci est tiré de api.jquery.com/delegate : "Attacher un gestionnaire à un ou plusieurs événements pour tous les éléments qui correspondent au sélecteur, maintenant ou dans le futur, en fonction d'un ensemble spécifique d'éléments Root." Cela doit être un suivi pour lier dans le futur ?

0 votes

Non, il utilise simplement la délégation sur le conteneur comme votre code ci-dessus. Si vous insérez un nouvel élément li dans le conteneur, l'événement click du conteneur est toujours déclenché et tout fonctionne. Aucun contrôle n'est nécessaire.

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