In This Chapter
If you’ve been following the Web trends, you’ve no doubt heard of AJAX.
This technology has generated a lot of interest. Depending on who you listen to, it’s either going to “change the Internet” or “it’s a lot of overblown hype.” In this topic I show what AJAX really is, how to use it, and how to use a particular AJAX library to supercharge your Web pages.
AJAX: Return to Troy
Okay, AJAX has nothing to do with a sequel to the Iliad (though that would be pretty cool). But since I have your attention, let’s discuss AJAX, the mighty and very real Web technology. The first thing to do is figure out exactly what AJAX is and what it isn’t. It isn’t
A programming language. Nope. It isn’t one more language to cram into your head (along with the many others you encounter).
New. No. Most of the technology in AJAX isn’t really all that new. It’s the way it’s being used that’s different.
Remarkably different. Not really. For the most part, AJAX is really the same kinds of things you see in the rest of this topic. It’s about building compliant Web pages that interact with the user.
So you’ve got to wonder why people are so excited about AJAX. It’s a relatively simple thing, but it has the potential to change the way people think about Internet development. Here’s what it really is, has, and does:
Direct control of client-server communication. Rather than relying on the automatic communication between client and server that happens with Web sites and server-side programs, AJAX is about managing this relationship more directly.
Use of the XMLHttpRequest object. This is a special object that’s been built into the DOM of all major browsers for some time, but hasn’t been used heavily. The real innovation of AJAX was finding creative (perhaps unintentional) uses for this heretofore-obscure utility.
Let’s say you’re making an online purchase with a shopping-cart mechanism.
Every time you make a request, the system builds a whole new page on the fly. The client and server have a long-distance relationship.
In the old days when you wanted to manage your Web site’s content, you had to refresh each Web page — time-consuming to say the least. But with AJAX, you can update the content without refreshing the page. Instead of the server sending an entire-page response just to update a few words, the server only sends the words you want to update and nothing else.
If you’re using an AJAX-enabled shopping cart, you might still click the fish-bowl image. An AJAX request goes to the server and gets information about the fishbowl. And here’s the good part: This information appears immediately on the current page, without having to completely refresh the page.
AJAX technology allows you to send a request to the server, which can then change just a small part of the page. With AJAX, you can have a whole bunch of smaller requests happening all the time, rather than a few big ones that rebuild the page in large, distracting flurries of activity.
To the user, this makes the Web page look more like a traditional application. That’s the big appeal of AJAX: It allows Web applications to act more like desktop apps, even if the Web apps have complicated features (such as remote database access).
Google’s Gmail was the first major application to use AJAX, and it blew people away because it felt so much like a regular application inside a Web browser.
AJAX Spelled Out
A is for asynchronous
An asynchronous transaction (at least in AJAX terms) is one in which more than one thing can happen at once. For example you can have an AJAX call process a request while the rest of your form is being processed. AJAX requests do not absolutely have to be asynchronous, but they usually are. (It’s really okay if you don’t follow this completely. It’s not an important part of understanding AJAX, but vowels are always nice in an acronym.)
When it comes to Web development, asynchronous means you can send and receive as many different requests as you want — independently. Data might start transmitting at any time without having any effect on other data transmissions. You could have a form that saves each field to the database as soon as it’s filled out. Or perhaps a series of drop-down lists that generates another drop-down list based on the value you just selected.
In this chapter, I show you how to implement both synchronous and asynchronous versions of AJAX.
A is for . . . and?
I think it’s a stretch to use “and” in an acronym, but AJX just isn’t as cool as AJAX. I guess they didn’t ask me.
AndX is for… data?
The X is actually for XML, which is one way to send the data back and forth from the server.
Because the object we’re using is the XMLHttpRequest object, it makes sense that it requests XML. It can do that, yes, but it can also get any kind of text data. You can use AJAX to retrieve all kinds of things:
Plain old text: Sometimes you just want to grab some text from the server. Maybe you have a text file with a daily quote in it or something.
Formatted HTML: You can have text stored on the server as a snippet of HTML/XHTML code and use AJAX to load this page snippet into your browser. This gives you a powerful way to build a page from a series of smaller segments. You can use this to re-use parts of your page (say headings or menus) without duplicating them on the server.
‘ XML data: XML is a great way to pass data around (That’s what it was invented for.) You might send a request to a program that goes to a database, makes a request, and returns the result as XML.
In this chapter, I stick with plain old text and HTML. Chapter 14 describes mechanisms for working with XML and JSON data in AJAX.
Making a Basic AJAX Connection
AJAX uses some pretty technical parts of the Web in ways that might be unfamiliar to you. Read through the rest of this chapter so you know what AJAX is doing, but don’t get bogged down in the details. Nobody does it by hand! (Except for people who write AJAX libraries or topics about using AJAX.) In Chapter 10 I show a library that does all the work for you. If all these details are making you misty-eyed, just skip ahead to the next chapter and come back here when you’re ready to see how all the magic works.
The basicAJax.html program shown in Figure 9-1 illustrates AJAX at work.
Click the button and you’ll see some AJAX magic.
When the user clicks on the link, a small pop-up shown in Figure 9-2 appears.
If you download this file to your own machine, it will probably not run correctly. That’s because AJAX relies on a Web server for its magic. AJAX code will only work properly if it is on a Web server. If you want to test AJAX, you’ll need to post it onto a Web host or install a server on your own machine. Chapter 14 outlines this process. The examples are working on my Web site, so you can always look there:
This text came from the server.
If you don’t get the joke, you need to go rent Monty Python and the Holy Grail. It’s part of geek culture. Trust me. In fact, you should really own a copy.
You might claim that HTML frames allow you to pull data from the server, but frames have been deprecated (labeled obsolete) in XHTML because they cause a lot of other problems. You can use a frame to load data from the server, but you can’t do all the other cool things with frame-based data that you can with AJAX. Even if frames were allowed, AJAX is a much better solution most of the time.
This particular example uses a couple of shortcuts to make it easier to understand:
It isn’t fully asynchronous. The program will pause while it retrieves data. As a user, you won’t even notice this, but as you’ll see, this can have a serious drawback. It’s a bit simpler, so I start with this example and then extend it to make the asynchronous version.
It isn’t completely cross-browser. The AJAX technique I use in this program works fine for IE 7 and 8 and all versions of Firefox (and most other standards-compliant browsers). It does not work correctly, however, in IE 6 and earlier. I recommend you use jQuery or another library (described in Chapter 10) for cross-browser compatibility.
Look over the code, and you’ll find it reasonable enough:
Building the HTML form
You don’t absolutely need an HTML form for AJAX, but I have a simple one here, complete with a button. Note that the form is not attached to the server in any way. Here’s the code:
Creating an XMLHttpRequest object
The key to AJAX is a special object called the XMLHttpRequest object. All the major browsers have it, and knowing how to use it in code is what makes AJAX work. It’s pretty easy to create with the new keyword:
Internet Explorer, in versions 5 and 6, had an entirely different way of invoking the XMLHttpRequest object — involving a technology called ActiveX. If you want to support these older browsers, use one of the libraries mentioned in Chapter 10. (I’ve decided not to worry about them in this introductory chapter.)
This line makes an instance of the XMLHttpRequest object. You’ll use methods and properties of this object to control a request to the server (as shown in Table 9-1).
AJAX is really nothing more than HTTP, the protocol that your browser and server quietly use all the time to communicate with each other. You can think of an AJAX request like this: Imagine you have a basket with a balloon tied to the handle and a long string. As you walk around the city, you can release the basket under a particular window and let it rise up. The window (server) will put something in the basket, and you can then wind the string to bring the basket back down and retrieve the contents.
|Table 1-1 Useful Members of the XMLHttpRequest Object|
|open(protocol, URL, synchronization)||Opens up a connection to the indicated file on the server.||Stands under a particular window.|
|send(parameters)||Initiates the transaction with given parameters (or null).||Releases the basket but hangs on to the string.|
|status||Returns the HTTP status code returned by the server (200 is success).||Checks for error codes (“window closed,” “balloon popped,” “string broken,” or “everything’s great”).|
|statusText||Text form of HTTP status.||Text form of status code, a text translation of the numeric error code returned by status.|
|responseText||Text of the transaction’s response.||Gets the contents of the basket.|
|readyState||Describes current status of the transaction (4 is complete).||Is the basket empty, going up, coming down, or here and ready to get contents?|
|onReadyStateChange||Event handler. Attach a function to this parameter, and when the readyState changes, the function will be called automatically.||What should I do when the state of the basket changes? For example, should I do something when I get the basket
Don’t worry about all the details in this table. I describe these things as you need them in the text. Also, some of these elements only pertain to asynchronous connections, so you won’t always need them all.
Opening a connection to the server
The XMLHttpRequest object has several useful methods. One of the most important is the open() method. Here’s what it looks like in action:
The open() method opens up a connection to the server. As far as the server is concerned, this connection is identical to the connection made when the user clicks a link or submits a form. The open() method takes three parameters:
‘ The request method: The request method describes how the server should process the request. Typical values are GET and POST. The use of these values is described in Chapter 14.
A file or program name: The second parameter is the name of a file or program on the server. This is usually a program or file in the same directory as the current page.
A synchronization trigger: AJAX can be done in synchronous or asynchronous mode. (Yeah, I know, then it’d be AJAX or SJAX, but stay with me here.) The synchronous form is easier to understand, so I use it first. The next example (and all the others in this topic) will use the asynchronous approach.
For this example, I use the GET mechanism to load a file called beast.txt from the server in synchronized mode.
Sending the request and parameters
Once you’ve opened up a request, you need to pass that request to the server. The send() method performs this task. It also provides you a mechanism for sending data to the server. This arrangement only makes sense if the request is going to a PHP program (or some other program on the server). Because I’m just requesting a regular text document, I send the value null to the server:
This is a synchronous connection, so the program pauses here until the server sends the requested file. If the server never responds, the page will hang. (This is exactly why the normal approach is to use asynchronous connections.) Because this is just a test program, however, assume everything will work okay and motor on.
Returning to the basket analogy, the send() method releases the basket, which floats up to the window. In a synchronous connection, we’re assuming the basket is filled and comes down automatically. The next step won’t happen until the basket is back on earth. (But if something goes wrong, the next step might never happen, because the basket will never come back.)
Checking the status
The next line of code won’t happen until the server passes some sort of response back. Any HTTP request is followed by a numeric code. Normally, your browser checks these codes automatically, and you don’t see them. Occasionally, in the course of regular Web browsing, you run across an HTTP error code such as 404 (file not found) or 500 (internal server error). If the server was able to respond to the request, it will pass a status code of 200. (You never see a 200 status code in ordinary browsing, because that means the page request was successful, so you see the page.) The XMLHttpRequest object has a property called status that returns the HTTP status code. If status is 200, then everything went fine and you can proceed. If status is any other value, some type of error occurred.
Fun with HTTP response codes
Just like the post office stamping success/error messages on your envelope, the server sends back status messages with your request. You can see all the possible status codes on the World Wide Web Consortium’s Web site at www.w3.org/Protocols/rfc2616/ rfc2616-sec10.html, but the important ones to get you started are as follows:
200 = OK: This is a success code. Everything went okay, and your response has been returned.
400 = Bad Request: This is a client error code. It means that something went wrong
on the user side. The request was poorly formed and couldn’t be understood.
404 = Not Found: This is a client error code. The page the user requested doesn’t exist or couldn’t be found.
408 = Request Timeout: This is a client error code. The server gave up on waiting for the user’s computer to finish making its request.
500 = Internal Server Error: This is a server error code. It means that the server had an error and couldn’t fill the request.
You’ll want to make sure that the status of the request is successful before you run the code that’s dependant upon the request. You can check for all the various status codes if you want, but for this simple example I’m just ensuring that status is 200:
The request.status property will contain the server’s response. If this value is 2 00, I want to do something with the results. In this case, I simply display the text in an alert box. If the request is anything but 200, I use the statusText property to determine what went wrong and pass that information to the user in an alert.
Using the status property is like looking at the basket after it returns: The container might have the requested data in it, or it might have some sort of note (along the lines of “Sorry, the window was closed. I couldn’t fulfill your request.”). There’s not much point in processing the data if it didn’t return successfully.
All Together Now: Making the Connection Asynchronous
The synchronous AJAX connection described in the previous section is easy to understand, but it has one major drawback: The client’s page completely stops processing while waiting for a response from the server. This might not seem like a big problem at first glance, but it is. If aliens attack the Web server, it won’t make the connection, and the rest of the page will never be activated. The user’s browser will hang indefinitely. In most cases, the user will have to shut down the browser process with Ctl+Alt+Del (or the similar procedure on other OSs). Obviously it would be best to prevent this kind of error.
That’s why most AJAX calls use the asynchronous technique. Here’s the big difference: When you send an asynchronous request, the client keeps on processing the rest of the page. When the request is complete, an event handler processes the event. If the server goes down, the browser will not hang (although the page probably won’t do what you want).
In other words, the readyState property is like looking at the basket’s progress. The basket could be sitting there empty, because you haven’t begun the process. It could be going up to the window, being filled, coming back down, or it could be down and ready to use. You’re only concerned with the last state (ready), because that means the data is ready.
I didn’t include a figure showing the asynchronous version, because to the user, it looks exactly the same as the synchronous connection. Be sure to put this code on your own server and check it out for yourself. (Or of course just look at it on my server.)
The asynchronous version looks exactly the same on the front end, but the code is structured a little differently:
Setting up the program
The general setup of this program is just like the earlier AJAX example. The HTML is a simple button which calls the getAJAX() function.
Building the getAJAX() function
The code in this function is pretty straightforward. Here’s what you do:
1. Create the request object.
The request object is created exactly as it was in the first example.
2. Call the request’s open() method to open a connection.
Note that this time I left the synchronous parameter out, which creates the (default) asynchronous connection.
3. Assign an event handler to catch responses.
You can use event handlers much like the ones in the DOM. In this particular case I’m telling the request object to call a function called checkData whenever the state of the request changes.
You can’t easily send a parameter to a function when you call it using this particular mechanism. That’s why I made request a global variable.
4. Send the request.
As before, the send() method begins the process. Because this is now an asynchronous connection, the rest of the page will continue to process. As soon as the request’s state changes (hopefully because there’s been a successful transfer), the checkData() function will be activated.
Reading the response
Of course, you now need a function to handle the response when it comes back from the server. This works by checking the ready state of the response. Any HTTP request has a ready state, which is a simple integer value describing what state the request is currently in. There are many ready states, but the only one we’re concerned with is 4, because it means the request is finished and ready to process.
Ready, set, readyState!
The readyState property of the request object indicates the ready state of the request. It has five possible values:
0 = Uninitialized: The request object has been created, but the open() method hasn’t been called on.
1 = Loading: The request object has been created, the open() method has been called, but the send() method hasn’t been called.
2 = Loaded: The request object has been created, the open() method has been called, the send() method has been called, but the response isn’t yet available from the server.
3 = Interactive: The request object has been created, the open() method has
been called, the send() method has been called, the response has started trickling back from the server, but not everything has been received yet.
4 = Completed: The request object has been created, the open() method has been called, the send() method has been called, the response has been fully received, and the request object is finished with all its request/response tasks.
Each time the readyState property of the request changes, the function you map to readyStateChanged is called. In a typical AJAX program, this will happen four times per transaction. There’s no point in reading the data until the transaction is completed, which will happen when readyState is equal to 4.
The basic strategy for checking a response is to check the ready state in the aptly-named request.readyState property. If the ready state is 4, check the status code to ensure there’s no error. If ready state is 4 and status is 200, you’re in business, so you can process the form. Here’s the code:
Once again, you can do anything you want with the text you receive. I’m just printing it out, but the data can be incorporated into the page or processed in any way you want.