I am having the code below and javascript's closure together with anonymous functions are giving me a headache.
for (var i = 0, len = sites.length ; i < len ; i++)
{
$("#thumb"+i).click(function() { $("#shader").show(); $("#thumbInfo"+i).show(); alert("#thumbInfo"+i); });
$("#thumbInfo"+i+" .xbutton").click(function() { $("#shader").hide(); $("#thumbInfo"+i).hide(); });
}
Due to closure, i is always 5 (the sites array has 5 elements), so all the click handlers refer to the same id.
Any workaround?
You could always loop with jQuery's each()
.
$.each(sites, function(i) {
$("#thumb"+i).click(function() { $("#shader").show(); $("#thumbInfo"+i).show(); alert("#thumbInfo"+i); });
$("#thumbInfo"+i+" .xbutton").click(function() { $("#shader").hide(); $("#thumbInfo"+i).hide(); });
});
use a closure in your for iteration:
for (var i = 0, len = sites.length ; i < len ; i++)
{
(function(i) {
$("#thumb"+i).click(function() {
$("#shader").show();
$("#thumbInfo"+i).show();
alert("#thumbInfo"+i);
});
$("#thumbInfo"+i+" .xbutton").click(function() {
$("#shader").hide();
$("#thumbInfo"+i).hide();
});
}(i));
}
Place a function returning a function and parameterized by i
outside the loop. JSLint will encourage you to do this anyway, and some might find it more readable to boot.
function make_fn1(i) {
return function() { $("#shader").show(); $("#thumbInfo"+i).show(); };
}
function make_fn2(i) {
return function() { $("#shader").hide(); $("#thumbInfo"+i).hide(); };
}
for (var i = 0; i < sites.length ; i++)
{
$("#thumb"+i).click(make_fn1(i));
$("#thumbInfo"+i+" .xbutton").click(make_fn2(i));
}
However, this could be cleaned up in other ways. For starters, as long as you're using jQuery, $("#shader, #thumbInfo"+i).show();
is more concise. Furthermore, in the current code the notion that the two functions either hide or show the same two elements is not factored out, so could be
function make_fn (i,showhide) {
return function() { $("#shader, #thumbInfo"+i)[showhide]() };
}
for (var i = 0; i < sites.length ; i++)
{
$("#thumb"+i).click(make_fn(i,'show'));
$("#thumbInfo"+i+" .xbutton").click(make_fn(i,'hide'));
}
var len = sites.length ;
for (var i = 0; i < len ; i++)
{
$("#thumb"+i).click(function() { $("#shader").show(); $("#thumbInfo"+i).show(); alert("#thumbInfo"+i); });
$("#thumbInfo"+i+" .xbutton").click(function() { $("#shader").hide(); $("#thumbInfo"+i).hide(); });
}
you might have been assigning 5 to i;