Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2008 (Washington, D.C.) with:

jQuery Live() Method And Event Bubbling

By Ben Nadel on

Recently, there has been a lot of talk in the development community about jQuery's new live() event method. People are just in love with it. If you have not heard of jQuery's live() method, it's an event delegation mechanism that allows you to bind event handlers not just to all existing instances of a given node type, but also to any future instances of a given node type (by "type" I mean a set of DOM nodes matched by a given jQuery selector). This is a very cool thing, both from a development standpoint as well as from a memory and performance standpoint; but, if you don't understand how the live() method works, you might get yourself into trouble.

 
 
 
 
 
 
 
 
 
 

While there is a magical quality to it, under the hood, jQuery's live() method is quite practical. Rather than binding an event handler directly to a given node set, the live() method works by binding event handlers to the document itself and then reacting to all the events that bubble up through the DOM. The actual wiring mechanism is a bit more complicated than that, but in general, you can think of the essence of the live() event cycle as follows:

 
 
 
 
 
 
jQuery Live() Event Method() Works By Using Event Delegation At The Document Level. 
 
 
 

As you can see, the click event on the "A" element bubbles up to its parent element, "P," and then on to its ancestor, the document. At the document level, jQuery then checks the event target against the selector used to define the live() event. If the target matches the selector (or close enough), jQuery then triggers the event handler in the context of the target element.

This event cycle is excellent for event delegation but, it comes with a cost; because it relies completely on the ability for the given event to bubble up to the document object, it is imperative that the bubbling remains in tact. If the event bubbling breaks anywhere within the ancestor chain, the live-bound event handlers will not be triggered. To see this problem in action, take a look at this demo:

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>jQuery Live() Method And Event Bubbling</title>
  • <script type="text/javascript" src="jquery-1.3.2.js"></script>
  • <script type="text/javascript">
  •  
  • jQuery(function( $ ){
  •  
  • // Bind click events to links. This will bind a click
  • // handler to all current links as well as all new
  • // links added to the page.
  • $( "a" ).live(
  • "click",
  • function( event ){
  • alert( "Link clicked!" );
  • }
  • );
  •  
  • // Cancel all click events off of paragraphs.
  • $( "p" ).click(
  • function(){
  • return( false );
  • }
  • );
  •  
  • });
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • jQuery Live() Method And Event Bubbling
  • </h1>
  •  
  • <p>
  • I am a paragraph that contains a <a href="">link</a>.
  • </p>
  •  
  • <p>
  • I am a paragraph that contains a <a href="">link</a>.
  • </p>
  •  
  • <p>
  • I am a paragraph that contains a <a href="">link</a>.
  • </p>
  •  
  • </body>
  • </html>

Looking at the code above, can you see what will happen with one of the "A" tags is clicked?

Nothing.

If you look at the code, you will see that we are using jQuery's live() method to bind a click handler to all the "A" elements. We are also directly binding a click handler to all of the "P" elements. The P-based click handler listens for the click event and then prevents it from being propagated (bubbling up). Now, even though each "P" element is an ancestor of each "A" element, because the live() method depends on event bubbling, the stop-propagation directive kills the live event.

jQuery's live() event method is definitely useful; but, unless you understand how it's working, things can start to fail quite quickly and for no obvious reason.

Tweet This Interesting post by @BenNadel - jQuery Live() Method And Event Bubbling Thanks my man — you rock the party that rocks the body!



Reader Comments

Have you seen the livequery() plugin? It's similar, but its internals are a bit different, allowing it to do certain things that live() cannot. For example, live() won't work with events like blur, focus, change, etc., whereas livequery does (or at least it does with focus and blur, the two I've used). There's a decent explanation here: http://www.neeraj.name/blog/articles/882-how-live-method-works-in-jquery-why-it-does-not-work-in-some-cases-when-to-use-livequery

Reply to this Comment

@Thomas, I believe jQuery 1.4 (yet to be released) will support both the blur and focus events in its "live" mechanism.

Reply to this Comment

Ben, when I listened to your video, I was taken back at your pronunciation of live(). Since the word is a Heteronym http://bit.ly/heteronym it could be pronounced as the verb "l?v" or the adjective "la?v". I always assumed the later, but you've adopted the prior. You're probably right, but I'm very interested to know what anyone else thought.

Reply to this Comment

@Luke,

To be honest, it was *painful* to pronounce it the way I did :) When I see that word, everything in my wants to pronounce it as "L'eye've". People tell me this comes as a hold-over from "liveQuery", which prople pronounced "L'iv Query". I only recently changed my pronunciation because someone told me it was wrong... but I don't care for it :)

Reply to this Comment

Hmmm... Ok, I always pronounced it live-rhymes-with-give (I mean, c'mon - it's live & die!), but after arguments with a live-rhymes-with-jive colleague we went out searching.(Which you could read about here: http://www.mrspeaker.net/2009/11/12/how-to-pronounce-live/ )
Brandon Aaron says, via Twitter, that it's "live as in 'live broadcast' :)"

Do you think he's wrong, and that I might still have a chance of turning the tables on my nemesis?!

Reply to this Comment

In 1.4 you can bind a parent element as the context, which would essentially allow you to avoid the bubbling problem if you had some parent returning false.

Of course, if your parent is a parent of an element that returns false on the same event as the deepest effected element, there will still be problems b/c you cannot stopPropogation, but that's usually a very rare case.

Reply to this Comment

@Weixi,

Yes, good point. In 1.4, the binding methods have gotten better with the context stuff in delegate().

Reply to this Comment

It's live as in "Saturday Night Live". Because it is an adjective. (Meaning something is ongoing or current, similar to "alive")
"The events are live."

In "Live and Let Die", live is a verb. (to live)
"The events hooks live on after document.ready is finished."

Anyway, does anyone know how to respond to a $("a.blah").live.click event and cancel the actual click? (eg like returning false from a conventional click handler)
For live.click it seems to start processing the page load as it starts running the handler :(

Reply to this Comment

@Beetlefeet,

I had thought that returning false would work. You might have to rely on event.preventDefault() in a live() method - I can't remember.

Reply to this Comment

Is there a way to prevent .live from attaching the event multiple times?

I mean you can accomplish this by creating a singleton module and making sure you event initialize only once but I was wondering if there was something built in that in fact prevents the method from reattaching multiple times

Reply to this Comment

@Virgilio,

I don't think there's any way to prevent this (implicitly) only because you can have multiple callbacks attach themselves to a live-binding events (or any event binding for that matter). I suppose that jQuery could check to see if the given callback has already been bound to a given event by looping over the existing callbacks; but I assume they don't do that for performance reasons.

What kind of a situation are you in where things are getting bound more than once? Perhaps we can come up with a better approach to event binding.

Reply to this Comment

Hi Ben,
thanks for the quick response.
well basically I'm working on an application where I need to use .live for most of our handlers. Our layout is like this, we have an index page that can have multiple partials as children views(tabs).
We just refactored this and establish the pattern of centralizing .live events into one single file file so it loads only once when the parent page loads as before each partial would load its .live events every time when navigating to them so our click events would fire multiple times. We stopped the firing by returning false on each live event but still we wanted to ensure that we wouldn't attach event more than once.

Reply to this Comment

@Vrigilio,

Ah, OK, I see what you're saying. Yeah, to deal with content like tabs that might be loaded multiple times, I guess you'd have to either centralized (either at the page level or the module level (ie. the tabs module)), or deal with unbinding events when the content is removed.

Reply to this Comment

I came here to find out more about Event Bubbling and now seem to be lost again. Have to look at the video again, and read just Ben's blog ONLY.

I have to remember not to read the comments. I always get lost in the comments. It seems like they never do any good and I always forget what the main idea was anyway.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.