AJAX for n00bs

Filed: Thu, Dec 21 2006 under Programming|| Tags: ajax tutorial beginner

Take a look on the net and you'll see endless pages of AJAX Frameworks: libraries which promise to do all the trivial and dirty AJAX work for you, leaving you free to code without actually understanding how the application you're writing really works. So lets pull back the smoke and mirrors and see what AJAX is and why it's just a simple evolution of client/server tricks Javascript programmers have been doing since the web was born.

Simply put, AJAX is a method for your javascript programs to talk to your server and send and request data. There's nothing particularly new about this. Javascript programmers have been communicating with the server in the background ever-since the FRAME tag became available. So we'll begin learning about AJAX by learning how things were done before AJAX became buzzworthy. The first thing to do is to set up an iframe somewhere on the page. The IFRAME will call a page on the server called http://www.hunlock.com/examples/notajax.html.

<IFRAME src="http://www.hunlock.com/examples/notajax.html" name="serverData" 
width=200 height=50 style='background-color: #DDDDDD'></iframe>
Here is the complete source of notajax.html:
<div ID='feedback'>Hello World!</div>

And here is the iframe, complete with the the notajax.html page loaded. Note that it's visible just for the purposes of this example. If we were actually using this method to transfer data on a production website, we'd make the iframe invisible and 1 pixel in size.


What we want to do now is access the data in the iframe and act on it so here's a little javascript snippet to do just that.

function test() {
   iframeData=serverData.document.getElementById('feedback');
   alert(iframeData.innerHTML);
}   

Now click on this link and see what happens.

What you have just seen is a web page which, after it was loaded, communicated with the server, asked for some specific data, recieved that data, and was able to act on what it received. And it did it all without AJAX. For that matter, it did it all without needing a server side script either.

There's precious little difference between using an IFRAME to communicate with the server and using an AJAX call. Indeed, AJAX is actually a bit more complex but the trade-off is that you get a little more feedback on the progress off the call, that is you have a better chance of catching when something goes wrong.

AJAX is an acronym which stands for Asyncronous Javascript And XML. It is horribly misleading because you can make syncronous calls if you want and very few people actually use the XML part. Ain't technobabble wonderful? If you'd like the history of how AJAX became part of the net check out this really nice article.

Coding wise, AJAX calls begin and end with the XMLHttpRequest object. Once you master this object, you have mastered AJAX. XMLHttpRequest is built into most modern browsers. Internet Explorer uses an activeX object which is set up a little differently but once set up, behaves exactly the same way as XMLHttpRequest. So lets start by setting up the object.

function ajaxRequest() {
   var AJAX = null;                                 // Initialize the AJAX variable.
   if (window.XMLHttpRequest) {                     // Does this browser have an XMLHttpRequest object?
      AJAX=new XMLHttpRequest();                    // Yes -- initialize it.
   } else {                                         // No, try to initialize it IE style
      AJAX=new ActiveXObject("Microsoft.XMLHTTP");  //  Wheee, ActiveX, how do we format c: again?
   }                                                // End setup Ajax.
   if (AJAX==null) {                                // If we couldn't initialize Ajax...
      alert("Your browser doesn't support AJAX.");  // Sorry msg.						
      return false                                  // Return false, couldn't set up ajax
   }
}

This code snippit merely defines a variable called AJAX and assigns an XMLHttpRequest object to it (or Microsoft's activeX version). If you noticed we used the "new" keyword when we set up AJAX, you noticed XMLHttpRequest is an object and that means it has methods and properties. Lets take a look at the methods that makes XMLHttpRequest tick.

  • AJAX.abort() -- abort the current request
  • AJAX.getAllResponseHeaders() -- returns as a string all current headers in use.
  • AJAX.getResponseHeader("headerLabel") -- returns value of the requested header.
  • AJAX.open("method", "URL"[, asyncFlag[, "userName"[, "password"]]]) -- set up a call.
  • AJAX.send(content) -- Transmit data
  • AJAX.setRequestHeader("label", "value") -- Create or change a header.

In addition to the above methods, XMLHttpRequest has the following properties.

  • AJAX.onreadystatechange -- event handler
  • AJAX.readyState -- the status of the request
    • 0 = uninitialized
    • 1 = loading
    • 2 = loaded
    • 3 = interactive
    • 4 = complete
  • AJAX.responseText -- String value of the returned data
  • AJAX.responseXML -- DOM-compatible XML value of returned data
  • AJAX.status -- Numeric status code returned by server. Example: 404 for "Not Found"
  • AJAX.statusText -- The text value of the server status. Example: "Not Found"

The Header methods are mostly used when you want to send data to the server as a POST method (IE a bunch of form data that you don't want to show up in the server logs --like credit card data and such). This article will be using the GET method to transfer data to the server since it's simpler to explain. The items we'll be using in this tutorial are open,send,onreadystatechange,readystate,responseText,status, and statusText.

Now that we have our AJAX variable declared and associated with the XMLHttpRequest object it's time to set up our first call. It may seem counter-intuitive but we begin not by sending the data to the server but by telling javascript what to do with it when we get data back from the server.

AJAX.onreadystatechange = function() {                      // When the browser has the request info..
   if (AJAX.readyState==4 || AJAX.readyState=="complete") { //  see if the complete flag is set.
      callback(AJAX.responseText, AJAX.status);             // Pass the response to our processing function
   }                                                        // End Ajax readystate check.
}                                                           // End Event Handler.

What this snippet does is to set up an event handler. When our AJAX request is complete and we've received data back from the server, this code will pass the data and the page status to a function called callback. The hard part is wrapping your head around the idea that your browser is going to be off doing other stuff then suddenly, out of the blue the browser is going to get the data back from the server and run the callback function. It's not a horribly difficult concept to understand or use, but it is a little different in that your code didn't call callback, the browser will make the call only after it's received data back from the server.

We'll have to write the callback function elsewhere in the code. There's nothing fancy here, we'll have it do the same thing our iframe example did.

function callback(serverData, serverStatus) {
   alert(serverData);
}

For the sake of simplicity we're ignoring the page status in our code. However as you develop real-world applications you'll want to check the status codes and make sure you actually got back a good response from the server (200).

So lets recap what we've done so far. We've set up a variable called AJAX which is an XMLHttpRequest object. We've then set up an onreadystatechange event that checks to see if the ajax object has finished receiving data and if so to call a function we've created called callback which will then just throw up the received data in an alert box.

Now we're going to actually set up and make the calls to the server.

var url='http://somedomain.com/getdata.php?doc=sometext.txt'; // This is the URL we will call.
AJAX.open("GET", url, true);                                  // Open the url this object was set-up with.
AJAX.send(null);                                              // Send the request.

AJAX.open does the bulk of the work here. The first parameter we set as "GET", this passes all our data back to the server in the URL. A "POST" method is also available but is more complex to set up so we're not covering it in this tutorial ( See http://www.hunlock.com/blogs/AJAX_POST-It_Notes for a tutorial using POST. ) The second parameter is the url we will be calling and since we're using a GET method we added doc=sometext.txt to the url as the data we'll be passing. The third parameter (true) says we're going to make this request asynchronously which means we're going to call the url and then go off and do other stuff without waiting for a response from the server. When the data gets back from the server the browser will call our callback function for us and we can process the data then.

If you pass false as the third parameter the browser will wait for the data to get back from the server before it does anything else. This requires a different programming structure from what we've done in this tutorial. Feel free to experiment with it, but realize that most likely this tutorial will break if you change this to false.

If your server requires you to log in you can add a fourth and fifth parameter to AJAX.open, representing your user name and password as such: AJAX.open("GET", url, true, 'johndoe','1234'). 1234? Who the heck uses 1234 as their password? For that matter who embeds their password in a web page? If you're going to pass a password back, it's best to prompt the user to enter the password then pass the user's entry rather than hard coding it.

Finally we send the request with AJAX.send(null). We're sending null (or nothing) because all of the data is in the URL because we're using GET. If you were doing a post, null would be a variable or string containing the data you're passing back as a post.

Now here is the completed function, all put together in one spot.

function callback(serverData, serverStatus) {       // Called automatically when we get data back from server
   alert(serverData);                               // Display an alert box with the recieved data
}

function ajaxRequest() {
   var AJAX = null;                                 // Initialize the AJAX variable.
   if (window.XMLHttpRequest) {                     // Does this browser have an XMLHttpRequest object?
      AJAX=new XMLHttpRequest();                    // Yes -- initialize it.
   } else {                                         // No, try to initialize it IE style
      AJAX=new ActiveXObject("Microsoft.XMLHTTP");  //  Wheee, ActiveX, how do we format c: again?
   }                                                // End setup Ajax.
   if (AJAX==null) {                                // If we couldn't initialize Ajax...
      alert("Your browser doesn't support AJAX.");  // Sorry msg.						
      return false                                  // Return false, couldn't set up ajax
   }
   AJAX.onreadystatechange = function() {                      // When the browser has the request info..
      if (AJAX.readyState==4 || AJAX.readyState=="complete") { //  see if the complete flag is set.
         callback(AJAX.responseText, AJAX.status);             // Pass the response to our processing function
      }                                                        // End Ajax readystate check.
   }
   var url='http://somedomain.com/getdata.php?doc=sometext.txt'; // This is the URL we will call.
   AJAX.open("GET", url, true);                                  // Open the url this object was set-up with.
   AJAX.send(null);                                              // Send the request.
}

Just for kicks, I modified ajaxRequest so that instead of calling some fictional, example URL, it calls http://www.hunlock.com/examples/noajax.html by changing the line which reads...

   var url='http://somedomain.com/getdata.php?doc=sometext.txt'; // This is the URL we will call.
to   
   var url='http://www.hunlock.com/examples/notajax.html';     // This is the URL we will call.

Now click on this link and see what happens. Pretty much exactly the same thing as our original no-ajax result save that the division tags are visible here.

So AJAX isn't this big, spooky, complex technology after all! It's just a more complicated way to get data back from the server without using IFRAMES! Hooray!

Javascript, of course, is only one-half of the equation. For AJAX to work to its full potential you need a server side program to process the requests and send back some data. While the server side program is worthy of its own tutorial, it's simple enough to include a small section of code here. Here's what http://somedomain.com/getdata.php would look like on the server.

<?php
   header("Cache-Control: no-cache, must-revalidate");     // Must do cache-control headers
   header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");       // or IE will pull from cache 100% of time (which is really bad)

   readfile($doc);                                         // send file to browser
                                                           // $doc is whatever was passed as doc= in the url.
                                                           // getdata.php?doc=hello.txt will open hello.txt.
?>

Pretty simple huh? All we do is pass two cache-control headers to make sure IE won't cache the url then do a simple readfile of file which was passed as doc= in the url. You'll also note, I hope, that this is horribly insecure. It's good to illustrate what's happening but you certainly don't want to use this live on the web.

Now that you have a basic grasp of what ajax is actually doing, there are two related articles you may want to browse. The first is Concurrent Ajax which shows you how to set up your AJAX function as an object making it trivial to do many different and simultaneous AJAX calls -- basically a bare bones AJAX framework without all the bells and whistles that separate you from what's really going on in your code. The second is Ajax Post-It Notes which detail how to POST data in AJAX instead of relying solely on GET -- after all, the last thing you want is for someone's credit card number, social security number or other personal data to start showing up in your server log files!