0

I am trying to set an onclick event for thumbnails that are dynamically populated from a database. I need to set the function to handle an argument, which is the id of the bigger picture the thumbnail represents. The code I have now sets all the thumbnails to point to #18. If you see in the for-loop, it is supposed to die at 17:

for (var i = 0; i < 18; i++) {
    document.getElementById('tat' + i).onclick = function() { display(i); }; 
}

(My thumbnail <img />s all have id="tat0", id="tat1", id="tat2", id="tat3" etc.) (display() loads the larger pic that the thumbnail represents into a separate element)

Each thumbnail gets this onclick function, so I know the for loop is accessing each one by its ID properly (stepping through for each i) so why are all the display(i) being assigned to 18? Can you assign an onclick function to handle parameters?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
BillyNair
  • 277
  • 4
  • 20
  • possible duplicate of [Javascript infamous Loop problem?](http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem) – Felix Kling Feb 27 '12 at 12:55
  • Bottom line of the problem: Each event handler references the same `i`. After the loop finished, `i` has the value `18`. The solution is to generate event handlers which do not share the same variable. This is neither related to `getElementById` nor `onclick`. – Felix Kling Feb 27 '12 at 13:00
  • You are right, I had to pull back and come at it a different way: function initOnClick(){ var images = document.getElementById("thumbs").getElementsByTagName("img"); for (var t=0; t < images.length; t++){ images[t].onclick = function() { var id = this.id.substr(3); display(id); } } } – BillyNair Apr 14 '12 at 18:59

3 Answers3

1

You need a closure function to generate your handlers.

function genHandler( param ) {
  return function() {
     // use all params in here
     display( param );
  }
}

and then assign your events similarly

for (var i = 0; i < 18; i++) {
  document.getElementById('tat' + i).onclick = genHandler( i );
}
Sirko
  • 72,589
  • 19
  • 149
  • 183
  • "You need a closure function to generate your handlers". The OPs event handler is a closure as well. In your code, `genHandler` is actually not a closure. – Felix Kling Feb 27 '12 at 12:57
0

It might also work, if you just add 'i' as a parameter to your function.

torbenl
  • 296
  • 2
  • 6
  • Which function? You mean `function(i) { display(i); };`? That won't work. The first argument passed to an event handler is the event object, if any (IE). – Felix Kling Feb 27 '12 at 12:57
  • You are right... A hack: `function() { display(this.id.substr(3)); };` could be used, if the ids are of type 'tat0', like yours. – torbenl Feb 27 '12 at 13:36
0

Wrapping your onclick handler in a function will create a closure that carrys the current scope with it.

for (var i = 0; i < 18; i++) {
    document.getElementById('tat' + i).onclick = (function(a) {
        return (function() {
            display(a);
        });
    })(i);
}​
Sam Greenhalgh
  • 5,952
  • 21
  • 37