Go4Expert

Go4Expert (http://www.go4expert.com/)
-   JavaScript and AJAX (http://www.go4expert.com/articles/javascript-tutorials/)
-   -   Ajax JavaScript (http://www.go4expert.com/articles/ajax-javascript-t3478/)

Mary 19Mar2007 18:38

Ajax JavaScript
 

Get The Most Out of AJAX



AJAX is a disruptive technology that's changed the way Web apps are developed and used. It allows for interactive pages and sits on the cutting edge of current Web trends.

Although the term AJAX is relatively new, the technologies behind it are not. For many years the ability to change the content of a Web page after it had been sent to the browser had existed - using javascript to change an iframe's src attribute being one technique.

It was the coming together of the XMLHttpRequest object being implemented in the majority of browsers, and the unveiling of GMail and Google Maps that inspired developers to rethink how they build Web pages.

XMLHttpRequest Object



The XMLHttpRequest object is what makes AJAX possible, it makes the asynchronous requests and determines how to handle the results. To create the object in most browsers we use the following code:

Code: JavaScript

var xmlhttp = false;
     try {
       xmlhttp = new XMLHttpRequest();
     } catch (e) {
       alert("cannot create object");
     }

Unfortunately I said "most browsers", which of course means that it doesn't work in IE, so we need a special technique to handle Microsoft's browsers. Just to keep things interesting though, there are two cases that we have to handle depending on the version of the MSXML parser
Code: JavaScript

var xmlhttp = false;
     try {
        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
      } catch (othermicrosoft) {
        try {
          xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (failed) {
          xmlhttp = false;
     }

So when combining the two code snippets above, we end up with a piece of code that will create a XMLHttpRequest Object for all major browsers.

Code: JavaScript

var xmlhttp = false;
    try {
      xmlhttp = new XMLHttpRequest();
    } catch (trymicrosoft) {
      try {
        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
      } catch (othermicrosoft) {
        try {
          xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (failed) {
          xmlhttp = false;
        }
      }
    }

Creation Timing



Now that we can create an XMLHttpRequest we need to consider when to create it. Although we have not made a request yet, one can see that it is possible to instantiate the XMLHttpRequest object prior to sending any requests or we could create the object within a method when we need it.

One problem with creating the object when you need it is that there exists no information about whether the client can create a XMLHttpRequest object or not. If a user arrives at your site and is unable create an XMLHttpRequest object you can accommodate them much more easier if you know from the earliest time possible that AJAX is not option.

It is never a good thing to have a user begin to interact with your Web application only to inform them that they cannot use it once they click on a submit button and have completely wasted their time filling out your form.

Whereas if the XMLHttpRequest creation is attempted at the start of the page, alternatives such as redirecting to a non-AJAX page become available before user interaction begins.

Setting up the request



At this stage we have a page creating an XMLHttpRequest object when it is loaded, now let's use it for the purpose for which it was intended - making requests.

To do this we have to pass at least two parameters to the open method, most of these are straight forward to understand.

Code: JavaScript

xmlhttp.open(Method, Url [, Async] [, User] [, Password])

The Method parameter defines the request method; our choices here are "POST", "GET" or "HEAD". To begin with, we are only going to use GET.

Url is the url string of the page we want to request. We cannot go and request any old page we like though, there is a sandbox that prevents us from accessing pages that are not the same domain as the page that is creating the request.

Async is what makes AJAX possible. Even though it is an optional parameter as defined in the API, for our purposes this parameter is mandatory and must be set to true - if it is set to false, the script will hold until a response is received. The default value for this parameter is true so you could choose not to set it, but in the interest of readability and maintainance, it is highly recommended to set this value.

User and Password are used for authentication if you choose to have it.

Once we set Async to true, we need to define a method to be called once the request state changes - this is done by setting the onreadystatechange property on XMLHttpRequest object.

Code: JavaScript

xmlhttp.onreadystatechange = myReturnMethod;

The last thing left to do is send the request off, for the moment we are going to keep things simple and send the request without any additional data.

Code: JavaScript

xmlhttp.send(null);

Putting this all together in a simple example:

Code: JavaScript

xmlhttp.open("GET", "/some_dir/myfile.html", true);
     xmlhttp.onreadystatechange = myReturnMethod;
     xmlhttp.send(null);

Three lines is all we need to enter the world of AJAX, no complicated concepts or twisted logic is needed.

Ready State



Previously I said that we need to define a method to be called once the request state changes and that this is done by setting the onreadystatechange property; you should note that I said 'state changes', not 'complete' - for those are two completely different things. The best way to show this is by way of example, incorporating everything that we have learnt so far. Put the following in one file:

Code: HTML

<script>
    var xmlhttp = false;
    try {
      xmlhttp = new XMLHttpRequest();
    } catch (trymicrosoft) {
      try {
        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
      } catch (othermicrosoft) {
        try {
          xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (failed) {
          xmlhttp = false;
        }
      }
    }

    function goAJAX() {
             alert("Initial Ready State is:"+xmlhttp.readyState);

         xmlhttp.onreadystatechange = myReturnMethod;
         xmlhttp.open("GET", "another_file.html", true);
         xmlhttp.send(null);
     }

     function myReturnMethod() {
          alert("New Ready State is:"+xmlhttp.readyState);
     }
</script>
<button onclick="javascript:goAJAX()">Let's try it!</button>

In the file being requested we can fill it with anything we desire, we are not going to use it's contents yet, as long as it is able to be found.

When the button is pressed we should notice that the readystate alert appears multiple times and eventually it will show the readyState equal to 4. Different browsers handle this differently, in Safari it counts nicely from 0-4 but in firefox it has 1 appear twice and 0 only appears on the first time it is run. Thankfully for us, we are only interested when the readyState is 4, but for the sake of completeness let's see what those numbers actually mean.

* 0: uninitialised - the object contains no data, prior to open being called
* 1: object is loading its data - prior to send being called
* 2: loaded - the request has been sent
* 3: interactive - the request is being processed and some data maybe available but is incomplete and thus unsafe to use
* 4: complete - the request is complete and the resultant data is safe to use

Armed with this new information we can change myReturnMethod to only have the alert appear when the request is complete.

Code: JavaScript

function myReturnMethod() {
         if (xmlhttp.readyState==4){
              alert("New Ready State is:"+xmlhttp.readyState);
         }
     }

Response status



Taking the previous code, let's change the url parameter of the open method to a file that does not exist:

Code: JavaScript

xmlhttp.open("GET", "filethatdoesnotexist.html", true);

Running the code again we see that it performs exactly the same as the previous code - what is happening here?

If it were a regular http request we would expect a 404 error to appear - the same applies in AJAX with the status property. This property is read only and contains the HTTP status code of the request, in the case of our file it is 404. The same status codes we are used to in a regular http request still apply when working with AJAX. (Note that for this to work properly the page should be requested from an HTTP server, if it is read from the filesystem the status code will always be undefined.)

Therefore we need to add an if statement that tests whether the request was successful, if it is a response code of 200 will be returned. If it is not successful we need to be able to handle the error should we choose to.

Code: JavaScript

function myReturnMethod() {
         if (xmlhttp.readyState==4){
             if (xmlhttp.status == 200) {
                 alert("Request successfully completed");
             }
             else if(xmlhttp.status == 404) {
                 alert("Requested file not found");
             }
             else {
                 alert("Error has occurred with status code: 
"
+xmlhttp.status);
             }
         }
     }

ResponseText & responseXML



Now that we are able to successfully complete an AJAX request, we need to do something with the results. There are two ways that we can do this, by using the responseText or the responseXML properties. The easiest way to fetch the data that the server has returned is to use the responseText property as it returns the data as plain text. This way the data can be anything that we want it to be: simple text responses, comma delimited values or an entire book in one string. In our return method we will output the responseText in an alert, this will output the entire contents of the file we are requesting.

At this stage if you have not put any contents into the file we have been requesting, another_file.html, you should do so.

Code: JavaScript

function myReturnMethod() {
         if (xmlhttp.readyState==4){
             if (xmlhttp.status == 200) {
                 alert(xmlhttp.responseText);
             }
             else if(xmlhttp.status == 404) {
                 alert("Requested file not found");
             }
             else {
                 alert("Error has occurred with status code: "+xmlhttp.status);
             }
         }
     }

An alternate technique to retrieve the resultant data is to use the responseXML property, it returns the data as an XMLDocument object which has to be traversed using the Javascript DOM functions. To be able to see this in action we will need to return a properly formatted XML document; let's create a new file to request (xmlresult.html) and put the following into it:

Code: XML

<?xml version="1.0" encoding="UTF-8"?>
     <root>
         XML Formatted Result
     </root>

We then need to change the open call to:

Code: JavaScript

xmlhttp.open("GET", "xmlresult.html", true);

The biggest changes are in our return method where we need to replace alert(xmlhttp.responseText); with:

Code: JavaScript

xmldoc = xmlhttp.responseXML;
     rootnode = xmldoc.getElementsByTagName('root').item(0);
     alert(rootnode.firstChild.data);

And voila, we are using the DOM to return data.

With a combination of existing javascript functions we know, this data can be used to manipulate a page's content. For instance:

Code: JavaScript

document.getElementById('resultdiv').innerHTML = xmlhttp.responseText;

When to use AJAX



Now that we know how to create a request and fetch the results, one question that has yet to be answered is, when should we use AJAX?

Naturally with such a new technique there are extremes in both opinions, some Web developers think that life would be easier if AJAX just disappeared altogether while others would love nothing better than to see an entire site written within an AJAX framework. As is usual with such things, the truth of the matter is somewhere in between these two points. When using AJAX on your site you should be aware of the consequences of your decision. Firstly any page you manipulate with AJAX is not guaranteed to be bookmarkable. The usage of AJAX introduces a "state" into your Web site which will not enable users to return to any state except the initial state. This is because the url does not change in the user's broswer - if it did change, then there would be no need for AJAX.

Secondly you will have doubled your work if you want to support each and every user to your site. For every fragment of your site that you create using AJAX, you will have to cater to users that do not have javascript enabled. A lot extra work is needed if you want to have a page degrade gracefully for javascript and non-javascript users alike, usage of noscript tags is a must.

That said, AJAX can improve usability of a site by reducing the number of page reloads needed to navigate and interact with it. Combined with javascript effect libraries we can create some very impressive Web interactions that would not have been possible a couple of years ago. Therefore, it is my belief that the place to use AJAX is in a non- essential part of your site. On this site, for instance, it would be an extremely bad idea to serve articles using an AJAX framework because your could no longer bookmark articles to read later without implementing a permalink structure. On the other hand, an article rating or talkback system would be very fitting for an AJAX implementation.

On your way



You've made it! We've created a foundation you can build on and have seen how asynchronous requests are made by using javascript, but this is far from a comprehensive treatment. There is much more that we have to investigate and learn about - making HEAD and POST requests, using forms with AJAX and incorporating PHP into our AJAX system. Until that time, we are equipped enough to begin to create basic requests and should we look at javascript of a site using AJAX, we will no longer be lost at sea.


All times are GMT +5.5. The time now is 23:18.