Reputation: 881
On rails I put all the JavaScript files into application js file.
//= require jquery
//= require jquery_ujs
//= require dropzone
//= require jquery.cookie
//= require toastr
//VENDOR JS BEGINS
//= require pace/pace.min
//= require modernizr.custom
//= require jquery-ui/jquery-ui.min
//= require boostrapv3/js/bootstrap.min
//= require jquery/jquery-easy
//= require jquery-unveil/jquery.unveil.min
//= require jquery-bez/jquery.bez.min
//= require jquery-ios-list/jquery.ioslist.min
//= require jquery-actual/jquery.actual.min
//= require jquery-scrollbar/jquery.scrollbar.min
//= require bootstrap-select2/select2.min
//= require switchery/js/switchery.min
//= require imagesloaded/imagesloaded.pkgd.min
//= require jquery-isotope/isotope.pkgd.min
//= require classie/classie
//= require codrops-stepsform/js/stepsForm
//= require bootstrap-datepicker/js/bootstrap-datepicker
Then I call javascript in the head of application.html.erb as;
...
<head>
..
<%= javascript_include_tag 'application' %>
..
</head>
...
Then I check the speed of the website and I am suggested to take this JS call to body. I know I should BTW. But the problem is with the page specific JS code.
Imagine I have home.html.erb
where users select date. So I put datapicker code into this page.
If I take <%= javascript_include_tag 'application' %>
into at the bottom of body, this time because the jquery & datepicker not loaded yet so page specific JS gives no method error
What would be the best approach?
Upvotes: 13
Views: 9451
Reputation: 259
You can also have a look at Page-specific Javascript for Rails done right. This is worth looking!
After installation. Let's look at sample code.
var ArticlesController = Paloma.controller('Articles');
ArticlesController.prototype.edit = function(){
// Handle edit article
};
That means that if you have Articles controller's edit action page. Then only the javascript will be triggered. This will not be triggered in other controller actions.
Upvotes: 2
Reputation: 675
There is a very good answer to this at http://brandonhilkert.com/blog/page-specific-javascript-in-rails/.
Basically, you want to open your app/views/layouts/application.html.erb and convince it to give you controller and view information each time it renders a page. To do so you change the body tag from
<body>
<%= yield %>
</body
to
<body class="<%= controller_name %> <%= action_name %>">
<%= yield %>
</body>
So, when rails renders the body tag it will now add a class for the controller and one of the actions in the controller.
Say you have a controller called static_pages, and the static_pages controller has
def home
end
When rails renders the view/page home it will now add to the body tag a class of static_pages and a class of home.
<body class="static_pages home">
the home view is rendered here
</body>
This will be a site wide change, so if you go to an index page/view from the users controller the body tag would be:
<body class="users index">
the index view is rendered here
</body>
Now, make a file called vendor/assets/javascripts/jquery-readyselector.js containing:
(function ($) {
var ready = $.fn.ready;
$.fn.ready = function (fn) {
if (this.context === undefined) {
// The $().ready(fn) case.
ready(fn);
} else if (this.selector) {
ready($.proxy(function(){
$(this.selector, this.context).each(fn);
}, this));
} else {
ready($.proxy(function(){
$(this).each(fn);
}, this));
}
}
})(jQuery);
That file must be properly referenced in application.js
...
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require jquery-readyselector
//= require_tree .
Once all that is done you can test it by making a simple alert specific to the view you want test like so:
// app/assets/javascripts/static_pages_home.js
$(".static_pages.home").ready(function() {
return alert("You should only see this on the static pages home page.");
});
// app/assets/javascripts/user_index.js
$(".users.index").ready(function() {
return alert("You should only see this on the users index page.");
});
You could also make a script controller specific by not referencing the action.
$(".users").ready(function() {
return alert("You should only see this on a users controller controlled page.");
});
Upvotes: 9
Reputation: 2184
Before body close tag and just after <%= javascript_include_tag 'application' %>
add <%= yield :page_scripts %>
Then anywhere (usually on top) in a specific view set your scripts with:
<% content_for :page_scripts do %>
<script>alert( "My nice scripts..." );</script>
<% end %>
Upvotes: 12