How to stop event bubbling with jquery live?

chobo2 picture chobo2 · Dec 28, 2009 · Viewed 22.8k times · Source

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>

Answer

Shog9 picture Shog9 · Dec 28, 2009

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);
});