How to stop event bubbling with jquery live?
Asked Answered
C

7

30

I am trying to stop some events but stopPropagation does not work with "live" so I am not sure what to do. I found this on their site.

Live events do not bubble in the traditional manner and cannot be stopped using stopPropagation or stopImmediatePropagation. For example, take the case of two click events - one bound to "li" and another "li a". Should a click occur on the inner anchor BOTH events will be triggered. This is because when a $("li").bind("click", fn); is bound you're actually saying "Whenever a click event occurs on an LI element - or inside an LI element - trigger this click event." To stop further processing for a live event, fn must return false

It says that fn must return false so what I tried to do

 $('.MoreAppointments').live('click', function(e) {
   alert("Hi");
   return false;
 });

but that did not work so I am not sure how to make it return false.

Update

Here is some more information.

I have a table cell and I bind a click event to it.

 $('#CalendarBody .DateBox').click(function(e)
    {
        AddApointment(this);
    });

So the AddApointment just makes some ui dialog box.

Now the live code(MoreAppointments) sits in this table cell and is basically an anchor tag. So when I click on the anchor tag it first goes to the above code(addApointment - so runs that event first) runs that but does not launch my dialog box instead it goes straight to the (MoreAppointment) event and runs that code. Once that code has run it launches the dialog box from "addApointment".

Update 2

Here is some of the html. I did not copy the whole table since it is kinda big and all the cells repeat itself with the same data. If needed I will post it.

 <td id="c_12012009" class="DateBox">
        <div class="DateLabel">
            1</div>
        <div class="appointmentContainer">
            <a class="appointments">Fkafkafk fakfka kf414<br />
            </a><a class="appointments">Fkafkafk fakfka kf414<br />
            </a><a class="appointments">Fkafkafk fakfka kf414<br />
            </a><a class="appointments">Fkafkafk fakfka kf414<br />
            </a><a class="appointments">Fkafkafk fakfka kf414<br />
            </a>
        </div>
        <div class="appointmentOverflowContainer">
            <div>
                <a class="MoreAppointments">+1 More</a></div>
        </div>
    </td>
Crusado answered 28/12, 2009 at 0:32 Comment(1)
What does your markup look like?Peafowl
V
52

The short answer is simply, you can't.

The problem

Normally, you can stop an event from "bubbling up" to event handlers on outer elements because the handlers for inner elements are called first. However, jQuery's "live events" work by attaching a proxy handler for the desired event to the document element, and then calling the appropriate user-defined handler(s) after the event bubbles up the document.

Bubbling illustration
(source: shog9.com)

This generally makes "live" binding a rather efficient means of binding events, but it has two big side-effects: first, any event handler attached to an inner element can prevent "live" events from firing for itself or any of its children; second, a "live" event handler cannot prevent any event handlers attached directly to children of the document from firing. You can stop further processing, but you can't do anything about processing that has already occurred... And by the time your live event fires, the handler attached directly to the child has already been called.

Solution

Your best option here (so far as I can tell from what you've posted) is to use live binding for both click handlers. Once that's done, you should be able to return false from the .MoreAppointments handler to prevent the .DateBox handler from being called.

Example:

$('.MoreAppointments').live('click', function(e) 
{
  alert("Hi");
  return false; // prevent additional live handlers from firing
});

// use live binding to allow the above handler to preempt
$('#CalendarBody .DateBox').live('click', function(e)
{
   AddApointment(this);
});
Valenzuela answered 28/12, 2009 at 2:13 Comment(2)
Wow that makes so much sense. Now I have to choose what the best answer your answer explains how live works with event bubbling and gives a solution. Or gnarf solution that takes no modifications to my code and works as well but in future cases might now work.Crusado
event.stopPropagation mentions that too: api.jquery.com/event.stopPropagationRiyal
P
7

I've used such kind if code and it worked for me:

$('#some-link').live('click', function(e) {
    alert("Link clicked 1");
    e.stopImmediatePropagation();
});

$('#some-link').live('click', function(e) {
    alert("Link clicked 2");    
});

so, it seems to me, that now JQuery support stopImmediatePropagation with live events

Pneumatology answered 9/8, 2011 at 16:15 Comment(0)
I
5

Maybe you could check that the click event didn't occur on an a element:

$('#CalendarBody .DateBox').click(function(e) {
  // if the event target is an <a> don't process:
  if ($(e.target).is('a')) return;

  AddApointment(this);
});

Might Work?

Iatrochemistry answered 28/12, 2009 at 1:27 Comment(3)
This seems to work just got to do some more testing on it. However I wonder if there could be a situation that the click event is an anchor tag it self and it would stop its self from calling the rest of the code. But then again I don't know anything about this target so this might not be a problem at all.Crusado
Out of curiosity, would this line: if ($(this).is('a')) return; be any different than the one in your answer?Kaete
@Codemonkey - Yes it would be... event.target always points at the actual thing that was clicked on, where this is going to be the .DateBox - the container you bound the event too.Iatrochemistry
Y
3

I'm using this:

if(event.target != this)return; // stop event bubbling for "live" event
Youlandayoulton answered 26/3, 2012 at 9:3 Comment(1)
$('#some-link').live('click', function(e) { if(e.target != this)return; }Youlandayoulton
C
1

I use

e.stopPropagation(); // to prevent event from bubbling up
e.preventDefault(); // then cancel the event (if it's cancelable)
Concerto answered 28/12, 2009 at 1:40 Comment(0)
W
1

I've used this in certain situations. Note: not always applicable, so assess for your needs as always:

html:

<a href="#" className="my-class-name">Click me</a>

js (in your live event handler):

if(e.target.className == 'my-class-name') {
    e.preventDefault();
    // do something you want to do...
}

This way, my live event only 'runs' when a particular element type/classname attr is clicked.

The e.preventDefault() here is to stop the link I'm clicking moving the scroll-position to the top of the page.

Wite answered 28/2, 2013 at 12:51 Comment(0)
F
0
Simply use **"on"** function to bind click event of child as well as parent element.

Example :  $("#content-container").on("click","a.childElement",function(e){
                   alert("child clicked");
                   e.stopPropagation() ; 
                }); 

                $("#content-container").on("click","div.parentElement",function(e){
                  alert("parent clicked");
                }); 
( where content-container is the outer div containing both parent as well as child elements. )

        Here only "child clicked" alert will occur.

    Thanks.
Fulgurate answered 21/8, 2014 at 6:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.