Ajax - There's nothing to it!

Apr 12, 2008

These days, when I have the pleasure to meet people who at first seem as enthusiastic about web application design as I, more often than not the question eventually arises: "So, what framework are you using?" Is everyone using some kind of Ajax framework these days?

Usually I reply that I don't use any framework; I deal with Ajax on a fundamental level. It's because of this level of intimacy that I am able to code a complete Ajax exchange application from scratch without looking up anything. Well, that's not entirely true :) I do use a pre-coded function to create the XMLHTTPRequest object for me, mostly because of the convoluted cross-browser rules required to do so. It's everything else I can code from scratch ;)

Now by this post I am not aiming to bash frameworks. They are perfectly fine if you want to avoid the minutia of customising a request each time you need one. My purpose here is mainly to cut away the hype-fueled framework-veneer which implies Ajax is a complicated, arcane mess of which only an API can possibly make sense. The truth is, Ajax is dead simple.

The hardest part comes first: creating the XMLHTTPRequest object. It's only hard because you need to do it a different way in Internet Explorer than the standard way in Opera and Firefox. This is the only part of the code that I need to copy and paste, because it works just the way it is and never needs to change:

/* ********************************************************
 * Modified from Jim Ley's implementation at jibbering.com
 *   http://www.jibbering.com/2002/4/httprequest.html
 *
 */
function getHTTPObject() {
  var xmlhttp = false;
  /*@cc_on
  @if (@_jscript_version >= 5)
    try {
      xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) { xmlhttp = false; }
    }
  @end @*/

  if (!xmlhttp) {
    try {
       xmlhttp = new XMLHttpRequest();
    } catch (e) {
      try {
        xmlhttp = window.createRequest();
      } catch (e) { xmlhttp = false; }
    }
  }
  return xmlhttp;
}

Examine the code if you will, but you don't need to know how it works. All you need to know is that now you can create the Ajax request object (XMLHTTPRequest or XHR) properly in virtually all modern browsers simply by calling the function.

var ajax = getHTTPObject();

So let's start with this and build on it, creating a valid Ajax application - at least the client side of things, anyway. Now that we have our XHR object, we need to give it a URI we want it to open.

var ajax = getHTTPObject();
ajax.open("GET", "/server-side-app.php", true);

The first argument of the open() method is the type of request we want to make. Usually GET is okay; it's the type of request your browser sends when you do a search on Google, for example. You'll notice you get sent to a location with a lot of variables in the address bar. This is how data gets passed using the GET method: via the URI. In our little example, we are going to assume the server-side script will send us info without us sending any special variables. We are just going to request the plain page and capture whatever output it sends back.

The second argument is the URI itself. It's relative to the document in which the script is included, and not to the javascript file if it's external.

The final argument tells the client whether or not this request should be asynchronous. Even though asynchronous is the A in Ajax, don't be alarmed at the ten-dollar terminology. It just means that the client should continue executing futher statements without waiting around for the request to finish. This keeps Ajax applications snappy, by keeping them from "freezing" while a request is taking place.

Now that we've done that, we need to put a function in place to handle the data we're going to get back:

var ajax = getHTTPObject();
ajax.open("GET", "/server-side-app.php", true);
ajax.onreadystatechange = function() {
  if (ajax.readyState == 4) {
    // Success
  }
};

During a request, an XHR object goes through several "ready state"s, finally ending up at 4, meaning the request has completed - but not necessarily successfully! Once we reach a readyState of 4, we know that there will be no futher modification to our XHR object so we can begin to extract data from it.

Now, even though the X in Ajax stands for XML, you can ignore that completely and just use the reponseText property. This returns a simple text string containing the entire reponse. For now, we'll just alert it.

var ajax = getHTTPObject();
ajax.open("GET", "/server-side-app.php", true);
ajax.onreadystatechange = function() {
  if (ajax.readyState == 4) {
    alert(ajax.responseText);
  }
};

So, we've set up the target and the response handler. All we need to do now is send it. We do this with one final statement:

var ajax = getHTTPObject();
ajax.open("GET", "/server-side-app.php", true);
ajax.onreadystatechange = function() {
  if (ajax.readyState == 4) {
    alert(ajax.responseText);
  }
};
ajax.send(null);

That's it! This script will request data from the /server-side-app.php page on your server and alert the reponse it recieves. It's up to you to take it further than this. For the most part, all you need to do is do something useful with the response, rather than just alerting it.

Another thing you'd likely do is put this code inside a function which is triggered by some user action, like clicking a checkbox, or making some other kind of selection.

One final thing to note concerns POST requests. If you encounter the situation where you need to send a great deal of data to the server, putting it all in the URI may not be feasible. Some browsers have a 1kB limit on URI sizes, and if your data is larger than that, you can kiss some of it goodbye. The solution is to use a POST request, which sends the data in a separate header which can be any length. We'll just modify our previous code like so:

var ajax = getHTTPObject();
ajax.open("POST", "/server-side-app.php", true);
ajax.onreadystatechange = function() {
  if (ajax.readyState == 4) {
    alert(ajax.responseText);
  }
};
ajax.send("myData");

So we changed "GET" to "POST" and put the data we're sending as the argument to the send() method. Easy right? Well, you'll be unpleasantly surprised when your keen-eyed swaps don't work at all. Sure, the request will get sent, but if you examine your server-side page, you'll find that it doesn't recieve any data. How odd!

The solution to this is an additional header, one which explicitly tells the remote server that there is POST data coming with the request and the server should look for it. Our code will now look like:

var ajax = getHTTPObject();
ajax.open("POST", "/server-side-app.php", true);
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajax.onreadystatechange = function() {
  if (ajax.readyState == 4) {
    alert(ajax.responseText);
  }
};
ajax.send("myData");

With this header, your POST requests will now work as expected.

That's all there is to it; just build on those code seeds and you'll be forging your own Ajax applications in no time. Ajax, who needs a framework when there's just nothing to it? :D

I'm finishing this up at 3am, so if you find any errors, please let me know, eh?


Comments closed

Recent posts

  1. Customize Clipboard Content on Copy: Caveats Dec 2023
  2. Orcinus Site Search now available on Github Apr 2023
  3. Looking for Orca Search 3.0 Beta Testers! Apr 2023
  4. Simple Wheel / Tire Size Calculator Feb 2023
  5. Dr. Presto - Now with MUSIC! Jan 2023
  6. Archive