Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails js files & Page specific js

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?

like image 668
Shalafister's Avatar asked Dec 20 '16 08:12

Shalafister's


People also ask

Does rails use JavaScript?

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.

Where are JavaScript files stored?

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.

What is a js Erb file?

.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').


2 Answers

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 %>
like image 188
Mat Avatar answered Oct 02 '22 12:10

Mat


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.");
});
like image 33
Jeremy Avatar answered Oct 02 '22 14:10

Jeremy