Building a compressed prototype + scriptaculous with YUI Compressor

A newer version of protoaculous is available from Inderpreet Singh, skip the reading and download protoaculous 1.9 directly.

A while back I started using protoaculous.js, a combined and compressed version of the Prototype.js and Scriptaculous in a single file. Unfortunately, as time went by and both Prototype and Scriptaculous got updated, it didn't seem like anyone was updating protoaculous in sync, so a few months ago I decided to build my own.

Of course, a day or so after I did that, John-David Dalton released a more up to date and far more complete set of files in his 'protopack', but I know some folks were already using my version because I got a request the other day to update it to use 1.6.0.2 of prototype.js. I figured this was a good opportunity to try and be a bit more organised about building it, plus I like being in the situation where I don't have to rely on anyone else for my updates, hence this mini-tutorial blog post.

Before starting we'll need the YUI Compressor (get the yuicompressor-x.y.z.jar file out of the build sub-directory), which itself needs a version of the Java runtime installed. The below assumes you're running on Windows, have Java setup, and have the YUI Compressor .jar file in your working directory. You'll also need a set of scriptaculous and prototype source files (the prototype.js file is in the 'lib' sub-folder, everything else is in 'src').

OK, so assuming we've got all the relevant stuff from the previous paragraph downloaded into your working directory, building the combined and compressed protoaculous.js is two fairly easy steps. First off, scriptaculous loads it's dependent scripts dynamically by inserting <script> elements into the document head, since we're not going to have the separate scripts in the combined file we need to stop it doing that. I create a file v_scriptaculous.js where I've removed lines 46 to 54:

    var js = /scriptaculous\.js(\?.*)?$/;
    $$('head script[src]').findAll(function(s) {
      return s.src.match(js);
    }).each(function(s) {
      var path = s.src.replace(js, ''),
      includes = s.src.match(/\?.*load=([a-z,]*)/);
      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
       function(include) { Scriptaculous.require(path+include+'.js') });
    });

And also lines 26-29:

  require: function(libraryName) {
    // inserting via DOM fails in Safari 2.0, so brute force approach
    document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
  },

If you end up working with a newer version the procedure should be similar, though the line numbers may be different, just look for any functions which try to dynamically insert script tags. With the above two sections removed I end up with a v_scriptaculous.js file 46 lines long, which, disregarding comments, looks like this:

var Scriptaculous = {
  Version: '1.8.1',
  REQUIRED_PROTOTYPE: '1.6.0.2',
  load: function() {
    function convertVersionString(versionString) {
      var v = versionString.replace(/_.*|\./g, '');
      v = parseInt(v + '0'.times(4-v.length));
      return versionString.indexOf('_') > -1 ? v-1 : v;
    }
 
    if((typeof Prototype=='undefined') ||
       (typeof Element == 'undefined') ||
       (typeof Element.Methods=='undefined') ||
       (convertVersionString(Prototype.Version) <
        convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
       throw("script.aculo.us requires the Prototype JavaScript framework >= " +
        Scriptaculous.REQUIRED_PROTOTYPE);
  }
};
 
Scriptaculous.load();

Now we need to combine all the files together and feed them into the YUI Compressor. To do this I've created a batch file build.bat:

@echo off
copy prototype.js + v_scriptaculous.js + builder.js + effects.js + dragdrop.js + controls.js + slider.js + sound.js c.js /b
java -jar yuicompressor-2.3.5.jar -o protoaculous.1.8.1.min.js c.js
del c.js

This creates a temporary file, c.js, which is a combination of all the javascript files, uses the YUI Compressor to build the output file, then deletes the temporary file. I found I had to use the /b (binary) switch on the copy command otherwise I got junk at the end of the file which caused errors in the compressor. After running the batch file we should end up with protoaculous.1.8.1.min.js sitting in our working directory.