Rails Plugin: Javascript Unqueue Spring, all Javascript output at page bottom

I’m releasing my second plugin, a simple library for being able to declare Javascript functions or executable code from anywhere within a template or partial file, and have it all output together in a lump at the bottom of your page.

Why?

It offers the following advantages over simply using javascript_tag:

  • Most (all?) browsers pause rendering when they encounter inline JS, so having JS (especially complicated JS) that is scattered throughout your code means your page won’t be visible until said code runs. That’s no fun.
  • Race conditions. If you declare code inside a javascript_tag that refers to a DOM element that isn’t yet instantiated, you’re in for some trouble. Using Javascript queuing, your JS code is assured not to run until the document is ready (i.e., all page elements have been loaded)
  • Easier to find JS code in Firebug if it’s all in one place at the end of the page
  • Best practices. It’s commonly accepted that inline JS is bad bad mojo. Ask Google if you don’t believe me.

Usage

Pretty damn simple.

<% queue_js do
<<-JAVASCRIPT_CODE
// Run an alert to show we exist:
alert("I go at the bottom of the page and run automatically!");

// Do some other senseless thing
$("a").click(function() { alert('An anchor was clicked!'); });
<<JAVASCRIPT_CODE
end %>

Using this plugin, this would be output by default (i.e., without changing JS to run using Prototype) as follows:

<body>
... (all the HTML rendered during your render pass) ...
</body>
<script>
//<!--[CDATA[
jQuery(function(){
alert("I go at the bottom of the page and run automatically!");
$("a").click(function() { alert('An anchor was clicked!'); });
});
//]]-->
</script>

You can open and reopen (i.e., call the queue_js method) as often as you like during your render call. All JS added during all calls will queued until the render pass finishes.

If you change to the Prototype option, the JS will be wrapped in an equivalent wrapper that Prototype uses to run JS after the DOM has been fully loaded. For specifics, see js_queue_spring.rb in the source code (hint: it uses Event.observe(window, ‘load’)).

Options

If you want to just add code that isn’t going to be automatically run, you can use the :flat parameter like so:

<% queue_js(:flat) do
<<-JAVASCRIPT_CODE
function someFunc() { alert("Doing nothin until you tell me to!"); }
<<JAVASCRIPT_CODE
end %>

You can also look in the /lib/js_queue_spring directory to specify whether you want to use jQuery (tested) or Prototype (untested) syntax to wrap your code that should run when the page has finished loading.

Limitations

Caching pages with queued JS is a problem. Since the JS is not output inline with the page, if you cache a partial with JS that is queued, that JS will not be re-rendered when the cached version of the partial is used. For partials that have cached content, you’re probably better off using javascript_tag.

Get it

From your base directory,

svn export http://jsqueuespring.googlecode.com/svn/trunk/ vendor/plugins/js_queue_spring

And that’s that. The plugin is configured by default to use jQuery’s “jQuery(function(){ }) ” to run the code after the document has loaded. If your site doesn’t use jQuery (well, it probably should, but) you can go into the /lib/js_queue_spring and change the “SPRING_WRAPPER_TYPE = :prototype”. Fair warning: I haven’t experimented much with using this as Prototype. If anyone uses this option, please report as to whether it works, and ideally, how you made it work.

A bit more info available at Google Code project. A bit more instruction also available in the plugins’ readme.

Leave a Reply

Your email address will not be published. Required fields are marked *