Blog of Jeff A blog about programming and random other things.

22Nov/09link

“Brief” Guide to JavaScript – Part 11

You should check out the previous parts before continuing with this final part:

Ajax

It's part of the "Web 2.0" trend. Ajax, or Asynchronous JavaScript and XML provides a background-styled http request to a URL. This is different from the traditional, "load a new page to perform an action" style. With the ability to essentially load a page in the background, you can let the user interact with the rest of your site while performing an operation by the user.


Pros & Cons

"With great power, comes great responsibility."

Ajax provides some very nice benefits, but there are some issues you should consider before determining to use ajax. A lighter-weight response from the server (instead of a full page reload) which can improve the user experience with ajax. But keep in mind:

  • The user's back button won't "undo" the last action. This has to be implemented manually.
  • Browsers without JavaScript or Ajax can't perform these actions.
  • Search engines & bots usually don't run JavaScript, so content provided via ajax is inaccessible to them.
  • Ajax doesn't provide an accessible way for blind people to figure out changes on a page (if any).

Providing a graceful alternative, the traditional page-reload mechanisms, is a good way to combat most of the issues above. Although, it's a good practice to avoid using Ajax for simply displaying content.

XMLHttpRequest

The core behind Ajax is the XMLHttpRequest object in JavaScript. XMLHttpRequest is a functional object that needs to be instantiated, so we do this:

 


var request;
try{
    if(XMLHttpRequest) // for all modern browsers
        request = new XMLHttpRequest();
    else // for IE prior to 8
        request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(error){
    request = false;
}
if(request){
    // do ajax stuff here...
} else {
    // browser doesn't support ajax
}

It's worth noting the both the ActiveXObject & XMLHttpRequest object have the possibility of throwing an exception, so use a try/catch block and handle if the feature is not supported.

Next, we need to configure the request object, the basics:


request.open('get', 'http://google.com', true);

open interface is as follows:


open(method, url, async?, username, password)
  • method: usually a string of get or post which describes how additional data should be sent. Identical to the method attribute of form tags.
  • url: the url to fetch. Identical to the action attribute of form tags.
  • async?: You should usually set this to true. This tells the browser to perform the request asynchronously and not freeze up the browser. The advantage of synchronous is after you perform the request, you can immediately use the results in your next line of code. This cannot be guaranteed with an asynchronous request. (optional - defaults true)
  • username & password: is the simple http-supported username & password. This does not work for sites that have a username & password login form, but rather for urls that prompt a login dialog before displaying the page. (optional - defaults to no login credentials)

Of course, doing an async request is useless if we can't handle it when the request is completed, so we add an event handler.


request.onreadystatechanged = function(){
    // our code goes here.
};

There's a handful of different cases when this handler will be called. In order to differentiate between the requests, the XMLHttpRequest object has a readyState property which we can use to check the current state the request is in. The values are:

  • 0: The xmlhttp object hasn't been initialized
  • 1: Xmlhttp object has been initialized
  • 2: Xmlhttp object has sent request
  • 3: Xmlhttp object is being processed (performing request)
  • 4: Xmlhttp object is completed (the request is completed)

Most of the time, you'll be checking to see the readyState property is 4.

Also worth mentioning the status property, for the XMLHttpRequest object, which returns the server response code from the request: 200 for successful request, 404 for missing file, etc.

Finally, there's the responseText property which contains the content of the server request.

Now let's build our onreadystate function body:

 


request.onreadystatechanged = function(){
    // ajax request finished & server returned 200
    // (url resource found and returned)
    // it's probably a better idea to accept any
    // status in the 200's, but for simplicity, we'll
    // do this
    if(request.readyState == 4 && request.status == 200){
        var c = document.getElementById('ajax_content');
        c.innerHTML = request.responseText;
    }
};

Here we set the interior html of the element with id attribute of ajax_content to whatever the server gave us. After we configured our object, we need to perform the request:


// string contains POST data to send to the server. null indicates no POST data.
request.send(null);

It's worth noting the POST data string should be in a query-string format:


request.send('var1=value1&var2=value2');

That's it, JavaScript ajax in a nutshell. No fancy voodoo magic.

XML / HTML / Text data

Just pinging a URL is definitely not useful, we want to handle the data from the user. There are several typical server responses, but usually you have control over this since ajax is used to improve the user experience of your web app.

For text we simply utilize the responseText property:


request.onreadystatechanged = function(){
    if(request.readyState == 4 && request.status == 200){
        // request.responseText
    }
};

This behavior is similar for XML, except when you need to parse them for specific information, then responseXML will be your friend then.

 


request.onreadystatechanged = function(){
    if(request.readyState == 4 && request.status == 200){
        // request.responseXML is like a DOM object, supporting DOM
        // traversal techniques.
        alert(request.responseXML.getElementsByTagName(‘h1’).length);
    }
}

Alternatively, you can manually create the XML parser object:


request.onreadystatechanged = function(){
    if(request.readyState == 4 && request.status == 200){
        var contents = request.responseText;
        var xml = null;
        if(window.DOMParser){ // all browsers but IE
            var parser = new DOMParser();
            xml = parser.parseFromString(contents, ‘text/xml’);
        } else { // internet explorer
            xml = new ActiveXObject(‘Microsoft.XMLDOM’);
            xml.async=’false’;
            xml.loadXML(contents);
        }
        // use xml identically to request.responseXML
    }
}

JSON

Another common data-transfer format is JSON (JavaScript Object Notation), which is a subset of JavaScript syntax – specifically the data structures part. The only accepted types of JSON are:

  • Numbers – 1, 2.5, –4, –5.2, etc.
  • Booleans – true, false
  • Null value
  • Strings - ‘abc’, “defghi”
  • Arrays – [‘a’, 1, 2]
  • Objects – {‘key’ : ‘value’} where keys must be strings!

The main advantage is the simple ways to use JSON as true JavaScript values. Given that json_string contains json data – whether from ajax or somewhere else – we can simply do:


var json = eval(‘(‘ + json_string + ‘)’);

To convert it to it’s equivalent data structure in JavaScript. Using eval is not safe parsing unsafe JSON code (eg – from a third party), use the JSON parser at json.org. This is simply because eval interprets a given string as JavaScript: including function calls and prototype definitions.

The json.org parser is also bundled with a stringify function to convert JavaScript data structures into JSON.

The End

(no really)

I’m wrapping up my exhausting JavaScript coverage here. But there’s plenty more things to learn if you’re up to it:

  • Debugging your JavaScript in IE, Safari, Firefox (with Firebug), etc.
  • Gracefully degrading when the user doesn’t have JavaScript or certain JavaScript features
  • JavaScript optimization techniques
  • XPath for DOM traversal
  • AJAX
  • Supporting the back button with AJAX actions
  • Modifying/Reading HTTP Headers
  • JavaScript Frameworks (Prototype/Scriptaculous, Mootools, YUI, jQuery, dojo, ext, etc.)
  • With that, I’ll tilt my hat, and walk off. If only I had a cool hat.

    - Jeff

    • Share/Bookmark

    Recent Posts

    Topics

    Archives

    Following

    Links