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?
Rails uses a technique called "Unobtrusive JavaScript" to handle attaching JavaScript to the DOM. This is generally considered to be a best-practice within the frontend community, but you may occasionally read tutorials that demonstrate other ways. When clicked, the link background will become red.
JavaScript files are stored with the . js extension. Inside the HTML document, you can either embed the JavaScript code using the <script></script> tags or include a JS file. Similar to CSS files, JS files can be included in multiple HTML documents for code reusability.
.js.erb files are for controller actions, such as create, when you want javascript to be executed when the action completes. For example, when you want to submit a form via ajax and want display an alert when everything is done, you would put the $('#business_submit').
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 %>
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.");
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With