Exploring jQuery .live() and .die()

05 October 2010

jQuery .live(), .die()

Most developers I talk to have limited knowledge of jQuery's .live() function. Typically they know what it does, but not how it works, and thus are not entirely comfortable using it. And usually they've never heard of .die(), which unbinds .live() events.

Even if you are familiar with these, are you aware of the problem with .die()?

What is .live()

The .live() function is similar to .bind(), except that it allows you to bind events to DOM elements now and in the future; you can bind events to elements that don't exist yet in the DOM. Consider the following example.

Let's say you want to warn the user that they're about to leave your site when they click on any link:

$(document).ready( function() {
  $('a').click( function() {
    alert("You are now leaving this site");
    return true;
  });
});

Note that the .click() method is merely a convenience method for the more general .bind() method, so the following is equivalent to above:

$(document).ready( function() {
  $('a').bind( 'click', function() {
    alert("You are now leaving this site");
    return true;
  });
});

But now, let's say you add another link to the page via javascript.

$('body').append('<div><a href="...">Check it out!</a></div>');

Now, when the user clicks that link, your function will not get called, because that link did not exist when you bound your click event to all the <a> nodes on the page. So we simply replace .bind() above with .live():

$(document).ready( function() {
  $('a').live( 'click', function() {
    alert("You are now leaving this site");
    return true;
  });
});

Now, if you add a new link to the page, this binding will work for it as well.

How .live() works

The magic sauce behind .live() is that it doesn't bind the event to the elements you selected. It actually binds the event to the root node of the DOM tree (in our case, the $(document)), passing in your element selector as a parameter.

Then, when you click an element, the click event bubbles up the DOM tree, until it hits the root node. This triggers the .click() event that was created on the root node by .live(). This triggered function first evaluates the clicked target to see if it matches the selector for which the .live() was called. So, in the example above, it checks if the element you just clicked matches the $('a') element you specified in $('a').live();. If the element you clicked matches the selector, then the bound function executes.

Because the root node's .click() event is triggered no matter what you click within the root node, this check happens even when you click on something that you just added to the root node.

Anything .live() can .die()

If you know about .bind(), then you surely know about .unbind(). Well .die() is the analogous compliment to .live().

In order to unbind the example from above (so, we don't want to alert users anymore when they click links), we'd simply do the following.

$('a').die();

More specifically, we could unbind only the live click bindings, if we had other live event bindings we wanted to keep, like hover or something.

$('a').die('click');

Even more specifically, if we had specified a named function, we could unbind only that function for only that event type.

specialAlert = function() {
  alert("You are now leaving this site");
  return true;
}

$(document).ready( function() {
  $('a').live( 'click', specialAlert );
  $('a').live( 'click', someOtherFunction );
});

// then somewhere else, we could unbind only the first binding
$('a').die( 'click', specialAlert );

The problem with .die()

When using these functions, there is one major shortcoming to the .die() method. You can ONLY use it for the exact element selector for which the .live() function was invoked. For example, you CANNOT do the following:

$(document).ready( function() {
  $('a').live( 'click', function() {
    alert("You are now leaving this site");
    return true;
  });
});

// it would be nice if we could then choose specific elements
//   to unbind, but this will do nothing
$('a.no-alert').die();

See, the .die() event looks for bindings on the root node that were created with .live(), then checks which ones match the target selector, and removes them. But in the above example, no live bindings exist for $('a.no-alert'), so jQuery does not find anything to remove, and so nothing happens.

Even worse, consider the following:

$(document).ready( function() {
  $('a,form').live( 'click', function() {
    alert("You are going to a different page");
    return true;
  });
});

// NEITHER of these will work
$('a').die();
$('form').die();

// ONLY this will work
$('a,form').die();

How to fix .die()

In my next article, I will propose a new way for .die() to work, which could provide this expected behavior, while being totally backwards compatible. Maybe if I have time, I could even convince the amazing jQuery core team to accept my changes for the next release.

There's a little more to these methods than I've discussed here, including the optional context parameter, which allows you to specify the node to which the event attaches, instead of the root node.

For more info and examples, check out the documentation for jQuery .live() and .die().

Also, be sure to check out .delegate() and .undelegate(), which are closely related and can be and attractive alternative to .live() and .die().

About the author:

Steve Schwartz // Owner of Alfa Jango Web-based Software, creator of RateMyStudentRental & LeadNuke, engineer, hacker, rubyist, guitarist, aspiring racecar driverist.



Comments are loading...