Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery detecting click interactions on nested elements causing huge loop

Attempting to add a click event to a button that is nested between multiple elements (ul, div.col, li, div.panel, div.panel-body). I am able to access it with the below code, however as if I click on the page more than a few times the console.logs begin to loop and execute thousands of times.

I am nearly positive it is the nesting of the functions causing this. But I do not have a thorough enough background in JQuery to be able to tell exactly what the browser is doing.

Here is my JQuery code:

        $('#displayList #col1').click(function(){
        console.log('clicked col');
        $('li').click(function(){
            var id = $(this).attr('id');
            console.log(id);
            $('div.panel').click(function(){
                console.log('clicked panel');
                $('div.panel-body').click(function(){
                    console.log('clicked panel body');
                    $('button').click(function(){
                        console.log('clicked button');
                        return;
                    });
                    return;
                });
                return;
            });
            return;
        });
        return;
    });   

Could one of you wonderful JQuery gurus explain what is causing this bug and point me in a better path for checking if the button has been clicked or if it hasnt(just the panel was clicked).

Also, does anyone know a good and preferably free debugging program that I can use to step through JQuery code execution by execution?

Thank you so much for your knowledge

like image 644
Bill Headrick Avatar asked Mar 15 '26 12:03

Bill Headrick


2 Answers

You are binding an event handler inside another event handler. So whenever the later event occurs, new handlers are added, Eventually causing multiple handlers for same event on same element.

Your code should look something like

$('#displayList #col1').click(function(){
    console.log('clicked col');
});
 $('li').click(function(){
    var id = $(this).attr('id');
     console.log(id);
});
$('div.panel').click(function(){
     console.log('clicked panel');
});
$('div.panel-body').click(function(){
      console.log('clicked panel body');
});
$('button').click(function(){
      // The following will be executed when the button is clicked 
      console.log('clicked button');
});

Assume you have the following markup:

<div id="container>
  <div id="parent">
    <button>Click Me!</button>
  </div>
</div>

And the event handlers:

$("#container").click(function(){
  console.log("container got a click!");
});
$("#parent").click(function(){
  console.log("parent got a click!");
});
$("#parent button").click(function(){
  console.log("button got a click!");
});

Now if you click the button output will be

//button got a click!
//parent got a click!
//container got a click!

When you click an element, all of it's ancestors will also receive a click event by default, and the corresponding event handler will be called, if any - This is called event bubbling. If you don't need any specific functionality then you don't need a handler so bubling won't hurt.

However, You can prevent this behaviour by calling the stopPropagation() method of event object inside the event handler:

$("#parent button").click(function(e){
      e.stopPropagation();
      console.log("button got a click!");
});

output will be

//button got a click!

There is one more event propagation method in some browsers (Only event bubbling model is supported by all the major browsers), you can read about it in detail @quirksmore: Event order

As DFTR mentioned in comments,

Visual studio allows break points in javascript code, when launching an application within internet explorer. Another debugging tool is firebug, which is a pretty neat firefox extension

like image 96
T J Avatar answered Mar 18 '26 03:03

T J


Might help you.

if you need to bind event to button, you should use descendant selector

$('#displayList #col1 li div.panel div.panel-body button').click(function() {
    console.log('clicked button');
});
like image 32
Satpal Avatar answered Mar 18 '26 01:03

Satpal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!