192 votes

Comment itérer correctement dans getElementsByClassName ?

Je suis un débutant en Javascript.

Je suis en train de visiter la page web via le window.onload je dois trouver un groupe d'éléments par leur nom de classe ( slide ) et les redistribuer dans différents nœuds en fonction d'une certaine logique. J'ai la fonction Distribute(element) qui prend un élément en entrée et effectue la distribution. Je veux faire quelque chose comme ceci (comme indiqué par exemple) aquí o aquí ):

var slides = getElementsByClassName("slide");
for(var i = 0; i < slides.length; i++)
{
   Distribute(slides[i]);
}

Cependant, cela ne fait pas la magie pour moi, car getElementsByClassName ne renvoie pas réellement un tableau, mais un NodeList qui est...

...c'est ma spéculation...

...en étant changé de fonction intérieure Distribute (l'arbre DOM est modifié dans cette fonction, et le clonage de certains nœuds se produit). For-each La structure en boucle n'aide pas non plus.

La variable slides agit de manière vraiment indéterminée, à chaque itération, elle change sauvagement de longueur et d'ordre des éléments.

Quelle est la manière correcte d'itérer à travers NodeList dans mon cas ? Je pensais remplir un tableau temporaire, mais je ne suis pas sûr de la façon de le faire...

EDIT :

fait important que j'ai oublié de mentionner est qu'il peut y avoir une diapositive à l'intérieur d'une autre, c'est en fait ce qui change le slides variable comme je viens de le découvrir grâce à l'utilisateur Alohci .

La solution pour moi a été de cloner chaque élément dans un tableau d'abord et de passer le tableau un par un dans Distribute() après.

8voto

ayjay Points 321

J'ai suivi Alohci La recommandation d'un looping en arrière parce que c'est un live. nodeList . Voici ce que j'ai fait pour ceux qui sont curieux...

  var activeObjects = documents.getElementsByClassName('active'); // a live nodeList

  //Use a reverse-loop because the array is an active NodeList
  while(activeObjects.length > 0) {
    var lastElem = activePaths[activePaths.length-1]; //select the last element

    //Remove the 'active' class from the element.  
    //This will automatically update the nodeList's length too.
    var className = lastElem.getAttribute('class').replace('active','');
    lastElem.setAttribute('class', className);
  }

2voto

Exodus 4D Points 399

Vous pourriez utiliser Object.values + for...of boucle :

const listA = document.getElementById('A');
const listB = document.getElementById('B');
const listC = document.getElementById('C');
const btn = document.getElementById('btn');

btn.addEventListener('click', e => {
  // Loop & manipulate live nodeLList
  for (const li of Object.values(listA.getElementsByClassName('li'))) {
    if (li.classList.contains('active')) {
      listB.append(li);
    } else {
      listC.append(li);
    }
  }
});

ul {
  display: inline-flex;
  flex-direction: column;
  border: 1px solid;
}

ul::before {
  content: attr(id);
}

.active {
  color: red;
}

.active::after {
  content: " (active)";
}

<ul id="A">
  <li class="li active">1. Item</li>
  <li class="li">2. Item</li>
  <li class="li">3. Item</li>
  <li class="li active">4. Item</li>
  <li class="li active">5. Item</li>
  <li class="li">6. Item</li>
  <li class="li active">7. Item</li>
  <li class="li">8. Item</li>
</ul>

<button id="btn">Distribute A</button>

<ul id="B"></ul>
<ul id="C"></ul>
Un seul mot :
Object.values(listA.getElementsByClassName('li')).forEach(li => (li.classList.contains('active') ? listB : listC).append(li))

1voto

Kushal Desai Points 25
 <!--something like this--> 
<html>
<body>

<!-- i've used for loop...this pointer takes current element to apply a 
 particular change on it ...other elements take change by else condition 
-->  

<div class="classname" onclick="myFunction(this);">first</div>  
<div class="classname" onclick="myFunction(this);">second</div>

<script>
function myFunction(p) {
 var x = document.getElementsByClassName("classname");
 var i;
 for (i = 0; i < x.length; i++) {
    if(x[i] == p)
    {
x[i].style.background="blue";
    }
    else{
x[i].style.background="red";
    }
}
}

</script>
<!--this script will only work for a class with onclick event but if u want 
to use all class of same name then u can use querySelectorAll() ...-->

var variable_name=document.querySelectorAll('.classname');
for(var i=0;i<variable_name.length;i++){
variable_name[i].(--your option--);
}

 <!--if u like to divide it on some logic apply it inside this for loop 
 using your nodelist-->

</body>
</html>

1voto

J0ANMM Points 2047

J'ai eu un problème similaire avec l'itération et j'ai atterri ici. Peut-être que quelqu'un d'autre fait la même erreur que moi.

Dans mon cas, le sélecteur n'était pas du tout le problème. Le problème était que j'avais raté le code javascript : J'avais une boucle et une sous-boucle. La sous-boucle utilisait également i comme compteur, au lieu de j donc, parce que la sous-boucle a remplacé la valeur de i de la boucle principale, celui-ci n'est jamais arrivé à la deuxième itération.

var dayContainers = document.getElementsByClassName('day-container');
for(var i = 0; i < dayContainers.length; i++) { //loop of length = 2
        var thisDayDiv = dayContainers[i];
        // do whatever

        var inputs = thisDayDiv.getElementsByTagName('input');

        for(var j = 0; j < inputs.length; j++) { //loop of length = 4
            var thisInput = inputs[j];
            // do whatever

        };

    };

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