Simple and easy javascript dependency management.

Why?

This plugin grew out of my desire to use javascript effectively in my new job. We began using UJS, and that was a good step in the right direction. The problem was that I found myself wanting to break the code I was writing into logical sections, so I created this convention:

The url /account/edit automatically includes /javascripts/account/edit.js if it exists, otherwise it would try /javascripts/account.js, and otherwise nothing. This convention worked pretty well, except that I found that often controllers would share code. I could have just included the controller javascript as well, but on top of that there was another convention: /javascripts/models/base.js, which communicates with the server (getting JSON back), and its subclasses. Controllers didn’t have a 1-1 mapping to models, so I needed some mechanism to specify what should be included where without a bunch of conditional statements in application.rhtml.

How to use it

My solution (from one index.js):

// require prototype menu models/tag models/interest builder moo.fx.pack.js

This is the first line of the file, and it tells my plugin to make sure that it includes these files before it includes this one when using javascript_include_tag. So the output of javascript_include_tag('index') would be this:

<script type="text/javascript" src="/javascripts/prototype.js"></script>
<script type="text/javascript" src="/javascripts/menu.js"></script>
<script type="text/javascript" src="/javascripts/models/tag.js"></script>
<script type="text/javascript" src="/javascripts/models/interest.js"></script>
<script type="text/javascript" src="/javascripts/builder.js"></script>
<script type="text/javascript" src="/javascripts/moo.fx.pack.js"></script>

It also handles recursive includes:

A.js: // require B …

B.js: // require C …

C.js: …

Here calling javascript_include_tag('A') returns:

<script type="text/javascript" src="/javascript/C.js"></script>
<script type="text/javascript" src="/javascript/B.js"></script>
<script type="text/javascript" src="/javascript/A.js"></script>

And, if two different scripts require the same script, it’ll only be included once:

A.js: // require prototype …

B.js: // require prototype

javascript_include_tag('A', 'B'):

<script type="text/javascript" src="/javascript/prototype.js"></script>
<script type="text/javascript" src="/javascript/A.js"></script>
<script type="text/javascript" src="/javascript/B.js"></script>

This even works if you include ‘A’ and ‘B’ in different calls to javascript_include_tag.

Installation

script/plugin install http://eventualbuddha.textdrive.com/svn/javascript_require/