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:

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

Four lines longer and only a little less readable.

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

Advertisements

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:

/js/myscript.js

/js/myscript-min.js

/js/corefiles-combo.js

(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.

Marketing

It’s time.

My web tool is starting to show slivers of promise! This in no way correlates with functionality; it’s still 99% incomplete. But, my goal has been to get to the point where I can *explain* my concept to someone, who can then explain it to others – i.e. investors, customers and future employees and work with me to morph the idea into something we can build and sell. I think I’m close enough to start looking for that person.

I have a few friends and relatives I’m hoping will help me get started on the search.

In the meantime, if you are or happen to know someone who might be this person, please let me know.

Interface

I’ve been working on the web tool interface recently. I don’t have much to write about, since it mostly involves me reading about design, trying ideas, learning about new YUI components, etc.

I’m trying to decide exactly how structured to make the test case editor right now. Free-form? Free-form with tags? Structured lines, but free-form within the line? Or, not free-form at all and build everything from structured tags. I would give an example, but I don’t have anything that I can show yet.

I have many conflicting goals: it needs to be *fast*. Fast to enter, fast to work with imported tests and fast in terms of the actual UI responsiveness.

On the other hand, almost all “add ons” will need structured data. It is very difficult to do processing on free-form data.

My Synchronous Javascript Solution

I wrote about the problem I was having with the asynchronous (albeit single-threaded) nature of Javascript in my last post.

After looking at the options to make my code more clear when using asynchronous calls in Javascript, I’ve decided to take a simple approach. Instead of using one of the libraries, I’ve come up with what is basically a different way to format my code.

I can’t tell if this will be my long-term answer yet; I’ll just have to get further into the project and see how it goes.

So, here’s what I did. First, I wrote a function to do the actual asynchronous call. The only special thing about it is that it returns TRUE or FALSE, plus the return object.

PX.Rest = function (method, url, data, callback) {
    var successHandler, failureHandler, makeRequest, request;
    successHandler = function (o) {
        callback(true, o);
    };
    failureHandler = function (o) {
        callback(false, o);
    };

    makeRequest = function () {
        YAHOO.util.Connect.initHeader('Content-Type', 'text/json', true);
        request = YAHOO.util.Connect.asyncRequest(
            method,
            url,
            { success: successHandler,
              failure: failureHandler,
              connTimeout: 8000
            },
            data
        );
    };
    makeRequest();
};

Now, this lets me write my code like so:

// The first AJAX call.
PX.Rest(method, sUrl, jsonData,
    function (result, o) {
        if (result) {
            // If I'm here, it means the initial call was successful.

            // The second AJAX call (for example, to tag the record I just created).
            PX.Rest(method, sUrl, undefined,
                function (result, o) {
                    if (result) {
                        // The second call passed also
                    } else {
                        // The second call failed (after the first call succeeded)
                    }
                    // Code that runs no matter if the second call passes or fails
                }
            );
            // Code that runs when the first call passes but BEFORE the second one returns.
        } else {
            // The first call failed.
            // In this example, I don't do anything else.
        }
    }
);

Now it flows!  It’s almost like using nested if statements.

Here’s why I (think) it works:

  • The arguments are ordered in such a way  that the last one is the callback. This allows you to simply indent it in order to make it obvious you are inside conditional code.
  • The PX.Rest function from above returns TRUE or FALSE, which allows me to use a ‘If (request)’ in-line. That way, I can continue to simply indent and don’t have to create separate callbacks, define them ahead of time, etc.

I certainly don’t think this is a perfect solution, but it does allow me follow the flow of my code much more easily. I wouldn’t want to go more than two or three calls deep, though!

Wrapping my head around Asynchronous Javascript

Most of the Javascript I use involves AJAX. Even before I really knew how to program in Javascript , my first cut & paste programs were AJAX simply because of the site I’m building. As I get deeper into the coding, trying to get multiple parts of my site to work together, the asyncronous model is getting harder and harder to work with.

Here is a simple pseudo-code example:

myFunction = function () {
    successHandler = function () {
    }
    failureHandler = function () {
    }
    ajaxSetup = function () {
    }
    ajaxSetup();
}

That’s not too bad. As I’ve said before, I think it’s a bit verbose, but workable.

Putting it into the regular flow of code is harder. Here is my (made up) example:

  1. Create a new window
  2. Get data from the server
  3. Format the data with links
  4. Update a counter on the server

In pesudo-code again, it might look like this:

createMyWindow();
myFunction = function () {
    successHandler = function () {
        formatTheData();
        myCounterUpdate = function () {
            myCounterUpdateSuccessHandler = function () {
            }
            myCounterUpdateFailureHandler = function () {
            }
            myCounterUpdateajaxSetup = function () {
            }
            myCounterUpdateajaxSetup();
        }
    }
    failureHandler = function () {
    }
    ajaxSetup = function () {
    }
    ajaxSetup();
}

Yuck! I actually have some code like this and was just going to deal with it. But, one of my flows required a third layer.

I simply can’t maintain any sense of the program with so many layers! So, I went looking for solutions and found this blog post by Harry Fuecks. It’s a couple of years old, but seems to capture exactly what my issue is and has some solutions. One is called Narrative Javascript and another is jwacs.

I’m not sure I like any of the solutions, though, since they involve adding a lot more code. But, I’m still wrestling with this issue, trying to re-factor a bit to gain control and see what other solutions there might be.

“Dime a Dozen”

I’m searching for a co-founder. It’s not easy. I’ve been attending group meetings and events for months where the kind of person I’m looking for might attend, but haven’t had any luck (yet).

My latest idea was to simply post an ad. I’ve had great success selling, giving away and buying things on Craigslist, so it seemed like a natural choice.

I think of Craigslist as free, but quickly remembered that they do charge for some things and job postings in the San Francisco Bay Area are one of them. I didn’t really want to spend $75, so I choose the Gigs/Computers area instead of Jobs. So far, so good.

I then wrote what I thought was a very clear and simple add. I clicked “No Pay” at the bottom (no bait and switch here!). After I posted, I quickly received a response for a company who was selling the services that I menteioned in my ad. So far, so good. And, fast!

Then– wham! Flagged.

Flagged?! Why?

I re-read the Terms of Service and was sure I was fine. So, I posted my query to the discussion board suggested in the message and found out right away what the issue was: people want to get paid. And, even though my ad was not against the Terms of Service, they hate “no pay” ads.

  • A dime a dozen.
  • Everyone wants a free geek (hey! I’m the geek here!).
  • People just want to pay their rent.
  • No Pay – No Stay.

Here’s the actual ad, in case YOU are interested.

I’m building a web tool for software test design (QA, basically) and need someone who can make it look good. I have ideas in terms of the functionality and some vague ideas about how it will look, but have zero ability to actually make it gel in terms of design.

Since I have the technical skills,  I’m not looking for a framework or a turnkey site. I’m specifically looking for someone who can create a look and feel, including colors, typography, graphics, etc. and then put it all together using CSS, HTML, graphics and fonts. I’ve started  using Yahoo’s YUI, so experience or a desire to learn how it works is necessary. Knowledge and expertise in user experience would also be great.

My goal is to get this tool working to the point where I can give a demonstration,  then start looking for funding. In the meantime, I’m out of a job and working on this full-time.

So, are you interested in being a co-founder? Having some kind of deferred compensation? Out of work and bored and want something to add to your portfolio? I’m open to pretty much anything, so if you are the person that I’ve described above, let’s talk!

Managing a non-trivial amount of JavaScript

Even though I’m still new to JavaScript, I’m using it most of the time now. My initial attempts with copy & pasting code, watching YouTube videos, reading blogs, etc. were not getting me up to speed fast enough. I also came to realize that I had some fundamental misunderstanding about the language. So, I took a break and read Douglas Crockford’s JavaScritpt: The Good Parts. How refreshing!

Now many of the  issues I was having, especially when comparing Perl code with JavaScript, had real answers. And, getting some real answers for differences in style of JavaScript code had some actual answers as well (due to things like the automatic semi-colon insertion).

My biggest discovery of all is the “Method Pattern.” (pp. 40-21). Eric Miraglia explains it very, very well in his blog post. This shows how to avoid Global Variable problems, make code more modular and all that other good stuff. It is *very* verbose (in my opinion). But, it works, I understand it and I can build a site with code structured like this with confidence.

With this new knowledge and the knowledge I already had about page size and performance issues with Rich Internet Applications (RIAs), I developed a way to load code on demand. I first wrote a “Loader” script. Then, I wrote a template to use that would interact with the Loader.

An example. Let’s say I wanted to open an interactive window. This window might require CSS files, JavaScript files, markup and data. And, some of it might already be loaded, but there is no guarantee. So, instead of dealing with this when you want to make the call, just call the Loader script with the action you want and let it take care of it.
Examples:
To open a dialog box:

pxLoader.open("dialog_box");

To close the dialog box:

pxLoader.close("dialog_box");

To make this work, I would need a standard set of commands (init, open, close, etc.)

So, if you want to check it out, here is the actual code. I ran it through JSLint with Recommended Options and Good Parts turned on. Be aware that I’ve only used it a bit and so have not flushed out all the issues that will make this truly robust.

Note: px is just a placeholder name. “plain_jane” would become “dialog_box” or “category_dialog) or whatever feature you were implementing. Oh, and I log. A lot.

// Copyright (c) 2009 Brian Estes - All Rights Reserved

/*global YAHOO */
YAHOO.namespace("px.plain_jane");
YAHOO.px.plain_jane = function () {
    YAHOO.log("Instantiating", "begin", "pxPlainJane");

    var example, setupListeners;

    example = function (o) {
        YAHOO.log("examle", "begin", "pxPlainJane");

        YAHOO.log("example", "end", "pxPlainJane");
    };

    setupListeners = function () {
        YAHOO.log("setupListeners", "begin", "pxPlainJane");
        YAHOO.util.Event.addListener(
            "plain_jane_one",
            "click",
            function () {
                YAHOO.log("clicked plain_jane_update", "info", "pxPlainJane");
            }
          );

        YAHOO.util.Event.addListener(
            "plain_jane_two",
            "click",
            function () {
                YAHOO.log("clicked plain_jane_one", "info", "pxPlainJane");
                YAHOO.px.Loader.open('some_package');
            }
        );
        YAHOO.log("setupListeners", "end", "pxPlainJane");
    };

    return {        // public methods
        init: function (o) {
            YAHOO.log(".init", "begin", "pxPlainJane");
            example(o);
            setupListners();
            YAHOO.log(".init", "end", "pxPlainJane");
        },
        open: function (o) {
            YAHOO.log(".open", "info", "pxPlainJane");
        },
        refresh: function (o) {
            YAHOO.log(".refresh", "info", "pxPlainJane");
        },
        close: function (o) {
            YAHOO.log(".close", "info", "pxPlainJane");
        },
        destroy: function (o) {
            YAHOO.log(".destroy", "info", "pxPlainJane");
        },
        exists: function (o) {
            YAHOO.log(".exists", "info", "pxPlainJane");
        },
        visible: function (o) {
            YAHOO.log(".visible", "info", "pxPlainJane");
        },
        ready: function (o) {
            YAHOO.log(".ready", "info", "pxPlainJane");
        }
    };
}();

YAHOO.util.Event.onDOMReady(function () {
    //YAHOO.px.plain_jane.init();
});

YAHOO.log("Instantiating", "end", "pxPlainJane");

Image sprites

Sprites were easier than I expected. Make a graphic, put multiple icons inside, put the ‘hover’ or rollover versions in there as well, then refer to them by coordinates.

The next step is to use this technique to make the site look good.

For that, I need someone who can design.