AddEventListener pass caller as argument
I have the following code. And my problem is that when clicked, the event is triggered, but the passed argument is wrong. It passes in the last dynamically generated string, that is, the value of dataStructure.length. Does anyone know how to get around this?
var table = document.getElementById('output');
for(i =0; i<dataStructure.length; i++){
var row = document.createElement('tr');
row.setAttribute('id', i);
var url = dataStructure[i].url;
if(document.addEventListener)
row.addEventListener('click', function(){handleRowClick(i);}, false);
var obj = dataStructure[i];
var cellCount = 0;
for(field in obj){
var cell = document.createElement('td');
cell.setAttribute('id', cellCount++);
//cell.addEventListener('click', function(){window.open(dataStructureObj.links[i].url);}, false);
cell.innerHTML = obj[field];
row.appendChild(cell);
}
cellCount = 0;
table.appendChild(row);
}
}
function handleRowClick(rowClicked){
var rowHTML = rowClicked.innerHTML;
var cells = rowHTML.getElementsByTagName('td');
for(cell in cells)
{
alert(cell.value);
}
window.open(cells[1].innerHTML);
}
a source to share
i
c function(){handleRowClick(i);}
is a loop variable i
. When the function is called, the loop is long and i
contains the last value it executed at the end of the loop, not the value it held when it was created function(){}
.
This is a closed loop problem. See this question for solutions using either closures or Function#bind
:
row.addEventListener('click', handleRowClick.bind(window, i), false);
However, you are not using this one at the moment i
. It would be easier to say:
row.addEventListener('click', handleRowClick, false);
and then use this
to extract the string:
function handleRowClick(){
window.open(this.cells[1].innerHTML);
}
(Side note: unfortunately, if you add a fallback attachEvent
for IE <= 8 support, it won't get this
to the right, so you'll still be looking at closures / anchors to get the object you want.)
and
for(i =0; i<dataStructure.length; i++){
None var
: i
is random global.
row.setAttribute('id', i);
Avoid getAttribute
/ setAttribute
in HTML documents. They don't do what they should in IE. Instead, use the properties of the HTML DOM level 2, they are more reliable and readable: row.id= i
.
a source to share