Cristhian Boujon
Cristhian Boujon

Reputation: 4190

Where to put a JS file for specific page in Rails?

I'm using an autocomplete JQuery plugin with some options. The little code is used in just one specific page.

My first attempt was to put it in a separated JS file in app/assets/javascripts/foo.js. The problem is that the code throws an exception because the element does not exist in other pages.

I also thought about calling the JS file from the specific page but where should I put this JS file?

EDIT 1

This is the code of foo.js

$(document).ready(function(){
    $("#search").autocomplete({
         // set options
    }) 
    .data( "ui-autocomplete" )._renderItem = 
        function( ul, item ) {
        // more code
        };
});

I get the typeerror $(...).autocomplete(...).data(...) is null in firebug so I tried put this code into the specific page with <script></script> and works fine but I don't like this approach.

Upvotes: 2

Views: 626

Answers (2)

Bubbles
Bubbles

Reputation: 3815

There are a couple of ways to handle this. Possibly the easiest would be to take all the relevant js and put it directly in the page it's concerned with - just add a script tag, put it inside, and be done with it.

I'm not a huge fan of this approach, and it wouldn't work in every circumstance. I'm going to go ahead and guess that in assets/javascripts, you have a "require_tree ." that combines & serves every file in the folder. What you could do is break this down a bit - keep every file that you server on every page in a specific, separate folder, and require every file within that folder. Keep things like foo.js elsewhere, and combine/serve them on an as-need basis.

I can't say for sure, but I'm guessing this division of JavaScript files will be overkill. I think the best thing to do though is change the structure of foo.js so you can still serve it with everything else, but it will not automatically run. There's a couple of ways to do this. One would be to just wrap everything in a named function, and call the function on the specific page that needs it would work.


However, if the issue is just a matter of configuring a jQuery plug-in, you may be able to rely on jQuery more to do this. I'd have to see the code in question, but you should be able to call a plug-in on an empty set.

For instance, if you're using jQuery-ui and declare something as draggable, $("#my_element").draggable() won't cause an exception if "#my_element" doesn't exist on the page - rather, nothing at all will happen. I can't say for sure without seeing what you're doing, but I'd bet you can get away with a clever restructure of foo.js and have it exist harmlessly on pages that don't need it.


With regards to Edit 1:

An easy, if somewhat gimmicky, fix would just be do this:

$(document).ready(function(){
  $("#search").autocomplete({
     // set options
  })
  .each(function() {
    $(this).data('ui-autocomplete')._renderItem = 
      function( ul, item ) {
      // more code
      };
  });

I don't know quite enough about the jQuery UI widgets to know if there's a better way - ideally, there'd be some way to include the _renderItem function as part of the configuration for autocomplete. I'm going to do a bit more digging, but otherwise this is a reasonable way of doing it.

Upvotes: 0

CDub
CDub

Reputation: 13354

You'll want to put this file outside of the asset pipeline, meaning not inside app/assets, lib/assets, or public/assets. You could put it in the public folder, and then link to it using javascript_include_tag in the view you need it in.

Upvotes: 1

Related Questions