Yandong Liu
Yandong Liu

Reputation: 345

javascript of dynamically change image src

I'm writing some very simple code to dynamically change image src on mouseover/mouseout:

   function e(id) {
     return document.getElementById(id);
   }

   function changeimg_bw(ele) {
      e(ele).src='rating_bw.png';
   }

   function changeimg_color(ele) 
      e(ele).src='rating_color.png';
   }

   for(var i=1;i<=5;i++) {
     var img ='rating'+i;
     e(img).addEventListener('mouseover', function(event) {
          changeimg_color(img);
     });
     e(img).addEventListener('mouseout', function(event) {
          changeimg_bw(img);
     });
   }

The idea is fairly simple: use an array of images to simulate the rating bar. And when some image is covered by mouse pointer, it should change color (well ideally including all previous images should change color but I got stuck before getting there). My question is when I hover on any image, only the last image changes color ('rating5'). Looks when i == 5 its eventlistener overwrote all other eventlistener (i=1,2,3,4)?

Upvotes: 5

Views: 5632

Answers (4)

code-jaff
code-jaff

Reputation: 9330

Since javascript don't have block scope but function scope, the img within the anonymous listener functions will refer to the last value.
You could solve this by simply encloses the listeners to a private closure like

for (var i = 1; i <= 5; i++) {
    var img = 'rating' + i;
    (function (img) {
        e(img).addEventListener('mouseover', function (event) {
            changeimg_color(img);
        });
        e(img).addEventListener('mouseout', function (event) {
            changeimg_bw(img);
        });
    })(img);
}

DEMO

For better understanding about closures read this

Upvotes: 2

Givi
Givi

Reputation: 1734

Easiest way to delegate event... In such way you don't need to add listeners per element

Live Demo

var parent = document.getElementById("rating1").parentNode;

parent.addEventListener("mouseover", changeimg_color, false);
parent.addEventListener("mouseout", changeimg_bw, false);

function changeimg_bw(e) {
    if (e.target.nodeName.toLowerCase() === "img") {
        e.target.src='rating_bw.png';
    }
    e.stopPropagation();
    e.preventDefault();
}

function changeimg_color(e) {
    if (e.target.nodeName.toLowerCase() === "img") {
        e.target.src='rating_color.png';
    }
    e.stopPropagation();
    e.preventDefault();
}

Upvotes: 2

sp00m
sp00m

Reputation: 48807

You could simply add your listeners in a custom function:

function addImgListeners(img) {
    e(img).addEventListener('mouseover', function(event) {
        changeimg_color(img);
    });
    e(img).addEventListener('mouseout', function(event) {
        changeimg_bw(img);
    });
}

Then:

for(var i=1; i<=5; i++) {
    var img = "rating" + i;
    addImgListeners(img);
    // or even addImgListeners("rating" + i);
}

Demo

Upvotes: 1

mohkhan
mohkhan

Reputation: 12305

In JS you can add properties to any object at run time. Using this behavior you can do something like this...

for(var i=1;i<=5;i++) {
    var img ='rating'+i;
    e(img).index = i;
    e(img).addEventListener('mouseover', function(event) {
        changeimg_color("rating" + event.target.index);
    });
    e(img).addEventListener('mouseout', function(event) {
        changeimg_bw("rating" + event.target.index);
    });
}

Upvotes: 1

Related Questions