web-dev-qa-db-fra.com

Obtenir le numéro de nième enfant d'un élément en JavaScript pur

Je crée une fonction pour mon site dans laquelle je définis un attribut de données qui contient le numéro de nième enfant de cet élément.

Mon balisage HTML:

<html>
<body>
    <section class="hardware">some text, nth-child is one</section>
    <section class="hardware">some text, nth-child is two</section>
    <section class="hardware">some text, nth-child is three</section>
    <section class="hardware">some text, nth-child is four</section>
    <section class="hardware">some text, nth-child is five</section>
</body>
</html>

Mon JavaScript jusqu'à présent:

var selector = document.getElementsByClassName('hardware');
for(var i = 0; i <= selector.length; i++) {
    var index = selector[i] //get the nth-child number here
    selector[i].dataset.number = index;
}

Comment puis-je obtenir le nième enfant d'un élément avec du JavaScript pur (pas de jQuery), est-ce même possible en JavaScript?

14
Sake Salverda

Quand vous dites "nombre", voulez-vous dire 1, 2, etc. ou "un", "deux", etc.?

Si 1, 2, etc., le nombre est simplement i + 1 ...

Si "un", "deux", etc., vous devez insérer le texte à l'intérieur de l'élément, utilisez probablement une expression rationnelle pour l'analyser et obtenir la valeur souhaitée.

3
jcaron

Découvrez cette réponse précédente ICI .

Il utilise 

var i = 0;
while( (child = child.previousSibling) != null ) 
  i++;
//at the end i will contain the index.
5
joshboley

Incrémenter simplement l'index de manière linéaire ne fonctionnera que si tous les éléments correspondant à ce nom de classe sont les seuls enfants d'élément du même parent, sans aucun autre élément susceptible d'interférer avec :nth-child(), comme indiqué exactement dans le balisage donné. Voir cette réponse pour une explication sur la manière dont d'autres éléments pourraient interférer. Consultez également la spécification Selectors on :nth-child().

Une façon plus infaillible de réaliser cet objectif consiste à parcourir en boucle les nœuds enfants du nœud parent de chaque élément, en incrémentant un compteur pour chaque nœud enfant qui est un nœud d'élément (puisque :nth-child() ne compte que les nœuds d'élément):

var selector = document.getElementsByClassName('hardware');

for (var i = 0; i < selector.length; i++) {
    var element = selector[i];
    var child = element.parentNode.firstChild;
    var index = 0;

    while (true) {
        if (child.nodeType === Node.ELEMENT_NODE) {
            index++;
        }

        if (child === element || !child.nextSibling) {
            break;
        }

        child = child.nextSibling;
    }

    element.dataset.number = index;
}

Démo de JSFiddle

Notez que ceci appliquera l'index correct indépendamment de l'emplacement de l'élément donné dans le DOM:

  • Si un élément section.hardware particulier est le premier et unique enfant d'une variable section différente, l'indice correct 1 lui est attribué.

  • Si un élément .hardware est le deuxième enfant de son parent, même s’il est le seul à posséder cette classe (c’est-à-dire qu’il suit un autre élément sans la classe), l’index correct de 2 lui sera attribué.

2
BoltClock

Je vais répondre aux questions avec les hypothèses suivantes:

  • Vos éléments hardware sont tous frères et soeurs
  • Vous êtes intéressé par le nième enfant pas le nième enfant + 1
  • Ils peuvent être mélangés avec d'autres éléments:
<body>
    <section class="hardware">some text, nth-child is zero</section>
    <section class="software"></section>
    <section class="hardware">some text, nth-child is two</section>
</body>

(Je fais ces hypothèses, parce que c'est le problème auquel je suis confronté, j'ai pensé qu'il pourrait être utile)

La principale différence est donc qu'au lieu d'interroger les éléments appartenant à une classe donnée, je vais obtenir les enfants (directs) de la variable body et les filtrer.

Array.from(document.body.children)
  .map((element, index) => ({element, index}))
  .filter(({element}) => element.classList.contains('hardware'))

Le tableau résultant ressemblera à ceci:

[
  {element: section.hardware, index: 0}
  {element: section.hardware, index: 2}
]
2
fodma1

Vous pouvez scinder le texte au niveau des espaces en obtenant le dernier Word de chaque tableau divisé:

var hards = document.getElementsByClassName('hardware');
for (var i=0; i < hards.length; i++) {
    var hardText = hards[i].innerText || hard[i].textContent;
    var hardList = hardText.split(' ');
    var hardLast = hardList[hardList.length - 1];
    alert(hardLast);
}

J'utilise || ici parce que Firefox ne supporte pas innerText, alors que IE ne supporte pas textContent.

Si les éléments ne contiennent que du texte, innerHTML peut être utilisé à la place de innerText/textContent.

0
Andy G