I'm trying to bind event handlers within a loop such as:
var tabs = ['one', 'two', 'three', 'four']
for(var i = 0; i < tabs.length; i++) {
alert(tabs[i]);
var id = i;
$('#' + tabs[i]).bind('click', function() {
loadTabs(id, tabs);
});
}
Which only keeps the last one bound (value 'four').
I'm trying to consolidate this code which currently does work:
$('#one').click(function() {
loadTabs(0, tabs);
});
$('#two').click(function() {
loadTabs(1, tabs);
});
$('#three').click(function() {
loadTabs(2, tabs);
});
$('#four').click(function() {
loadTabs(3, tabs);
});
Thought I might need a closure due to this post.
You are right about what you read in the other post.
You need to make a closure to bind the arguments to each single onclick handler:
$('#' + tabs[i]).bind(
'click',
(function(id) {
return function()
{
loadTabs(id, tabs);
};
})(id)
);
You might also want to look into currying.
In this example you might create a small helper function, which binds the first argument to a passed function and returns the new function.
function curry(func, arg1)
{
return function()
{
func(arg);
};
}
And then put it together like this:
$('#' + tabs[i]).bind(
'click',
curry(function(id) { loadTabs(id); }, id)
);
Note that my curry function does not match the definition of currying, because it ignores any other argument. But it should work for your case.
As you are already using jQuery you can use jQuery.each for this task. Therefor you won't need to do it yourself with, as you correctly assumed, closures
.
var tabs = ['one', 'two', 'three', 'four'];
$.each(tabs, function(idx, tab) {
$("#" + tab).on("click", function() {
alert(idx);
//loadTabs(idx, tabs);
})
});
jsfiddle