2

My simplified code, which should add an EventListener to each b element within my navigation, looks like this:

function openSubNavs2()
{
 var allToggleBs = document.querySelector('ul#nav').getElementsByTagName('b');
 for (var i=0; i<allToggleBs.length; i++)
 {
  var toggleB = allToggleBs[i];
  toggleB.addEventListener('click', function()
  {
   toggleB.className = 'show';
  });
 }
}
window.addEventListener('load', function() {openSubNavs2();});

but the EventListener 'click' is not created.

If I change the increasing allToggleBs[i] to a static allToggleBs[0], the first b element gets the class "show" when clicked - just as expected. The same works with allToggleBs[1] for the second b element.

So basically the b elements are found correctly, but the for loop is not working, and I can't find the reason why.

EricBln
  • 101
  • 1
  • 6
  • Possible duplicate of [javascript 'let' and 'var' in for-loops](https://stackoverflow.com/questions/43847863/javascript-let-and-var-in-for-loops) – zmag Feb 26 '19 at 13:19
  • 1
    toggleB will not stay the same after the loop finishes. Either use `event.target` or `this` to refer to the clicked tag instead of the variabel toggleB. YOu could also just add One click event to the nav instead of a click per tag and then use event.target to have One event to handle All cases. – Shilly Feb 26 '19 at 13:19
  • Possible duplicate of [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Nick Parsons Feb 26 '19 at 13:33

4 Answers4

1

Declare the variable with let instead of var which will create individual scope.

for (let i=0; i<allToggleBs.length; i++)
Mamun
  • 66,969
  • 9
  • 47
  • 59
1

You can also use anonymous function if you need es3 support:

function openSubNavs2()
{
    var allToggleBs = document.querySelector('ul#nav').getElementsByTagName('b');
    for (var i=0; i<allToggleBs.length; i++)
    {
        (function(toggleB) {
            toggleB.addEventListener('click', function() {
                toggleB.className = 'show';
            });
        })(allToggleBs[i]);
    }
}
deathangel908
  • 8,601
  • 8
  • 47
  • 81
  • While let instead of var (see other posts) is useful, it didn't solve the problem. Your solution does. – EricBln Feb 26 '19 at 14:16
1

I think you are lossing the context of i. You could declare the i var with let instead of var. Or still using ES5, wrapping i in a closure (so there, i won't change its value):

function openSubNavs2()
{
    var allToggleBs = document.querySelector('ul#nav').getElementsByTagName('b');
    for (var i=0; i<allToggleBs.length; i++)
    {
        (function(i) {
            var toggleB = allToggleBs[i];
            toggleB.addEventListener('click', function()
            {
                toggleB.className = 'show';
            });
        })(i);

    }
}
window.addEventListener('load', function() {openSubNavs2();});
José Antonio Postigo
  • 2,674
  • 24
  • 17
  • While let instead of var (see other posts) is useful, it didn't solve the problem. Your solution does, I just chose the other one for its support of some older browsers (while otherwise doing the same). – EricBln Feb 26 '19 at 14:15
0

Declare variable with let rather than var .You can use

for (let i=0; i<allToggleBs.length; i++)