Rails 3 - Javascript/Ajax - date-remote=true


I recently watched DHHs presentation at RailsConf09 (http:// railsconf.blip.tv/file/2081411/). I think the "unobstrusive" Javascript stuff (like replacing onClick="..." by data-remote=true or similar) is very interesting.

I'm using these HTML5 data-attributes already in some of my projects for storing additional information that are handled by javascript functions etc.

I was curious about how this would be implemented in Rails3, but didn't find any changes regarding this in the rails3/master-branch. My concern with this is just about performance. So I've tried to set up a quick performance test (using jQuery in Firefox 3).

The test may be not very representative, but I guess that the results will not differ very much in other browsers. If you've got 5.000 HTML elements like this

<a href="http//something.com/action/url" data-remote=true class="remote-link">

jQuery needs about 240ms to find all links with the data-remote=true attribute (Syntax: $('a[data-remote=true]').each(...)).

Looking for a-tags by class jQuery only needs 50ms to find all links ( $('a.remote-link')....).

So... my suggestion is just to use classes (like "_rails_remote_link") for finding remote forms, links etc. I know that it is unlikely to have 5.000 links on a single page, but if you could use classes instead of data-attributes with a performance gain of about 400%, it's worth to think about that?

:slight_smile: Christian

That’s an interesting idea to use classes, but perhaps it would be better to work with jQuery / Prototype to make their selection engines better? Why are they able to find by classes so much quicker than by attributes?

Paul Bowsher

While I am definitely in favor of using classes for booleans, there is a mitigating factor here.

Rather than do:

$(“a[data-remote=true]”).click(…), we will be doing $(“a[data-remote=true]”).live(“click”, …), which does not bind to every link, but rather tests click events to see whether they match the event in question. As a result, jQuery will never have to do a full scan of the DOM looking for links; also, this will make the helpers work via returned Ajax responses.

– Yehuda

I'm not absolutely sure about that. In the jQuery code there are a lot of comments (regarding searching functionality) like:

// It's faster to filter by class and be done with it or // We can get a big speed boost by filtering by class here

I think, if they could make it faster, they would have tried (because obviously they know that searching for classes is currently a lot faster).

Unfortunately the jQuery source is generally hard to read, so I don't know what they're exactly doing in the search/traversing section. I've took a quick look at the prototype source, and it seems that it's also easier for Prototype to find an element by class.

But, maybe I'll prepare a full test for jQuery and Prototype and checking this with several browsers. At least my above jQuery sample with 5.000 elements runs a lot faster on Safari (18ms for searching by class, 65ms for searching by data-attribute).

But again: I think the Javascript experts (jQuery, Prototype, etc) already did their best to make their code as fast as possible.:slight_smile:

$("a[data-remote=true]").live("click", ...), which does not bind to every link, but rather tests click events to see whether they match the event in question.

Yes, good point :slight_smile: Makes sense using .live() here, especially for Ajax responses. But as .live() doesn't support bindings on the onSubmit event currently there could be a problem with forms that are submitted via the return key?

This is why I thought that you, at least for forms, would use the traditional submit event, which would require a DOM scan (and unfortunately for each new DOM elements updated via Ajax, too).


jQuery is going to be adding support for .live(“submit”) in the next release, and it’s possible to emulate in rails.jquery.js in the interim.

– Yehuda