Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript - Issue with scope and passing parameters to dynamically created event handler

In the code below you will see that I am trying to define an event handler for image.onclick which takes extra parameters, i was declaring those parameters inside of the while loop hoping javascript defined scope this way but it does not. Basically all of the event handlers here are getting the very last value that i give to variables id and section_id. Any idea on how to handle a situation where i want to be generating these handlers dynamically?

function handlePicturesResult(){
    if (req.readyState == 4) { // Complete
        if (req.status == 200) { // OK response

            var el = document.getElementById('pictureHolder');
            while( el.hasChildNodes() ){
                el.removeChild(el.lastChild);
            }

            var tempObject = JSON.parse(req.responseText);
            var pictures = tempObject.images;
            var i=0;

            while(i<pictures.length){

                var picIndex = i;

                var image= new Image(120,80);
                image.src = 'images/' + pictures[i].url;
                image.width = 120;
                image.height = 80;
                var id = pictures[picIndex].id;
                var section_id = pictures[picIndex].sectionId;
                image.onclick = function(event){
                    deleteImage(event,id,section_id);
                }


                var txtNode = document.createTextNode(pictures[picIndex.valueOf()].id); 
                el.appendChild(image);
                el.appendChild(txtNode);
                i++;
            }
        } else {
        alert("Problem: " + req.statusText);
        }
    }

}
like image 925
flips Avatar asked Jun 01 '12 19:06

flips


1 Answers

Yet another problem solved by closures!

image.onclick = function(id, section_id){
    return function(event) {
        deleteImage(event,id,section_id);
    }
}(id, section_id);

The outer function is run at once (notice the parentheses with arguments at the end), and it returns the inner function, which keeps in its scope a copy of the variables as they are at that iteration of the loop.

JavaScript passes non-object variable by value, so by passing id and section_id to the outer function, you create a copy of them inside that function. When you create and return the inner function, that inner function keeps in scope all variables that are in scope at the time of its creation (this is at the heart of what a closure is), including the local-variable copies of id and section_id. The inner function, with its unique scope, becomes the event handler for that element.

like image 106
apsillers Avatar answered Oct 12 '22 08:10

apsillers