Agnostic Unobtrusive JavaScript

A few weeks ago I wrote about Unobtrusive JavaScript using the Prototype versus JQuery stacks. In that post I came down on the side of the JQuery stack. Something I didn’t analyze at the time, was: is it possible to use a little of each? For instance, say (hypothetically) that you have a big old Rails project that uses RJS all over the place and you’d like to continue using RJS — is there a way to leverage pieces of JQuery in that scenario.

In this pursuit I learned a few things. Firstly, plain old JQuery does not “do” UJS in the following sense: if you bind a behavior to an element (via a CSS selector), that binding will not be reapplied as the DOM is manipulated. For dynamic binding, or “live” binding that gets re-applied after every DOM update, you need Brandon Aaron’s livequery plugin for JQuery. Livequery is to JQuery as Dan Webb’s Low Pro is to Prototype — kind of. Difference being that livequery hooks each of JQuery’s DOM manipulation routines, whereas Low Pro hooks each of Prototype’s Ajax.Responders “onComplete” event — the event that happens when an XHR is complete.

What all this means is that you can use JQuery’s UJS (livequery) if you use JQuery for all your DOM manipulations, or you can use Prototypes UJS (Low Pro) if you use Prototype for all your Ajax calls. The unfortunate bit is that you cannot (yet) use livequery with Prototype Ajax calls, or Low Pro with JQuery DOM manipulations. Can’t we all just get along?

I wonder if a UJS package could remain stack agnostic. I think livequery is on to something by hooking DOM manipulation routines. That seems more robust (if potentially less performant) than hooking the Ajax returns. By hooking DOM manipulation it seems that you’ve plugged more holes and have a more general-purpose solution. Could the livequery approach (of watching for DOM manipulation) be done in a stack-agnostic fashion rather than by hooking JQuery routines? If we could do that then we’d have a UJS package we could use no matter which JavaScript base library we choose — or perhaps whichever library chooses us.

This entry was posted in AJAX, RJS templates, Ruby on Rails. Bookmark the permalink.

4 Responses to Agnostic Unobtrusive JavaScript

  1. babak says:

    Hey Bill,
    thanks for the nice post. I also enjoyed the one before. I am about to decide which framework to use in our RoR project: well-known and supported Prototype or emerging developer’s favorite jQuery. I lean towards jQuery, as it seems to be as powerful as prototype and at the same time slicker, easier and, also, unobtrusive.

    So reading your post, I wondered: Why is it obtrusive not to reaply bingdings after DOM manipulations? I thought UJS is about seperating behaviourial and data layers.

  2. Bill says:

    Babak – it isn’t that failure to reapply bindings after DOM manipulations is unobtrusive (parse that!) — it’s just that it’s inconvenient for the programmer.

    Now that being said, let me add that one of the really cool things about Lowpro and JQuery+livequery is that your unobtrusive “behaviors” can be expressed in a _declarative_ style. If one has to explicitly re-apply those behaviors then their declarative nature is diminished.

  3. Bart says:

    You should look into event bubbling to avoid using livequery.

  4. bburcham says:

    That’s interesting Bart. Can you point me to an example of how to use event bubbling with JQuery or Prototype to achieve UJS?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s