Using Rails 3.1, where do you put your "page specific" JavaScript code?

To my understanding, all of your JavaScript gets merged into 1 file. Rails does this by default when it adds to the bottom of your manifest file. //= require_tree .application.js

This sounds like a real life-saver, but I am a little concerned about page-specific JavaScript code. Does this code get executed on every page? The last thing I want is for all of my objects to be instantiated for every page when they are only needed on 1 page.

Also, isn't there potential for code that clashes too?

Or do you put a small tag at the bottom of the page that just calls into a method that executes the javascript code for the page?script

Do you no longer need require.js then?

Thanks

EDIT: I appreciate all the answers... and I don't think they are really getting at the problem. Some of them are about styling and don't seem to relate... and others just mention ... which I know exists (obviously...) but it would appear that the Rails 3.1 way going forward is to wrap up all of your JavaScript into 1 file rather than loading individual JavaScript at the bottom of each page.javascript_include_tag

The best solution I can come up with is to wrap certain features in tags with s or es. In the JavaScript code, you just check if the or is on the page, and if it is, you run the JavaScript code that is associated with it. This way if the dynamic element is not on the page, the JavaScript code doesn't run - even though it's been included in the massive file packaged by Sprockets.dividclassidclassapplication.js

My above solution has the benefit that if a search box is included on 8 of the 100 pages, it will run on only those 8 pages. You also won't have to include the same code on 8 of the pages on the site. In fact, you'll never have to include manual script tags on your site anywhere ever again.

I think this is the actual answer to my question.


答案 1

The Asset Pipeline docs suggest how to do controller-specific JS:

For example, if a is generated, there will be a new file at and another at . You should put any JavaScript or CSS unique to a controller inside their respective asset files, as these files can then be loaded just for these controllers with lines such as or .ProjectsControllerapp/assets/javascripts/projects.js.coffeeapp/assets/stylesheets/projects.css.scss<%= javascript_include_tag params[:controller] %><%= stylesheet_link_tag params[:controller] %>

Link to: asset_pipeline


答案 2

For the page-specific js you can use Garber-Irish solution.

So your Rails javascripts folder might look like this for two controllers - cars and users:

javascripts/
├── application.js
├── init.js
├── markup_based_js_execution
├── cars
│   ├── init .js
│   ├── index.js
│   └── ...
└── users
    └── ...

And javascripts will look like this:

// application.js

//= 
//= require init.js
//= require_tree cars
//= require_tree users

// init.js

SITENAME = new Object();
SITENAME.cars = new Object;
SITENAME.users = new Object;

SITENAME.common.init = function (){
  // Your js code for all pages here
}

// cars/init.js

SITENAME.cars.init = function (){
  // Your js code for the cars controller here
}

// cars/index.js

SITENAME.cars.index = function (){
  // Your js code for the index method of the cars controller
}

and markup_based_js_execution will contain code for UTIL object, and on DOM-ready UTIL.init execution.

And don't forget to put this to your layout file:

<body data-controller="<%= controller_name %>" data-action="<%= action_name %>">

I also think that it is better to use classes instead of attributes, for the better page-specific css. As Jason Garber have mentioned: page-specific CSS selectors can get really awkward (when you use attributes)data-*data-*

I hope this will help you.