Use Jquery – document.ready() to load page specific javascript in Rails App

Yesterday I was working on one of our portal (It’s in Ruby on Rails and we have used quite alot jquery as well). Was integrating a nice Photo Gallery plugin on one of the page. Applcation is having many pages. Every page has some different behaviour and we have different jquery calls for that as per need.

For a performant application, we always want to avoid any unwanted calls to different methdods/functions. In my case, as I mentioned earlier I wanted to show Photo Gallery on a page and photo gallery loads as soon as page is loaded. Gallery photos are dynamic and random which I will be getting from server always.

As soon as we talk about page load we start thinking 🙂 that this code has to go in $(document).ready() 🙂 isn’t is?

Ok, so I did the same thing. I wrote my function and called it in $(document).ready(). Everything worked fine as expected from the functionality point of view. However as I knew getting random photos is always a heavy thing and so I wanted to make sure that I do not hamper performace of the app by any means. So I started looking at application terminal/console to see what all requests are coming in.

Oh I see unwanted calls to my funpics action, in Home page and other all pages. Why it is happening? It was obvious as my $.ajax method which I have used it not based on any Click/ MouseWheel etc event. It was directly on the load.

As per rails practices, I was having a separate JS file for my each controller and same for the “Gallery” controller and there I wrote my code to get the Photos. But you can see that I am calling my ajax method directly on document.ready. Which I should not be.

//----- gallery.js
$(document).ready(function(){
var gallery ="" ;
$.ajax({
url: '/funpics',
async: false,
success: function (data) {
//render images
},
error: (function(xhr, status, e) {
// show error
})
});
$('#photos').append(gallery);
});

I could have done a workaround for it by adding a “IF” condition before calling the $.ajax method.

$(document).ready()
{
if ($('body.gallery').length > 0)
{
$.ajax({
.....
});
}
});

However I wanted to do it in a little better way, so I came across a nice article. Article was addressing exactly same issue. So I added ControllerName and ActionName to the body tag atg in my layout file application.html.haml file

Something like this
%body{class: "#{controller_name} #{action_name}"}

Now I will always have two classes – controller_name and action_name in body tag.

After doing this I added JS plugin jquery.readyselector.js. This one is must and it is doing the really trick. Do not forget to include this in your application.js

Then I changed my gallery.js file little bit, now it looks like

$('.gallery.funpics').ready(function(){
var gallery ="" ;
$.ajax({
url: '/gallery',
async: false,
success: function (data) {
//render images
},
error: (function(xhr, status, e) {
// show error
})
});
$('#photos').append(gallery);
});

In above code $(‘.gallery.funpics’)_, gallery is –> controllerName
and funpics is –> actionName

Now when I started app, I can see $.ajax code of funpics is only called when I am on funpics page and not on Home or any other page.

By this approach jquery.readyselector.js plugin makes sure that content of the ready() block is only loaded when those classes are there otherwise it will not call those functions.

There are some other approaches to handle this problem. e.g.

1. Some developer recommended using data-attribute_, instead of defining the ControllerName and ActionName as class, define them as data-attr_
e.g.

%body{"data-controller" => "#{controller_name}"
"data-actionname" => " #{action_name}"}

I tried it, but I did not like the idea of comparing the names. So I dropped this approach

2. Some suggested using gems like Pluggable_js and Paloma_

However I was not having a need of that level of complexity so I did not use any of these gems. Paloma gem looks good for a bigger project where we have many many controllers and it will take care for things in systematic manner. However I cannot comment much on it as I have not tried it, I just read about it 🙂

3. If you still want to know some more approaches then go through this blog, it has one more approach http://viget.com/inspire/extending-paul-irishs-comprehensive-dom-ready-execution

I hope this will help you guys improving your application perforamance by avoiding unnecessary method calls.

Special thanks to:
John Firebaugh for writing useful jquery-readyselector
Brandon Hilkert as his blog really helped me

If you are trying this approach then do read comments written on “Brandon Hilkert” blog as those are also very informative and useful

Advertisements

One thought on “Use Jquery – document.ready() to load page specific javascript in Rails App

Add yours

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: