Building out .live() and .die()

Building out .live() and .die()

In building a large Rails 3 / jQuery application, I've been running into some limitations of jQuery's .live() and .die() methods. 

For anyone who is unfamiliar, Rails 3 uses .live() extensively to enable all the AJAX functionality for an app.

The Problem:

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

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

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

Making lines 9 and 10 work:

I rewrote part of the .die() method so that the two functions on lines 9 and 10 work as expected. In addition to unbinding exact matches (what line 13 currently does), line 9 essentially appends ':not("a")' to partial matches. So,  $('a,form').live( 'click', ...) becomes  $('a,form:not("a")').live( 'click', ...). 

The new .die() method is smart enough to know which live-bindings to append, based on matching only the applicable selectors, events, and event-namespaces. 

So, $('a).die() would leave $('form').live() un-touched, since they're mutually exclusive selectors. Likewise, $('a').die('hover') would leave $('a').live('click') un-touched since they're mutually exclusive events. It only appends if the selector/event/namespace combination are not mutually exclusive.

Why this is useful:

The .die() method is not a popularly used method yet. However, with the growing popularity of Rails 3, which uses .live() for all the AJAX functionality by convention, it's useful to allow developers to easily unbind the AJAX calls for specific elements, or after the AJAX call has already been made. The only way to do this currently is to 'return false' to stop the bubbling of the event on the target element itself, which causes other negative side-effects, or to unbind the live-bindings for ALL remote link and form elements.

I updated the rails.js UJS driver to namespace all of the live-bindings with the "rails" namespace, and it was recently pulled into core: See commit

If we pulled this into jQuery core, we could now do something like:

  1. // In rails.js:
  2. $('a[data-remote]').live('click.rails', ...);

  3. // Then elsewhere in the application
  4. $('a#no-more-ajax').die('rails');

Anyway, I suppose my question is, would there be any interest in pulling this into core? If so, I will go ahead and finish writing the tests for the new functionality and submit a pull request. 

If anyone else is interested in helping out, coming up with test cases and whatnot, that'd be cool too. For instance, one thing I haven't accounted for yet is what happens if you try to re-bind a live handler on something you just die'd. E.g.:

  1. // In rails.js:
  2. $('a[data-remote]').live('click.rails', ...);

  3. // Then elsewhere in the application
  4. $('a#no-more-ajax').die('rails');

  5. // Now, to re-bind, we need to find and remove any ':not("a#no-more-ajax")' selectors from 
  6. // 'click.rails' live-bindings in addition to creating a new live-binding.
  7. $('a#no-more-ajax').live('click.rails', ...); 

Sorry for the long post. I hope it wasn't too dry. Let me know what you think.

-Steve