
I am guessing 9 out of 10 of you reading the title is prepared for yet-another Rails drama on some obtrusive community members, and because everyone is tired of Rails dramas, I am risking that some of you won’t care to read the article – but I couldn’t resist
. Actually I’d like to talk about usage of (un)obtrusive Javascript – why is it a bad idea to be obtrusive, especially given that (as you will learn from the article) writing unobtrusive Javascript is not harder, and you get the warm, fuzzy feeling of writing nice and clean code!
To demonstrate the differences, I’ll lead you through the creation of a quick AJAXy shout wall both the default/standard (and obtrusive) way, then do the same with unobtrusive Javascript to show you that contrary to the popular belief, you don’t need to memorize the “Tome of Javascript Black Magick Tricks” by heart, use obscure libraries or special coding techniques to achieve clean, unobtrusive code. The shout wall is simply a form for posting a new message, and a list of messages below it, like so:

Note: If you’d like to follow along, please use the provided pastie links – do not try to cut & paste multiple lines from the page (single lines are OK), as it will be b0rk3d.
rails obtrusive-shout-wall
cd obtrusive-shout-wall
script/generate resource message
t.string :author
t.text :message
rake db:migrate
default_scope
rder => 'created_at DESC'
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag :defaults %>
<%= yield %>
body {
background-color:#FFFFFF;
color:#333333;
font-family:"Lucida Grande",verdana,arial,helvetica,sans-serif;
margin:0 auto;
padding:0;
text-align:center;
width:960px;
}
#messages {
text-align: left;
margin-left: 80px;
margin-top: 50px;
}
#message-form {
text-align: left;
}
#message-form dl {
margin:10px 0 0 80px;
}
#message-form dd {
color:#666666;
font-size:11px;
line-height:24px;
margin:0 0 5px 80px;
}
#message-form dt {
float:left;
font-size:14px;
line-height:24px;
width:80px;
text-align: left;
}
#author {
margin-right: 640px;
}
#message {
width: 600px;
height: 200px;
margin-right: 194px;
}
.message {
margin-bottom: 20px;
}
.first_row {
padding-bottom: 10px;
}
.message-meta {
font-size: 12px;
}
.author {
color: #FF5050;
font-weight: bold;
}
.new-message-label {
text-align: left;
padding-top: 30px;
margin-left: 80px;
}
#submit-button {
float : right;
margin-right: 195px;
margin-top: 10px;
}
def index
@messages = Message.all
end
Enter new message!
<% remote_form_for :message, :html => {:id => "message-form"} do |form| %>
We are showing the form for the messages and list the already exiting messages below the list.
Note that we are using the _remote_form_for_ Rails helper to create an AJAXy form. This is already obtrusive, since if you observe the generated HTML, you will see that the form has an onsubmit parameter with some horribly looking code attached to it.:

def create
@message = Message.create(:author => params[:author], :message => params[:message])
end
page.insert_html :top, "messages", :partial => 'message',
bject => @message
page.visual_effect :highlight, "message-#{@message.id}"
Here we insert the “messages” partial, using the just created @message, and throw a splash of yellow fade into the mix for good measure. Easy peasy.
Here I am presenting only the steps that are different from the above – i.e. if step 3 is skipped, use the one from above.
rails unobtrusive-shout-wall
cd unobtrusive-shout-wall
curl http://jqueryjs.googlecode.com/files/jquery-1.3.1.min.js > public/javascripts/jquery.js
curl http://www.malsup.com/jquery/form/jquery.form.js?2.28 > public/javascripts/jquery-form.js
curl http://view.jquery.com/tags/ui/latest/ui/effects.core.js > public/javascripts/effects.core.js
curl http://view.jquery.com/tags/ui/latest/ui/effects.highlight.js > public/javascripts/effects.highlight.js
and replace
<%= javascript_include_tag :defaults %>
with
<%= javascript_include_tag 'jquery' %>
<%= javascript_include_tag 'jquery-form' %>
<%= javascript_include_tag 'application' %>
<%= javascript_include_tag 'effects.core' %>
<%= javascript_include_tag 'effects.highlight' %>
in the layout file.
def create
@message = Message.create(:author => params[:author], :message => params[:message])
render :partial => 'message',
bject => @message
end
$(document).ready(function() {
$("#message-form").ajaxForm({success: handleNewMessage});
function handleNewMessage(response, statusText) {
$("#messages").prepend(response).effect("highlight", {}, 1500);
}
});
I don’t think so that this code is particularly more complicated or hard to understand that the RJS one. Everything is inside the ready() function, which means that it’s only run once the document is properly loaded. Then we declare that “#message-form” is an AJAX form, and that upon successful submission, the handleNewMessage() method should be called. And if that happens, we add the response (which is the return value of the “create” action) to the “#messages” div, just as we did in RJS. Then we apply the yellow fade! w00t!
(You can check out the code used in this post from it’s github repository).
As you can see, the only real difference between the obtrusive and non-obtrusive version is in the last 2 points (downloading and including the jQuery header files can be easily solved with Rails templates): instead of leaving the rendering part to Rails, we return the response as a string and dynamically insert it from jQuery. With about the same effort, we kept all the Javascript code in application.js, which is much cleaner this way (you can open up 1 file and check out all the JS/AJAX behavior in one place), especially after introducing a lot of Javascript functionality into your code – in other words, for the same amount of work we got something much better. Please try to keep this in mind when you are working with Javascript and Rails the next time – believe me, it can save you from a lot of pain!
]]>
Light & Shadow is a ProtoType-based library for creating great looking drop shadows easily. Check out the HTML I used to generate the example image and see it yourself that it’s not rocket science!
All you have to do is to set up a light source with a few parameters (distance, intensity, size etc.) and add the class ‘shadowThrowing’ to your elements which should… well, throw shadows
. I won’t go into details here, you can find the explanation and other details on the Light & Shadow project page.
(Found via Gedankenkonserve – thanks Bernhard
)
Update: Sergio, the author of the livevalidation rails plugin updated the plugin so you can disregard the finale of the article (validates_confirmation_of is working, as well as the newest version of livevalidation, 1.3 is used in the plugin – so no additional tweaking is needed, install and validate away Surely I am not the only one who was a ‘bit nervous’ (that was a mild euphemism) when his carefully entered data disappeared after submitting a form to the server. Nowadays web applications are doing better than that – valid data is saved and only the problematic fields are pointed out.
Of course even that feels so 1990′s now. A contemporary (ehm… web 2.0?) web application is expected to validate the form on the client side already (WARNING! That doesn’t mean at all you shouldn’t validate on the server side though – client side validation is for the good guys but you should still look out for the script kiddies et al), pointing out the errors on the fly so there is no need to come back and change/edit those fields after submitting a form.
My library of choice is livevalidation, which has a Rails companion too – if you are using Rails form helpers and standard validation on your models, you don’t have to touch anything just install livevalidation (=drop it to your javascripts folder, it’s a single .js file). w00t!
The only major shortcoming (from my POV) of the Rails plugin is that validates_confirmation_of is not implemented. However, it’s easy to add it via standard javascript:
<input id="user_password" name="user[password]" size="30" type="password" />
<input id="user_password_confirmation" name="user[password_confirmation]" size="30">
<script type="text/javascript">
var validate = new LiveValidation('user_password_confirmation');
validate.add( Validate.Confirmation, { match: 'user_password' } );
</script>
That’s it!
One more note: the Rails plugin contains version 1.2 but there is a newer version, 1.3 so be sure to replace it.
]]>