Archive for May, 2009|Monthly archive page

My Javascript Object maker

While using my solution to clear, easy to understand and short asynchronous Javascript, I ran into a big problem. I wrote it properly(1), with private variables and all. But, if another part of code called it, the variables would collide. It was just a function. Obvious in retrospect, like most problems!

I need an instance of the function for each call. But, I really don’t like “objects.” I’m not sure why. So, I decided to write an “Object Maker” that will accept a function as an input.

Here it is:

PX.asyncObject = function (spec, my) {
    var that = {};  // declare PRIVATE variables here
    my = my || {};  // Use my.xx for *shared* variables
    if (spec.objName) {
        eval('var ' + spec.objName);    // GLOBAL vars are *more* evil than eval
        window[spec.objName] = spec.newObj;             // Make the function sent into a method named from objName
        that[spec.objName]   = window[spec.objName];    // Make the new method a method of "that"
    } else {
        var go;
        go      = spec.newObj;  // Make the function into a method named "go"
        that.go = go;  // Make "go" a method of "that"
    that.spec = spec;    // Put spec into private vars. call go({vars})
    return that;  // return the new, private, durable object

The basic routine and idea came from (surprise) Douglas Crockford’s “Javascript: The Good Parts,” pp. 52-55. It is called a functional constructor.

I use it like this:

    newObj: function (spec) {
        PX.Rest('GET', sUrl, undefined,
            function (result, o) {
                if (result) {                         
                    // Code for success
                } else {
                   // Code for failure
                    // Code for both

Four lines longer and only a little less readable.

(1) Using a Module (pp. 40-41) from Douglas Crockfords “Javascript: The Good Parts.”


My Javascript Package Manager (again)

I just finished re-writing the “loader” piece of my package manager. It turns out that I was using a function instead of an instance of a function. So, when I thought everything was working and tried loading three packages all at once: ka-blam! They stomped all over each other (as should have been expected, in retrospect).

So, I created an “instance creator” routine. This way, I can take one of my functions and send it as a variable to the instance creator and get back an instance of the same function. Since I’m sure I’ll have this problem frequently. And, since I hate writing routines that are real objects to begin with (not sure why; maybe I’ll get over it some day), I now have a generic solution.

My “loader” can now, from the input of a package name and a function (e.g. init or open), download all specified files except those already loaded, make the necessary queries except those that the data is already loaded for, then render the template once everything else is in place.

I’m hoping to share some code as soon as it is reasonable.

Package Manager File Loader

The package system I originally came up with is getting more complex by the day. First, I wanted to make sure I could load files.

YAHOO.util.Get solved that easily.

Then I wanted to be able to minify and compress them.

YUI Compressor took care of that.

Finally, I wanted to be able to combine them into single files. Again, not really hard at all. In fact, I just wrote a script that essentially does “cat file1 file2 file3 > combofile”.

So, now I have the possibility of:




(I had /js/corefiles-min-combo.js for a while too, but then realized if I wanted it minified, I just needed to make the combo definition include minified files to begin with). See, sometimes things get more simple!

Next, I need to make sure that I only download a file once. So, when I want to dynamically load a new file, I need to make sure I don’t have the plain version, a minified version or either one of those as part of a combo file.

I’m only part of the way through this code. No YAHOO.package.manager to save me this time (if I missed it somehow, please let me know!).

So far, I can list all loaded files. I can then strip the “-min” off (since, from the program’s point-of-view, it doesn’t matter if the file is min’ed or not). I can also take a -combo file, check the package definitions for what is in that combo file,  then add those files (again, removing the -min) to the list.

Now, I have a “master” list of all loaded files, which I can check before trying to load a file.

Next up is to determine if it is faster to add files to this array as I load them or to simply rebuild the entire list every time I load a new package. It seems safer to just rebuild, but sloppy. Keeping track means things could sneak in if a file gets loaded and doesn’t “register” itself with the list tracker.

We’ll have to wait and see what I come up with.