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); 
        }

      

+2


a source to share


1 answer


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

.

+2


a source







All Articles