How to scope efficiently javascript et css on a rails appliacation?

css, javascript, jquery, ruby-on-rails, scope

Solution

Requirements:

in your application layout change

<body>

to

<body class="#{controller_name}_#{action_name}">

The body will have a different class for every page. For example, on a blogging application with an article_controller and an index action on this controller, the body will be :

<body class='article_index'>

CSS Scoping

The CSS scoping is almost immediate. If you have some styles that only need to be rendered on a certain page (let's say article#index), you just need to ad in you SCSS file :

body.article_index {
# CSS STYLE HERE
}

You don't need to add very long class names everywhere.

Javascript scoping

You need to download jquery-readyselector. This plugin extends `.ready()` to provide a nice syntax for page-specific script :

$('.article_index').ready(function () {
    alert("I'm on article#index !");
});

An other great things about this plugin is that it is working with turbolink.

Here you can see one of my previous question about turbolink. In order to make my java-script work on page loading AND on page change, someone proposed to me something like that :

// accommodate Turbolinks
$(document).on('ready page:change', function() {
// STUFF
});

But sometime (on the first page loaded), the function was executed twice (one for `ready`, one for `page:change`), now I just use jquery-readyselector like so :

// accommodate Turbolinks
$('nav.nav').ready(function() {
// STUFF
});

and the function will be executed once on every scenario.

I hope this will helps someone.

Problem

I had a lot of trouble to scope my javascript and css files on my rails app. By scoping, I mean : How to deal with java-script and CSS only used in one page or one controller ? I tried some solutions but they were all complicated and not so elegant : I saw some advices like this one : including my .js file directly on my .erb file like so : ``` <% content_for :head do %> <script type="text/javascript"> <% end %> ``` and then yield that in the application layout. But that means doing one more request to the server in order to get the .js file. I think it is important to stay with only one .js file and one .css file for the application, created by the asset pipeline I saw some other advices like testing if my HTML tag was present on the DOM with the .length method of jquery. That's still mean testing on every page if on particular tag is present (knowing it will be present in only one or two pages). I found a solution that's is easy to implement and, in my point of view, elegant.

Original source