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 plicated 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.
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 plicated 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.
Share Improve this question asked Jul 13, 2014 at 4:43 user3704659user37046592 Answers
Reset to default 9Requirements:
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 :
// acmodate 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 :
// acmodate Turbolinks
$('nav.nav').ready(function() {
// STUFF
});
and the function will be executed once on every scenario.
I hope this will helps someone.
Conditional Layout
If you only want to show css
/ js
assets on a specific page, you'll either be best calling the asset in the view
itself (which isn't remended), or just set a condition in your layout
to call the files you need:
#app/views/layouts/application.html.erb
<html>
<head>
<% if controller_name == "test" && action_name == "index" %>
...
<% end %>
</head>
</html>
Something which will help you are the controller_name
and action_name
helpers - they will give you the reference to the controller
or action
your page has rendered.
--
Turbolinks
In regards to your answer, I don't understand what you're trying to propose. There's a problem here:
$('nav.nav').ready(function() { //-> wrong syntax
If you want to incorporate Turbolinks
, you need to use either the event
hooks of Turbolinks
, or javascript delegation:
var nav_ready = function() {
// do stuff here
};
$(document).on("page:load ready", nav_ready);