Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery: Event Bubbling and how "click", "live.click", "stopPropagation", and "return false" work together

Tags:

jquery

I will have couples scenario here. Please help me

Here is the base case: http://jsfiddle.net/2zsLy/9/

When I click Click Me, both alert box and Another Paragraph come out. This is expected since the click event bubble up to the parent container, which is body. Now start my questions

1) http://jsfiddle.net/2zsLy/10/

How come adding return false to my live.click does not stop the click event from bubble up. From the example, the live.click bubble up and trigger the alert box. I thought the documentation said that return false will stop the live event from bubble.

2) http://jsfiddle.net/2zsLy/11/

Now, I change the click event in body to live.click and it fix the problem -> the click event does not bubble up (hence no alert box is shown). Why does live.click work and click does not.

3) http://jsfiddle.net/2zsLy/13/

I think the documentation clearly said that calling event.stopPropagation() will not stop the bubbling up from occurring, well I just did. I use event.stopPropagation() expecting that it will still trigger my alert box, but it does not. Why?

NOTE: for the answer of the first two question, see justkt answers. For the answer to the last question, see Squeegy answer and his reply.

like image 739
Thang Pham Avatar asked May 03 '11 17:05

Thang Pham


2 Answers

Answers to your questions can be found in the event.stopPropagation() docs.

With regards to live('click') versus 'click' and bubbling:

Since the .live() method handles events once they have propagated to the top of the document, it is not possible to stop propagation of live events. Similarly, events handled by .delegate() will always propagate to the element to which they are delegated; event handlers on any elements below it will already have been executed by the time the delegated event handler is called.

So what you are seeing is expected behavior. live('click') won't stop bubbling. The same is true of the now-preferred .delegate().

This answer describes extensively the problems of stopping propegation when using .live. See also the .live() documention:

The event bubbles up until it reaches the root of the tree, which is where .live() binds its special handlers by default.

  • As of jQuery 1.4, event bubbling can optionally stop at a DOM element "context".

With regards to stopPropagation itself:

Kill the bubbling on the click event.

So stopPropagation() should prevent bubbling wherever return false; will, although not where it won't. It is preventDefault() that will not prevent bubbling. return false; is effectively stopPropagation() and preventDefault().


In response to each jsfiddle example.

1) http://jsfiddle.net/2zsLy/10/

return false; will not prevent events bound using live or delegate from bubbling up. The documentation explicitly says this about all bubbling, whether done with return false; or with stopPropagation(). So what happens is

  1. Click on <p>
  2. Click bubbles to <body>, where body.click() is triggered
  3. Click bubbles to document root, where it matches $(event.target).closest('p'); and so live('click') is invoked
  4. Return false happens, but body handler was invoked at step 2

2) http://jsfiddle.net/2zsLy/11/

In this case the event gets to the same spot (document root) and the return false stops the propagation to the further event bound via live, which is on the body.

  1. Click on <p>
  2. Click bubbles to <body>, but since body's handler is attached via live it is not invoked yet
  3. Click bubbles to document root, where it matches $(event.target).closest('p'); and so live('click') is invoked
  4. Return false happens
  5. live('click') is not invoked on the body due to the return false occurring.

3) http://jsfiddle.net/2zsLy/13/

stopPropagation() is explicitly used to prevent bubbling, although it has the same restrictions return false; does - so it won't prevent it in the case of a live('click') event if there are click handlers bound via bind.

like image 140
justkt Avatar answered Sep 24 '22 10:09

justkt


  1. Live events ALWAYS happen after bind events (like calling click(fn)). So return false does nothing here because $("body").click() already happened. This is due to bubbling. The click happens on each parent of the element you clicked, triggering every click event. Only when it bubbles up to the root document, does it trigger any live events.

  2. In this example, you have 2 live events. So the event bubbles up to the document, and jQuery starts running any live events it finds that match your click. When it gets a return false it stops running any other live events. And live events declared first, run first. So you get the new paragraph, but nothing else since the alert was added to the live event stack AFTER the p live click.

  3. It wont stop propogation for bind events, but the event argument is actually a jQuery event wrapper object, and I believe it knows about live. So it has a similar effect as returning false, it prevents the document click handler from executing any additional live events.

like image 45
Alex Wayne Avatar answered Sep 25 '22 10:09

Alex Wayne