Andru
Andru

Reputation: 7131

jQuery/JavaScript: Event handlers only assigned during the last iteration of a loop

I'm having a problem whereby a loop which is instantiating two objects, which in turn create elements and attach event handlers, only actually attach the event handlers for the last iteration of the loop. While I'm aware of issues with scope inside anonymous functions in a loop, I can't see how that is applicable here, and I'm left scratching my head...

So, first, a setContent method of a view object iterates over an array of content, and creates two instances of the CrowdControl.ui.Button object: (irrelevant code removed for clarity)

setContent: function(content){
    if(content.length > 0){
        for(var i in content){
            var c = content[i];

            var container = $('<div></div>');

            //content array code removed for clarity

            var reject = new CrowdControl.ui.Button({label:'Reject'});
            var approve = new CrowdControl.ui.Button({label:'Approve'});

            container.append(reject.draw());
            container.append(approve.draw());

            this.contentlist.addItem(container);


        }
    }
}

Here is the Button object (again some code removed for clarity)

CrowdControl.ui.Button = function(){
    this.uniqueId = Math.random(); //added for debugging
    var els = this.elements = {}
    els.container = $('<div class="cc-button"></div>');
    els.label = $('<div></div>').text('Debug'); 
    els.container.append(els.label);
}
CrowdControl.ui.Button.prototype.draw = function(){
        console.log('Drawing element '+this.uniqueId);
        var els = this.elements;
        els.container.remove();

        console.log('Binding click to button');
        console.log(els.container); 

        //attach the click handler - this will only attach during the last iteration
        els.container.click( function(){ console.log('wtf'); });

        return els.container;
}

The above code logs that all the elements are made, and they're all unique, but only the last two instances of the Button object receive the event handlers and log 'wtf' when clicked.

Any help would be hugely appreciated - if you need any more code or explanation just ask...

Upvotes: 1

Views: 309

Answers (2)

Andru
Andru

Reputation: 7131

Thanks for the help Neal. It actually turned out the problem was elsewhere in my framework, where a view was incorrectly redrawing after each iteration, and calling .remove() each time, which was of course removing the event handlers from child elements.

Upvotes: 0

Naftali
Naftali

Reputation: 146310

I fixed you code: http://jsfiddle.net/maniator/E8XcQ/6/

Click should be done like this:

//attach the click handler 
$(els.container).click(function() {
    console.log('wtf');
});

You accidentally attached the click to the DOM element and not the jQuery element

Upvotes: 2

Related Questions