0

I'm having a seemingly dumb problem, but since I'm not very knowledgeble at JavaScript, I need some help.

I'm just trying to iterate through an array, but it seems to be skipping elements for no reason. My function is really simple:

function uncolour(classname)
{
    var anchors = document.getElementsByClassName(classname);
    for(var i = 0; i < anchors.length; i++) {
        var anchor = anchors[i];
        anchor.classList.toggle("nocolor");
    }
}

The problem is that it is consistently skipping an element. It works for the first element, then for the third and so on. I have verified and all the correct elements are present in the anchors array, but it toggles the class only on the even indexes. Any idea about why? I am at a loss here.

EDIT: Thank you for your responses. I've read the other similar post, but the case with me is that toggling the "nocolor" class shouldn't affect the elements of the array, because the classname that I'm looking for is not the same as "nocolor". I think that while the elements may remain the same, they are somehow rearragend because I've changed the class of an element in the document. So, I don't know why, but that worked for me: for(var i = anchors.length-1; i>=0; i--)

  • Can you reproduce the problem using the code snipped feature of SO ? – Denys Séguret Dec 12 '16 at 12:19
  • 2
    Probably since a man alters a live element collection. – Lain Dec 12 '16 at 12:19
  • That is a live HTML Collection, reverse the loop and start from the end. `for(var i = anchors.length-1; i>=0; i--) {` or `while(anchors.length) { anchors[0].classList.toggle("nocolor"); }` – epascarello Dec 12 '16 at 12:20
  • try using document.querySelectorAll instead of getElementsByClassName – maioman Dec 12 '16 at 12:20
  • can you add your html or mock-up code – Azad Dec 12 '16 at 12:22
  • @Lain that's strange, because the size of the array and its elements should stay the same, since I'm not changing the "classname" class of the elements, I'm just toggling the "nocolor" class. But your solution worked for me, even though I don't understand why. Thank you. – user2980149 Dec 12 '16 at 12:52
  • classList changes the className in the end. – Lain Dec 12 '16 at 12:52

1 Answers1

1

Here is what you can do:

<html>
    <head>
        <script>
            window.onload = function(){
                //This gets all anchors.test.. for now
                var anchors = document.getElementsByClassName('test');
                for(var i=0; i < anchors.length; i++){
                    var anchor = anchors[i];

                    /*
                        As soon as the class test gets removed, the anchors list is updated and the .length of it adjusted.
                        This leads to the mentioned behavior of each second element being skipped

                        Turn one: a, b, c, d, e, f
                        Turn two: b, c, d, e, f
                        Turn three: b, d, e, f
                        .. As much as i is increaded the length is decreased
                    */
                    anchor.classList.toggle('test');
                    anchor.style.color = 'red'
                }
            }
        </script>
    </head>

    <body>
        <a class = 'test'>a</a><a class = 'test'>b</a><a class = 'test'>c</a><a class = 'test'>d</a><a class = 'test'>e</a><a class = 'test'>f</a>
    </body>
</html>

Here is what you should do:

<html>
    <head>
        <script>
            window.onload = function(){
                //This gets all anchors.test.. for now
                var anchors = document.getElementsByClassName('test');

                //Instead from counting up.. it gets counted down which makes the removed element irrelevant
                for(var i=anchors.length-1; i>=0; i--){
                    var anchor = anchors[i];
                    anchor.classList.toggle('test');
                    anchor.style.color = 'orange'
                }
            }
        </script>
    </head>

    <body>
        <a class = 'test'>a</a><a class = 'test'>b</a><a class = 'test'>c</a><a class = 'test'>d</a><a class = 'test'>e</a><a class = 'test'>f</a>
    </body>
</html>
Taryn
  • 242,637
  • 56
  • 362
  • 405
Lain
  • 3,657
  • 1
  • 20
  • 27