More inline RJS
In Inline RJS I talked about invoking simple RJS actions right there in your controller. Did you know you can do the same in your views, with (among other helpers) link_to_function
?
1 2 3 4 5 6 7 8 |
# before <%= link_to_function "Close", "$('some_div').down('form').reset(); $('some_div').hide()" %> # after <%= link_to_function "Close" do |page| page[:some_div].down('form').reset page[:some_div].hide end %> |
Furthermore, Sam Stephenson showed me a trick where you can use RJS in arbitrary helper methods to generate Javascript code. Don’t like inlining RJS as above? Then refactor it like this:
1 2 3 4 5 6 7 8 |
module SomeHelper def hide_and_reset(div) update_page do |page| page[div].down('form').reset page[div].hide end end end |
Then, in your view:
1 |
<%= link_to_function "Close", hide_and_reset(:some_div) %>
|
That update_page
method is defined in PrototypeHelper, and will return the generated Javascript as a string. Beware, though: whether you use update_page
or a block passed to link_to_function
, making use of inline RJS has a price. It’s fine if you only need to do it a few times on a page, but stick to explicit Javascript if you’re emitting lots of bits like that.
Reader Comments
Very cool. Thanks for these updates—I’ve enjoyed them quite a bit.
12 Jan 2007
I can see that loads of great posts are coming from you Jamis!
12 Jan 2007
link_to_function supports inline rjs?!? Jamis, you just blew my mind.
12 Jan 2007
Jamis, Another gem!
The information, quality and clarity of your posts are fantastic. The best rails related blog by a mile in my opinion.
Thanks, John
13 Jan 2007
Awesome.
I don’t really understand why excessive use of inline RJS is bad, does the generated Javascript slow down the page rendering?
13 Jan 2007
Thanks, John!
Brian, the JavascriptGenerator that RJS uses internally isn’t very lightweight right now, so if you use it alot on a page it will significantly slow down the rendering of your page. We had a page that was doing about 120 (very simple) calls to update_page, and by removing those and replacing them with explicit javascript, we increased the rendering speed by 10x (no exaggeration!). However, a handful of calls to update_page will not significantly impact your render time.
13 Jan 2007
Cool! Shouldn’t we always use helpers in such case, though? I thought the Gods of Rails instruct us to stay away from such code in views?
13 Jan 2007
This is a great post, but I’m confused by the line: page[:some_div].down(‘form’).reset
Some other people have used the “down” and “up” functions on DOM elements, but I can’t find a definition of those functions anywhere. They don’t seem to be part of standard javascript, nor of scriptaculous nor prototype. Does anybody know where I can find their definitions?
-gcn
13 Jan 2007
gcnovus, they are in prototype.js. The “down” method, if given with no parameters, returns the first child element. Likewise, “up” without parameters returns the parent element. If a parameter is given, it is a CSS selector that describes the ancestor (for up) or descendant (for down) node to select. In the example, it will return the first “form” tag that is a descendant of the element with id “some_div”.
It’s really one of the more amazingly useful functions in prototype!
13 Jan 2007
Thanks! I love it when I find things I’ve already written 4 times in open source code. :)
14 Jan 2007
A more on-topic question: is there an elegant way to make this degrade for non-javascript browsers?
14 Jan 2007
Autofocus the first form input on every page of your site:
$(‘application’).down(‘input’).focus();
down() is just the thing I’ve been looking for to use on a small intranet app. Sweetness!
16 Jan 2007
Would there be a way to autofocus the first input that’s wrapped in a div with a class name of fieldWithErrors?
16 Jan 2007
meekish, you might try:
Note that the above does no error checking (for instance, to see if there ARE any matching inputs), but it would be trivial to add such checking if needed.
16 Jan 2007