0

i've this sample code where i have a set of images that i create dinamically and set to each of them an onclick addlistener with certain params. The problem is that all of them when the onclick is set popups always the values of the last image.

Any ideas why i can't set individually and dinamycally a listener to each of them?

Thanks.

Fully functional code below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title></title>
    <script type="text/javascript">

function image() {
var shared = eval([{"img":"9","ext":"jpg"},{"img":"8","ext":"jpg"},{"img":"20","ext":"jpg"},{"img":"24","ext":"png"}]);
var divShared = document.getElementById('image');
for(x in shared){         
   var img = document.createElement("img");
   img.id = "img_"+shared[x].img;
   img.style.width = "30px";
   img.style.height = "30px";
   img.style.cursor = "pointer";
   img.style.marginLeft = "15px";
   var url = "http://www.kakuylive.com/fotos/user_"+shared[x].img+"."+shared[x].ext;
   img.src = url;    
   document.getElementById('image').appendChild(img);                          
   document.getElementById("img_"+shared[x].img).addEventListener('click', function() { openSharedUserInfo(shared[x].img,shared[x].ext)},false);  
}
}

function openSharedUserInfo(id,ext){
  alert(id+" :: "+ext);
}
</script>
</head>

<body>
<div id="image" style="margin-bottom:15px"></div>
<div><a href="javascript:image();">click to see image</a></div>
</body>
</html>
Tony
  • 3,425
  • 10
  • 30
  • 46
  • This is probably not what you want to hear but I'd set an eventlistener on the containing (e.g. parent) element and then figure out what element was clicked. This is called `event propagation` or `event bubbling` and you can find some more [here](http://stackoverflow.com/a/6945909/215042) and [here](http://www.quirksmode.org/js/events_order.html). Other than that; your code might need a bit more reviewing since I see some other issues as well. – RobIII Feb 19 '14 at 02:17

1 Answers1

2

Notice the immediately invoked function(IIFE) as the first line of the looping code, that will give you an extra "level" of scope so that the x you refer to will be the one you think it is when the event fires.

This is a classic closure problem as seen here. The code below should fix the problem you are immediately having.

for (x in shared) {
   (function(x) {
      var img = document.createElement("img");
      img.id = "img_" + shared[x].img;
      img.style.width = "30px";
      img.style.height = "30px";
      img.style.cursor = "pointer";
      img.style.marginLeft = "15px";
      var url = "http://www.kakuylive.com/fotos/user_" + shared[x].img + "." + shared[x].ext;
      img.src = url;
      document.getElementById('image').appendChild(img);
      document.getElementById("img_" + shared[x].img).addEventListener('click', function() {
         openSharedUserInfo(shared[x].img, shared[x].ext)
      }, false);
   }(x))
}

function openSharedUserInfo(id, ext) {
   alert(id + " :: " + ext);
}

Other Notes

You shouldn't be using a for in loop when looping over an array; a standard for loop is preferred for performance reasons. You shouldn't need to do getElementById again because you already have the DOM element "on hand" since you are creating it in this function.

Community
  • 1
  • 1
arb
  • 7,753
  • 7
  • 31
  • 66