Skip to content
Advertisement

How can I make a style event with addEventListener to multiple Nodes

I am trying to set a style event for a multiple images tags and I can’t: the error is in the anonymous function of the event when I put into a loop to make the effect individually and for all galleries in the document with images[i].

Why ? : Uncaught TypeError: Cannot set property 'style' of undefined at HTMLImageElement.<anonymous>

images = document.querySelectorAll(".gallery img");

for (var i=0; i<images.length; i++){
    images[i].addEventListener('mouseout', function(){ images[i].style=" transform: scale(.8)" }); 
    images[i].addEventListener('mouseover', function(){ images[i].style=" transform: scale(1.2)" }); 
} 
<div class="gallery">
    <img src="https://picsum.photos/300/180">
    <img src="https://picsum.photos/300/180">
    <img src="https://picsum.photos/300/180">
</div>

Advertisement

Answer

ES6+ solution:

Simply change var to let in the for loop.

images = document.querySelectorAll(".gallery img");

for (let i = 0; i < images.length; i++){
    images[i].addEventListener('mouseout', function(){ images[i].style=" transform: scale(.8)" }); 
    images[i].addEventListener('mouseover', function(){ images[i].style=" transform: scale(1.2)" }); 
} 
<div class="gallery">
    <img src="https://picsum.photos/300/180">
    <img src="https://picsum.photos/300/180">
    <img src="https://picsum.photos/300/180">
  </div>

If you must use var rather than let, you can use .bind() to set the value of i for the function. Otherwise it will reference the last value of i in the loop because of the async nature of the event callback and the higher scope of i due to the use of var.

images = document.querySelectorAll(".gallery img");

function callback1(i){ images[i].style=" transform: scale(.8)" };
function callback2(i){images[i].style=" transform: scale(1.2)" };

for (var i=0; i<images.length; i++){
    images[i].addEventListener('mouseout', callback1.bind(this, i));
    images[i].addEventListener('mouseover', callback2.bind(this, i)); 
}
  <div class="gallery">
    <img src="https://picsum.photos/300/180">
    <img src="https://picsum.photos/300/180">
    <img src="https://picsum.photos/300/180">
  </div>
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement