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

Hi,

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).

Christian

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