The other answers mostly explain how to fix the closure problem, although such methods are not particularly memory efficient since they end up creating a new closure for each possible combination of i
and j
.
However, since you're using jQuery you have a number of other options available to you:
Pass data
parameters to the .on
call
td.on('click', { i: i, j: j }, function(event) {
var i = event.data.i;
var j = event.data.j;
alert(i + ' ' + j);
});
The i
and j
values as you can see above will be available in event.data
Use $.each
to iterate instead of a for
$.each(Array(5), function(i) {
// i is already bound here because it's a function parameter
$.each(Array(5), function(j) {
// and j available here
td.on('click', ...);
});
});
Use event delegation instead of a per-element handler
$('#myTable').on('click', 'td', function() {
// use jQuery methods to determine the index, e.g.
var j = this.cellIndex
var i = this.parentNode.rowIndex
...
});
which is more efficient than binding a separate handler to each <td>
individually.
and more generically, use .data()
to store per-cell information
You can store data values directly on elements, which would work very well if you wanted to retrieve values other than the cell and row indexes:
td = $('<td>').data({i: i, j: j});
and then extract these row and column values directly from the clicked element's .data
:
for (var i = 0; i < 5; i++) {
var tr = $('<tr></tr>');
for (var j = 0; j < 5; j++) {
$('<td></td>').data({i: i, j: j}).appendTo(tr);
td.appendTo(tr);
}
}
$('#myTable').on('click', 'td', function() {
var data = $(this).data();
var i = data.i;
var j = data.j;
alert(i + ' ' + j);
});