0

This is an extension to my previous question javascript dynamically adding and removing classes

As per the answer given, it uses a forEach loop but I am trying to use a for loop and implement the same:

function test() {
  var paragraphs = document.querySelectorAll("#divid p[id ^= 'p']");
  for(index =0; index < paragraphs.length; index++) {
    paragraphs[index].addEventListener('click', (e) => {
      for (i = 0; i < index; i++) {
        paragraphs[i].classList.remove('active');
      }
      for (i = index; i < paragraphs.length; i++) {
        paragraphs[i].classList.add('active');
      }
    });
  }
}

But I am getting the following error:

11 Uncaught TypeError: Cannot read property 'classList' of undefined
    at HTMLSpanElement.paragraphs.(anonymous function).addEventListener

I also want to remove the special symbol => in above code and solve the issue.

10
  • 1
    "avoiding forEach loop" - but... why? Commented Jul 21, 2017 at 20:10
  • while testing my team reported that some browsers are not supporting this feature, I am not sure which browser is that. Commented Jul 21, 2017 at 20:13
  • Yes, IE<9 are on the list ... Commented Jul 21, 2017 at 20:14
  • 1
    @user3181365 Those browsers would not support arrow functions and classList as well. Commented Jul 21, 2017 at 20:14
  • @YuryTarabanko, oh can you please tell me what is the alternate solution in this case. I want achieve same output without using foreach Commented Jul 21, 2017 at 20:15

1 Answer 1

1

You are running into the classic "closure inside loop" issue, where your loop index variable is the same between all the closure you are creating inside the loop (the functions you are creating as event handlers).

The solution is to wrap the event handler function in an immediately invoked function expression to which you pass the index variable, binding its current value to scope.

function test() {
  var paragraphs = document.querySelectorAll("#divid p");
  for (index = 0; index < paragraphs.length; index++) {
    paragraphs[index].addEventListener('click', (function(index) {
      return function() {
        var i;
        for (i = 0; i < index; ++i) {
          paragraphs[i].classList.remove('active');
        }
        for (i = index; i < paragraphs.length; ++i) {
          paragraphs[i].classList.add('active');
        }
      }
    })(index));
  }
}

test();
p.active {
  color: red;
}
<div id="divid">
  <p>p1</p>
  <p>p2</p>
  <p>p3</p>
  <p>p4</p>
  <p>p5</p>
  <p>p6</p>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

It worked, thanks a lot

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.