Getting my feet wet with Unobtrusive Javascript for Ruby on Rails
Got a link from fellow Filipino Ruby on Rails programmer Mark about a plugin that allows your Ajax-powered application to degrade gracefully when JavaScript is turned off. This is important because every user can choose to turn off JavaScript in their browser. If you rely solely on JavaScript, then your application will not behave properly in this situation.
The UJS (Unobtrusive JavaScript) Rails Plugin has a very professional looking website and I didn't doubt for a second their claims. So I gave it a try.
When installing the plugin in Windows, you may encounter the "Exec format error - rake update_scripts (Errno::ENOEXEC)" error. Don't worry, just execute the command below afterwards and you will be fine:
-
rake unobtrusive_javascript:install
Below is the sample RJS code I wanted to change:
-
<%= link_to_function(image_tag('new_album.jpg'), update_page { |page|
-
page.visual_effect :blind_down, 'folder_new', :duration => 0.5
-
# some code removed
-
}) %>
This link, when clicked, will display a form where the user can input some data (just like the typical new.rhtml)
Here are the steps I did to transform the above UJS.
1. Create a new link to your desired action. In my case, a 'new'.
-
<%= link_to(image_tag('new_album.jpg'), {:controller => 'albums',
-
:action => 'new'}, 'id' => 'new_album') %>
Before, the link has no ID. Since UJS uses CSS selectors, the new link must have an ID or class. In my case, I used an ID since I want this to be uniquely identifiable in my page.
2. Now, let's use UJS
-
<% apply_behavior 'a#new_album:click' do |page, element, event|
-
page.visual_effect :blind_down, 'folder_new', :duration => 0.5
-
event.stop
-
end %>
Note that there are 3 parameters to the code block. Even though I did not use 'element', I need to include it so that 'even't will have the correct object. (Is there an alternative here?)
I called 'event.stop' to prevent the original link from executing.
Some gotchas I encountered.
1. Not specifying the action attribute in the CSS selector.
Initially, I had this code. Note there is no ':click'
-
<% apply_behavior 'a#new_album' do |page, element, event|
When a I did a page refresh, the UJS code was executed right away.
2. Specifying too many javascript_include_tag.
This one took almost 80% of my time to figure out.
Since this is a
new JavaScript, you need to include it in the
use it. Following the tutorial, I pasted the code in my
layout/application.rhtml
-
<%= javascript_include_tag 'prototype', :unobtrusive %>
Even though I followed everything, the behavior was still not being applied to my "a#new_album" link. The problem is caused by these two lines in my layout/application.rhtml
-
<%= javascript_include_tag 'prototype', :unobtrusive %>
-
<%= javascript_include_tag :defaults %>
This two lines will include "prototype.js" twice. Viewing the generated HTML source code, I tthought this was harmless. I merged the above two lines into a single call
-
<%= javascript_include_tag :defaults, :unobtrusive %>
Now, the UJS works. Actually, I have no idea what had just happened. It seems including "prototype.js" twice affects the behavior of UJS
Conclusion
I love it!!! The Rails code is simpler and more importantly, I can turn off JavaScript and everything can still work. My only problem right now is recovering the old RHTML codes I removed after I transitioned to RJS ![]()
Did you enjoy this post? Why not leave a comment below and continue the conversation, or subscribe to my feed and get articles like this delivered automatically each day to your feed reader. If you don't have a feed reader, you can always have these articles delivered to your email inbox every day. Click here to sign up.



Great article! I’ve known about UJS for awhile now but I’ve yet to use it in any of my projects. The UJS site by the way uses a variation of the Sydney mephisto theme used in Luke Redpath’s blog, which I agree is a very slick, classy looking theme. In fact, I’m thinking of using a similar black background/white text look for one of my upcoming projects, subject to approval of my clients. I already use a modified sydney theme for a gaming community portal i’m developing.