Apr 28 2010

How-to: Organizing JavaScript in Ruby on Rails

tobyhede

I have started using what I think is a pretty robust system for handling JavaScript in my Rails projects.

The basic process is this:

1) In order to create some modularity, each controller in my system has it’s own JS file. The controller file contains the code required for the views in that controller. I still have some higher level files for common and application-wide JS code.

2) Each of the controller files is scoped to a namespace:


//File: javascripts/controllers/dashboard.js
var dashboard = {
  init: function() {
    //kick-off code for the "dashboard" controller
  }
}

3) I have a view helper that appends a load command to the layout. Loading is a matter of calling the namespaced init method: $(document).ready(dashboard.init);

The helper looks like this:


def load_controller_script(script = controller.controller_name)
  content_for :javascript do
    "<script type=\"text/javascript\">$(document).ready(#{script}.init);</script>".html_safe
  end
end

And is included in my layout using: <%= raw(yield :javascript) -%>

Using “raw” because I am in Rails 3 land.

4) At deploy time I use the awesome asset_packager plugin to join all of the controller files into a single file, meaning I only have a single request for JS in my production system. The namespacing ensures that there are no conflicts across the many small files.

That’s it!

I am still investigating the most robust way to setup the namespaces. The above is simple, but not necessarily the best way to go about it.

It would be quite a simple matter to have the files be more granular – you could actually tie them to specific actions in your system. Controller is fine for my use-case as this particular app is very JS-centric and builds actions and views using AJAX and JS in the browser (so a lot of my actions return JSON rather than HTML).


Sep 5 2009

How-To: Load Javascript and CSS dynamically with jQuery

tobyhede

I’ve been working on a new project for Inspire Digital.

The project is going to allow site members to produce their own content.

Members have a WYSIWYG editor (using jquery.wysiwyg) for creating content with some basic HTML. I wanted to come up with a way for only those who need the files to download the files.

Previously in this sort of situation I have simply included the script and css files within the form, but this is not valid HTML.

So … Loading Javascript and CSS dynamically with jQuery to the rescue!

Loading JavaScript is built-in to jQuery, but you need to create CSS elements yourself.

The approach places a class on the text area we want to be WYSIWYG, then we detect that class, load the CSS and JavaScript and initialise the editor. Easy!


$(document).ready( function() {
  if ($('.wysiwyg_editor')) {
    $("head").append("<link>");
    css = $("head").children(":last");
    css.attr({
      rel:  "stylesheet",
      type: "text/css",
      href: "/javascripts/jwysiwyg/jquery.wysiwyg.css"
    });
    $.getScript("/javascripts/jwysiwyg/jquery.wysiwyg.js", function(){
         //wait before initialising to prevent intermittent load error
	 setTimeout("init_wysiwyg_editor()",250);
    });
  }
});
function init_wysiwyg_editor() {
  $(".wysiwyg_editor").wysiwyg();
}

The only gotcha I found was that calling $(“.wysiwyg_editor”).wysiwyg(); would occasionally error with an undefined method unless I put a momentary timeout in before calling. I think this was the result of the browser making the call while still interpreting the freshly loaded script.