Search

Assorted Linkage

Current Terror Alert Level

ClustrMap

« Minor Simpsons spoiler | Main| Flex yer Domino »

You don't need an entire framework to use AJAX

Category javascript
With all of the many, many JavaScript frameworks to choose from, I'm getting the impression that some folks think that they can't use AJAX unless they use an entire framework. Quite the contrary. Although I often see frameworks like Prototype, Ext, YUI, etc., referred to as "AJAX frameworks", in reality the portion of each that provides AJAX functionality (as opposed to CSS selectors, DOM scripting, and other fancy widgetry) is quite minimal. In fact, if you simply want to add some AJAX to your applications and don't need a bunch of fancy widgets, the following is quite sufficient:

var Ajax = function() {
    var transport; // private variable, will store the request object
    var callback; // private variable, will store the function to run against the returned data
    var errorHandler; // private variable, will store the function to run if the request fails
    try {
        transport = new XMLHttpRequest(); // first preference, supported in all major browsers except I.E.
    } catch(e) {
        try {            
            transport = new ActiveXObject('Msxml2.XMLHTTP'); // newer versions of I.E.
        } catch (e) {
            try {            
                transport = new ActiveXObject('Microsoft.XMLHTTP'); // older versions of I.E., last resort
            } catch (e) {
                alert(e.description); // inform the user their browser doesn't support Ajax
            }
        }
    }
    var processStateChange = function() { // private function, runs whenever the request object's state changes
        if (transport.readyState === 4) { // indicates the request is completed
            if (transport.status === 200) { // indicates the request was successful
                if (callback) { // skip if no callback function was defined
                    callback(transport); // run the function defined in the options parameter and pass a handle to the request object
                }
            } else {
                if (errorHandler) {
                    errorHandler(transport); // run the function defined in the options parameter and pass a handle to the request object
                }
            }
        }
    };
    transport.onreadystatechange = processStateChange; // bind the private function to all state changes
    return { // return an object with public members that still have access to the private members
        request: function (options) {
            callback = options.onSuccess || null; // if defined, sets the private variable, otherwise replaces undefined with null
            errorHandler = options.onFailure || null; // if defined, sets the private variable, otherwise replaces undefined with null
            transport.open(options.method || 'GET',options.url,options.async || false); // establish the URL connection
            transport.send(options.postData || null); // retrieve the data
        }
    };
}(); // runs the anonymous function and sets the Ajax variable to the returned object

Calling the above is very similar to using some of the frameworks; for example:

Ajax.request({
    method: 'POST',
    url: '/' + AtFormula.WebDbName() + '/ServerSideFormula?OpenPage&formula=@Username',
    async: false,
    onSuccess: function (requestObject) {
        alert('@Username: ' + requestObject.responseText); // .responseXML would return the response as a DOM document
    },
    onFailure: function (requestObject) {
        alert('The number you dialed has been disconnected or is no longer in service.');
    }
});

In case you're curious, there are a couple nuances to the above structure that disprove some of the negative stereotypes concerning JavaScript. The stereotype I hear the most often is that JavaScript isn't a "real" programming language because it doesn't support private object members. This is, as it turns out, pure rubbish. The easiest way to dissect how this example disproves the myth is to start from the bottom and work our way up.

Instead of merely closing the function assigned to the variable Ajax with a curly, we tack on parentheses. This subtle addition causes the function to be run immediately at runtime, which assigns the result of the function to the variable, not the function itself. This is a departure from the "old" way of simulating classes in JavaScript, which was to use this.whatever within the function to establish a property or method, then to treat the function as a constructor for other objects.

Moving slightly upward, we see the return statement assigning an object literal ( {} ) as the result of the function. This is where the magic happens. Ajax becomes that object, with any members defined in the object (in this case, just the request method) publicly accessible. But the beauty of JavaScript objects is that anything already defined in the function prior to the returned object's definition is accessible to anything inside the object even after the function that created the object has finished executing. So, in this example, transport, callback, errorHandler, and processStateChange can all be accessed and updated by the object's public methods, but not by anything outside of the function that defined it. In other words, they're private. So you can rest assured that nothing outside of that function definition is mucking with those private members... if something isn't behaving as expected, you only have one place to check to see what's gone awry.

Comments

Gravatar Image1 - I like it, simple and elegant. Put an onLoading in there as well and it'l be enough for all my needs.

Post A Comment

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)

Contact Me

Hire Me

Elsewhere

What the Quote?

"I know you're excited, but stop eating your brother."

Tim Tripcony

"We could do a lot to reduce the rate of construction accidents if we could just get those 5 year-olds with head-colds off those bulldozers."

Chad Schelfhout

"I'm gonna go play some more. Don't delete my mom."

Kofi Whitney

"No, she's all four-cylinder ugly on the inside."

Laura Tripcony

"I want my MTV, dammit, but you don't hear me bitching... oh wait, that was me bitching."

Steven Rodgers

Apparel

Lotus Rocks

I write the code that makes the young girls cry