Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery, click event, too much recursion

Tags:

jquery

click

Could somebody tell me why this code:

$('#places-view > tbody').find('td').click(function(evt) {
    var td = $(this),
        input = td.find('input');
        console.log('click');
        console.log(input.attr('disabled'), 'disabled');
        if (! input.attr('disabled')) {
            input.trigger('click');
            console.log('inner click');
        }
})

throwing too much recursion error...

Regards

like image 253
Marek Avatar asked Jun 27 '10 13:06

Marek


2 Answers

To prevent event bubbling, place event.stopPropagation() in the handler for your input element's click event.

$('#places-view input').click(function(event) {

      // This will prevent the click event from bubbling up and firing
      //    the click event on your <td>
    event.stopPropagation();

      // run the rest of your click code
});

http://api.jquery.com/event.stopPropagation/


EDIT: As @Pointy noted, it may be your intention to have the same handler handle both events, or at least have the td handler still fire when you click the input.

If that's the case, you'll just need to check to see if the td handler was fired by a click on the input, and if so, prevent the input.trigger("click") from running:

$('#places-view > tbody').find('td').click(function(evt) {
    var td = $(this),
        input = td.find('input');
        console.log('click');
        console.log(input.attr('disabled'), 'disabled');
        if (! input.attr('disabled')) {
                // If the target of the click was not the input,
                //   then trigger the click on the input
            if( input.not( evt.target ).length ) {
                input.trigger('click');
                console.log('inner click');
            }
        }
});

Another way to do the test would be:

if(input[0] != evt.target) {...

Both of these approaches assume that there's just one input. If that's not the case, then you'll need to give the input an identifier to allow the test to be more specific.

like image 62
user113716 Avatar answered Oct 17 '22 14:10

user113716


When you trigger the "click", it's not really a separate event dispatch loop — jQuery is going to run the handlers right there and then. Since your <input> is inside your <td>, the event is going to bubble out to the <td> itself, where it'll run smack into that handler again.

Also note that this line here:

console.log(input.attr('disabled'), 'disabled');

is maybe not what you want - I think that'll always log the word "disabled". Maybe you meant

console.log(input.attr('disabled') + ' disabled');
like image 30
Pointy Avatar answered Oct 17 '22 14:10

Pointy