Reputation: 2269
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.
Upvotes: 3
Views: 2226
Reputation: 3372
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.
Upvotes: 5
Reputation: 21881
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);
})
});
Upvotes: 1