1

I am trying to toggle 5 circles (divs with class 'circle') on a page to change background color on a click with eventListener.

javascript:

var circle = document.querySelectorAll(".circle");

for(var i = 0; i < circle.length; i++){
 circle[i].addEventListener('click', function(){
 circle[i].classList.toggle('effect');
});

}

I keep getting the error "Cannot read property 'classList' of undefined" - I'm not sure why circle is undefined?

css:

.circle {
width: 100px;
height: 100px;
border: solid 3px black;
border-radius: 100%;
float: left;
margin: 1%;
}


.effect {
background-color: green;
border-color: blue;

}

html:

 <!DOCTYPE html>
  <html>
  <head>
   <meta charset="utf-8">
   <title></title>
   <link rel="stylesheet" href="style.css">
 </head>
 <body>

  <div class="circle">
  </div>

  <div class="circle">
  </div>


  <div class="circle">
  </div>

  <div class="circle">
  </div>

  <div class="circle">
  </div>


 <script src="script.js"></script>
</body>
</html>
FakeEmpire
  • 668
  • 1
  • 14
  • 35

2 Answers2

1

The callback you pass into the addEventListener captures the varible i in the loop, so when it is time for the callback to be executed (the click event is triggered) the call back just sees the varible i at the time the loop finishes which is your circle.length, so circle[i] will be out of bound which returns a non existing element (or undefined). So to make it work, change circle[i] inside the back to this which points to the current DOM element like so

for(var i = 0; i < circle.length; i++) {
     circle[i].addEventListener('click', function(){
         this.classList.toggle('effect');
});

Learn more about this HERE

Trash Can
  • 6,608
  • 5
  • 24
  • 38
0

Since the click event will happen in future, but the i to be update with the last value as loop will not wait to execute.

var circle = document.querySelectorAll(".circle");

for (var i = 0; i < circle.length; i++) {
  // Creating a closure & passing value of i which is received in argument x
  (function(x) {
    // adding the click event to the the element 
    circle[x].addEventListener('click', function() {
      // this will refer to the current element in target
      this.classList.toggle('effect')
    })

  }(i)) // passing the value of i
}

DEMO

brk
  • 48,835
  • 10
  • 56
  • 78