BUY THIS BOOK
Add to Cart

Print Book $34.99


Add to Cart

PDF $27.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £24.99

What is this?

Looking to Reprint or License this content?


Adding Ajax
Adding Ajax

By Shelley Powers
Book Price: $34.99 USD
£24.99 GBP
PDF Price: $27.99

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Getting Ready to Make a Move to Ajax
Ajax brings a whole new level of feedback and flexibility to web applications. Gone, or at least pushed gently aside, are the days when web page forms produced a result only after being submitted to a server. Gone also are static web pages of frozen HTML (Hypertext Markup Language) that could be read, but were unresponsive to the page reader's actions. Nowadays, web page developers can provide, directly within the page, much of the same functionality that used to require a round trip to the server.
Using Ajax, page components can be collapsed or expanded as required, populated on demand, and feedback to the user can range from a color fade to a system of strategically placed messages. Every element of the page can be used to make web service requests, thus creating more responsive pages and less frustration for the users. The end result is a sharper, tighter application.
Ajax applications can also make use of a host of Ajax-enabled libraries and web services from companies such as Google, Amazon, Adobe, Microsoft, and Yahoo!, as well as independent libraries such as Prototype, Dojo, MochiKit, and jQuery. Existing web services can often be used as they are or easily modified to work with Ajax.
Ajax is unique in that it's a cutting edge concept that's based on rather mature technology. Even some of the more esoteric effects can be created comfortably and with confidence; developers can be secure in the knowledge that any particular effect should work in most, if not all, modern browsers.
Ajax development has some challenging aspects, but it really is an 80-20 technology: 80 percent of the people interested in the technology need only about 20 percent of the capability. Much of the discussion related to Ajax is based on explorations in how far the concept can be pushed. Because of this, it may feel as if you're working with an extremely complex framework. This can be intimidating when you're just starting to consider how you can use Ajax in your sites, but in general, using the Ajax group of technologies is relatively simple with few moving parts. You don't have to spend months reading all that's been written or trying all of the libraries in order to create efficient and interesting Ajax functionality
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Technologies That Are Ajax
Ajax is not built on new technologies, but focuses instead on the refinement and maturing of existing tools and environments. When Jesse James Garrett originally defined Ajax, he listed the associated technologies as:
  • XHTML (Extensible HTML) and CSS (cascading stylesheets) for page layout and presentation
  • XML (Extensible Markup Language) and XSLT (Extensible Stylesheet Language Transformations) for data interchange
  • Document Object Model (DOM) for interactivity
  • A specialized object (XMLHttpRequest) for client-server interaction
  • JavaScript (or JScript) to act as glue
All of these technologies have been around in one form or another for years.
Though most of the emphasis of Ajax is on the web service request, the concept extends beyond simple data access within the page. It's a way of looking at a web page and using existing and new technologies to make it more interactive and responsive. This includes a new way of looking at JavaScript and more sophisticated JavaScript libraries, as well as a fresh new look at dynamic HTML techniques from the 1990s. It's thinking outside the web page box, whether you are using these technologies to create desktop applications, or, as in our case, to add usefulness, sparkle, and spontaneity to existing web pages.
Ajax is the result of a natural progression of client-side functionality. If Garrett hadn't boxed the concept into one name, chances are good that someone else would have; the web development environment was already heading toward a new explosive interest in the combined technologies.
In the earliest days of the Web, all of an application's functionality resided on the server. Netscape introduced client-side scripting with JavaScript, which allowed some client-side interactivity, but web pages remained static. Other browsers that followed, such as Microsoft's Internet Explorer (IE), had their own implementations of scripting, and eventually an effort arose to provide a minimum definition of scripting standards; the result was ECMAScript.
However, it wasn't until the W3C specification work with the DOM and CSS that pages became more dynamic and script could be used to modify, move, hide, create, or remove individual web page elements. At that time, dynamic web page effects were given the term
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Start Clean
Adding Ajax to your site is an opportunity to do that page cleanup you've probably been wanting to do for a long time, but couldn't find the time. Dynamic effects and the use of old and outdated HTML don't go together well, particularly if you're moving objects around, collapsing and expanding columns, or doing in-place editing or help.
In a weblog post at O'Reilly Radar, Nat Torkington wrote the following account of Mark Lucovsky's attempt to implement the same bit of Ajax functionality into two very different web sites; one clean and the other with a large amount of "baggage" (http://radar.oreilly.com/archives/2006/08/the_value_of_web_standards.html:
While at OSCON, Mark Lucovsky of Google sent us a bit of HTML that'd embed a slender map search widget into our conferences web site. It's an easy way for attendees to find restaurants, hotels, parks, bars, etc. near the conference venue. Great idea, and an elegant demo of the Ajax Search API that Mark's been working on.
Mark's next speaking gig was at the Search Engine Strategies (SES) conference, so naturally he reached for the find-me-stuff-around-the-conference example. However, he rapidly ran into the messy HTML that is the SES web site. Whereas it had been a matter of seconds to add the JavaScript into the O'Reilly web page, adding it to the SES page was an ordeal.
That's a vindication of the large amount of hard work that [the] O'Reilly design team put into redesigning pages so they were XHTML and CSS. It's also a vindication of the standards themselves: we sometimes lose track of the bigger picture when we're fighting our way through a twisty maze of namespaces, all alike. The point of the standards is not just to ensure that browsers can display the pages. The standards also ensure the pages form a platform that can be built upon; a hacked-together platform leads to brittle and fragile extensions.
Ajax is heavily dependent on CSS and even more dependent on the DOM. In Ajax applications, we can access individual elements and move them about, create them, or remove them on the fly. Due to the dependency on DOM, we can't just embed script in a page, throw a couple of ID attributes on elements, and expect our effects to work. Ajax is really dependent on the page being clean before we begin.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Converting Tables to CSS Layouts
Page layout problems that trigger an error message are easy to identify. However, some page changes that are required to make a site optimal for Ajax development (and all other uses) don't result in validation errors or accessibility warnings. One of the most common old layout tricks before the advent of CSS was using HTML tables to manage the page contents, regardless of content type. However, HTML tables were meant for tabular data, such as a listing of records from a database. For our purposes, HTML tables are not very adaptable to many Ajax effects. As I'll demonstrate later in this chapter, and also in , updating a dynamic table is trickier than updating a discrete div element. In addition, you can't necessarily move a table row or handle a table cell as a distinct object. HTML tables also drive the semantic web people batty—if you use HTML tables to present all of the information on a web page, the tabular data will not stand out.
Here are some of the issues with using HTML tables for all of your page content:
  • HTML table elements were created specifically for tabular data.
  • HTML tables add an extra layer of complexity when using JavaScript.
  • HTML table elements, such as rows and cells, exist within a framework that makes it awkward to work with an element individually.
  • HTML table elements can't be easily collapsed, moved, or removed from the display without adversely effecting other elements.
  • Some JavaScript-based effects, such as layering, opacity, and other subtle effects can have a negative impact when used with an HTML table.
Based on all this, one of the most common Ajax preparation tasks is converting HTML tables to valid XHTML elements and CSS. Converting the page to CSS is going to make creating Ajax effects easier, and it is going to make site maintenance easier, too. Contrary to expectation, the conversion is actually not as hard as you may think. The next couple of sections explore how to do this, along with a few other conversion efforts. If your web site is already valid and making use of CSS and XHTML, you may want to skip these sections.
HTML tables were designed to display related data, such as a list of stores and locations or the results of a survey. Using them for general page layout is not semantically correct. You'll hear mention of the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Continuing the Conversion: Element by Element
Converting a page to XHTML and CSS is one major change, but there are a host of smaller, easier changes to make before the page validates as XHTML. These changes will make the page elements accessible for script access, which I'll be demonstrating throughout this book.
There are a number of tools that can assist you in cleaning up your web pages and converting them from HTML to XHTML. A popular tool used for this purpose is HTML Tidy, available at http://tidy.sourceforge.net/.
In the early days of the browser, one of the first items people wanted to control was the font. If the entire page were black and white, with font family and size based only on the type of element, our sites would have been too uniform and far too dull (though it would have been easy from a designer's perspective, not to mention fully accessible).
To provide for page customization, a few new HTML elements were introduced as the language developed, including one of the most notorious of all bad elements: blink. This element caused objects (text, images, etc.) to blink on and off. It has become universally hated and is a poster child for separation of page markup and presentation. Luckily, people only toyed briefly with blink, but another element that was widely used (and is still used) is font.
The font element gives designers the ability to specify a font family, size, and color:
<font size="4" color="blue" face="arial">
Some text
</font>
The font element lets us make our text more distinctive, but it does have a drawback: if we want to make a change to the font in our web content, we have to hunt down the use of font in all of our web pages and make the change manually. This can make page maintenance excruciating.
With the advent of CSS, the push is on to remove the use of font (and it has disappeared, more or less, from most pages). If the font element is present in your web sites or applications, you'd be wise to remove it and use a stylesheet setting instead. The following is the CSS setting for the font of a specific element:
#test { font-family: arial; font-size: 4em; color: #0000ff }
Other position- and style-specific elements have been deprecated or conflict with the use of Ajax and should be removed. Among these are:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Dealing with Browser-Specific Quirks
It may seem like every HTML element has predefined style settings. Headers are block-level elements, larger than paragraph text, increasing in size from h6 to h1. Each HTML list item has a default padding value. Paragraphs are block elements with specific margins and padding, fonts, and line spacing.
At first glance, these defaults appear to be relatively the same across browsers, but even minor variations can have significant impact on page design and Ajax effects. Browsers provide their own internal stylesheets that define these values, and though there are some constraints on the styling (such as paragraphs being block-level elements), other settings are based on the browser developers' interpretation of W3C-specified guidelines.
Due to these variations, the amount of spacing between letters, sizes, and so on can differ. Link colors, list icons, and relative header sizes can also differ—significantly at times. This can cause a lot of problems in the page design and can produce unexpected side effects when adding Ajax.
Many effects in Ajax, such as just-in-time (JIT) help (in-page messages that are hidden until needed), placement, color fades, collapsible elements, and so on can only work effectively across browsers when the browsers' various quirks are eliminated.
For example, Safari supports a different line height than Firefox—a quirk that doesn't impact pages containing a great deal of text, but one that can create major problems for an Ajax application that positions text in a small box for a help system. If the text ends up being too large for some browsers and too small for others, the overall system is going to look amateurish or may be hard to read.
One of the worst offenders for invalid CSS has been IE, and some of the workaround hacks have actually been given names, such as Peekaboo Bug, Border Chaos, and the Guillotine Bug; entertaining names, but they're a pain to work with.
Microsoft has made an effort in IE 7 to fix most of the browser's CSS problems; for more information see http://blogs.msdn.com/ie/archive/2006/08/22/712830.aspx. Unfortunately, the browser isn't perfect and still has quirks.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Understanding Your Client Base
The amount of Ajax functionality that you introduce to your site depends on more than just how much you're willing to add and maintain. Even the niftiest technology is going to fall flat if it doesn't provide an added value, or worse, locks your users out of the site. What you will discover, though, is that if you listen to the feedback from your client base, you'll be able to use a little scripting and a few in-page web services to really increase the usability of your site.
The first step in your Ajax makeover is discovering all you can about the people who visit your site so that you plan accordingly. Your best friends in this regard are your site's logs. The following log entry is from one of my sites, and it is a fairly typical example:
5x.x2.x8.xx0 - - [31/Aug/2006:03:09:27 +0000] "GET /wp-content/themes/
bbgun/bbgung.png HTTP/1.1" 200 90338 "http://burningbird.net/wp-content/themes/bbgun/
style.css" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6)
Gecko/20060728 Firefox/1.5.0.6"
This log displays the date, the resource accessed, and a string containing information about the client's operating system and browser. In this case, the browser is Firefox version 1.5.0.6, and the operating system is Windows. Another line from the log is:
x0.xx3.1xx.xx4 - - [31/Aug/2006:03:14:48 +0000] "GET /wp-content/themes/
words/eyesafe.png HTTP/1.1" 404 9058 "http://burningbird.net/" "Mozilla/5.0
(Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1b1) Gecko/20060707 Firefox/2.0b1"
This client is using Firefox 2.0, the first beta release, and the operating system is Mac OS X.
This information will help you determine which user agents (browsers and mobile devices) to support, and will allow you to compensate for the image, image resolution, font support, and tool support differences that exist between operating systems.
You can look at a logfile directly or you can use one of a variety of web tools such as AWStats or Webalizer to analyze the log. You can find these and others just by searching for "logfile analyzer" with your favorite search engine.
Other resources you can use to explore web access are the sites that track browser statistics, such as the W3 Schools at
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Designing a Framework for Your Site
The most important decision facing you now is whether to add Ajax to existing pages or to start from scratch. This book is based on an assumption that web developers begin by introducing Ajax into existing pages and applications rather than scrapping a site and starting anew. In other words, the client-side functionality is adapted, and the server-side component of the site is left as-is, more or less.
The next step in the decision process is to determine the extent of the Ajax modifications. If you're changing a static web page form to one that uses script and XMLHttpRequest to support in-page edits, your use of the new technologies is relatively isolated and will have little impact on the overall site application.
However, if you're adding a site-wide help system, a new dynamic menu, or an in-place search feature, all of your pages will be impacted, and you might want to consider some additional architecture changes, such as splitting out your header and all the script into separate files that can be included in all of your pages. This approach allows you to make sure all of the appropriate JavaScript libraries are included, and allows you to isolate objects like event handlers.
Many of the new content management systems are based on a modular approach that allows you to reuse the sidebar, headers, and footers as much as possible. If your site doesn't use a modular system and the pages are managed manually, you might want to add this to your to-do list for future designs.
Whether you modularize your web pages or not, all of your custom JavaScript should be created in separate files that are included into the appropriate pages. When you change in the code in a script, it will automatically be propagated out to all the pages using that script.
Earlier, I covered the importance of discovering your web page readers' environments, including their browsers and operating systems, and determining whether they have JavaScript enabled. You'll also need to work through an accessibility plan, including criteria used to judge each web page as it's converted to Ajax. This will help to ensure the plan's requirements are met.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Progressive Enhancement Versus Massive Overhaul
As stated earlier, you're one of the luckier Ajax developers because you have a site or an application that already has all the basic functionality, and now you're looking to enhance and improve it through the use of Ajax. This might require some preparation ahead of time, but anything done to make the pages better for Ajax also makes the site better.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: The Ajax Bits
What sets Ajax apart from JavaScript is its use of in-page requests for external data and its ability to return the results without reloading the page. The request can be as simple as loading a new image or stylesheet, or as complex as loading an entire XML document that updates many parts of the page. The data from the web service can be integrated into the page through dynamic scripting—creating a scripting block that consists of a callback function and the returned data. Typically, though, the request is made to a web service through a key object, XMLHttpRequest.
The concept of an object that manages web service requests from script within a web page originated several years ago with Internet Explorer 5.0. The original object was an ActiveX object, and Microsoft continued to support that approach with IE 6.x. Now, though, like the other browsers, Microsoft supports the XMLHttpRequest object.
The XMLHttpRequest object is one of the simpler browser objects to work with: a web service request is created, the request is sent, and a callback function is invoked to process the response. Rather than all of this activity spread across many pages, as is the case with traditional web applications, it's all accomplished within the same web page, without any page reloads.
There are so many acronyms in this business. I use XMLHttpRequest throughout much of the book, but I, and other developers, also sometimes just say XHR to save both time and typing.
For this chapter, I created a simple application, Drinks, where the web page reader selects the name of a drink and the drink recipe is printed out. Though it's fairly trivial, it does serve to demonstrate the server-client communication implicit in web applications without getting too bogged down with extraneous functionality.
The server-side functionality is created using PHP, and for this simplified example, the recipes are stored within the PHP page. The client side contains a form with a list of drink names and a submit button. When the page reader clicks the submit button, the form is sent to the web server, and the associated recipe is retrieved and printed to the page.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Web Application
For this chapter, I created a simple application, Drinks, where the web page reader selects the name of a drink and the drink recipe is printed out. Though it's fairly trivial, it does serve to demonstrate the server-client communication implicit in web applications without getting too bogged down with extraneous functionality.
The server-side functionality is created using PHP, and for this simplified example, the recipes are stored within the PHP page. The client side contains a form with a list of drink names and a submit button. When the page reader clicks the submit button, the form is sent to the web server, and the associated recipe is retrieved and printed to the page.
Before getting into the Ajax functionality, let's look at an application as it might be constructed without any use of JavaScript.
For a simple application, it's not unusual to combine the client and server within the same file, with the server-side functionality printing out pertinent client-side elements. The only tedious part of creating this application is ensuring the selected drink reappears in the list as the selection; otherwise, the first drink in the list will be displayed, making it out of sync with the printed recipe. shows the complete application, with one page containing both client and server components.
Example 2-1. Complete one-page Drinks application
<?php

//If no search string is passed, then we can't search
$drink = $_REQUEST['drink'];
if (empty($drink)) {
   $drink = 'TEA';
} else  {
    //Remove whitespace from beginning & end of passed search.
    $search = trim($drink);

    switch($search) {
      case "TEA" :
         $result = "<h3>Hot Tea</h3><p>Boil water. " .
                   "Pour over tea leaves. Steep five minutes. " .
                   "Strain and serve</p>";
         break;
      case "APPLETINI" :
         $result = "<h3>Appletini</h3><p>Mix 1 oz vodka and 1/2 oz Sour
Apple Pucker or " .
                   "apple schnapps in a glass filled with ice. Strain into
martini glass. " .
                   "Garnish with an apple slice or raisin.</p>";
         break;
      case "NONCHAMP" :
         $result = "<h3>Non-Alcoholic Champagne</h3><p>Mix 32 ounces club soda" .
                   " with 12 ounces frozen white grape juice concentrate.</p>";
         break;
      case "SWMPMARGARITA" :
         $result = "<h3>Swamp Margarita</h3>" .
                   "<p>Mix 1 1/2 ounce good quality tequila, 3/4 ounce Cointreau, " .
                   "3/4 ounce Grand Marnier, 1/2 ounce lime juice, and 2
ounces sour mix.
                Chill an hour. " .
                   "Fill bottom of tall glass with several green olives and
a few drops                  olive juice. " .
                   "Pour margarita over the olives and let sit for ten minutes. " .
                   "Strain and serve with a few olives stuffed with pimento on a
                toothpick.</p>";
         break;

      case "LEMON" :
         $result = "<h3>Lemon Drop</h3><p>Mix 1 ounce lemon vodka " .
                   "with 1 ounce lemon juice and 1 teaspoon sugar. Shake with ice, " .
                   "strain and serve.</p>";
         break;
      default :
         $result = "No recipes found";
         break;
      }
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Drinks</title>
<link rel="stylesheet" href="drink.css" type="text/css" media="screen" />
</head>
<body>
 <body>
    <h1>Drinks</h1>

    <div id="drinkblock">
      <form action="" id="myform" method="get">
        <fieldset legend="drinks">
          <label for="drink">Select drink:</label> <select
          name="drink" id="drink">
            <option value="TEA" <?php if ($drink == 'TEA')
                                           printf('selected="selected"'); ?>>
              Hot Tea
            </option>

            <option
            value="APPLETINI" <?php if ($drink == 'APPLETINI')
                                            printf('selected="selected"'); ?>>
              Appletini
            </option>

            <option value="NONCHAMP" <?php if ($drink == 'NONCHAMP')
                                           printf('selected="selected"'); ?>>
              Non-alcoholic Champagne
            </option>

            <option
            value="SWMPMARGARITA" <?php if ($drink == 'SWMPMARGARITA')
                                           printf('selected="selected"'); ?>>
              Swamp Margarita
            </option>

            <option
            value="LEMON" <?php if ($drink == 'LEMON') printf
('selected="selected"'); ?>>
              Lemon Drop

            </option>
          </select> <input type="submit" value="Get Recipe" />
        </fieldset>
      </form>
    </div>

    <div id="drinkblock">
      <?php echo $result; ?>
    </div>
</body>
</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Preparing the Object for Use
One of the first decisions to make when creating the XMLHttpRequest object is whether your application will support IE 6.x. In IE 7, and in newer versions of the other browsers (Opera, Firefox, Safari, Netscape, and so on), the server request object is simply XMLHttpRequest, and the browsers all support similar behavior. However, IE 6.x still supports the older Microsoft ActiveX object. Since older Windows operating systems, such as the very popular Windows 2000, cannot support the newer IE 7, you have to decide whether you will provide support for people using Windows 2000 (or those using Windows XP who have not upgraded their browsers).
This is where you return to your logs and see how many people access your site using IE 6.x. If you have even five percent using IE 6.x, you're most likely going to want to support this older browser. Fortunately, the additional code doesn't take a lot of extra space.
The next issue when working with the ActiveX object is determining which object ID to set in the function call to create the object. Unfortunately, Microsoft was not consistent with the name of this object by operating system, and we have variations such as MSXML2.XMLHttp, MSXML2.XMLHttp.3.0, and MSXML2.XMLHttp.4.0. Most Ajax libraries focus on two of these, the older ID, Microsoft.XMLHttp, and the more common of the newer ones, MSXML2.XMLHttp.
Since most browsers that access the site will have access to the now-standard XMLHttpRequest object, it's most efficient to test for its presence first. If this test fails, test for the two Microsoft-specific objects. Since we'll be making a great deal of use of XHR, packaging it into a reusable function simplifies its inclusion in a library. shows the code for a typical XMLHttpRequest object function.
Example 2-4. Typical XMLHttpRequest object creation function
function getXmlHttpRequest(  ) {

   var xmlHttpObj;
   if (window.XMLHttpRequest) {
      xmlHttpObj = new XMLHttpRequest(  );
   } else {
      try
         {
            xmlHttpObj = new ActiveXObject("Msxml2.XMLHTTP");
         }
         catch (e)
         {
            try
            {
               xmlHttpObj = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e)
            {
               xmlHttpObj = false;
            }
         }
    }
   return xmlHttpObj;
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Preparing and Sending a Request
Preparing and sending a web service request is probably one of the easiest aspects of Ajax. A few decisions about parameters, a couple of function calls, and you're done.
When preparing a request, the first decision to make is which HTTP verb to use with the request. When adding Ajax to a site, chances are you'll be working with existing web services, and you'll have to build your JavaScript client interface accordingly. However, if you're also modifying the web service interface, it'll be worth your time to review the HTTP methods that can be used between the client and the web service in order to maximize the efficiency and security of the application.
I'm assuming you've probably worked with web applications before and are familiar with the GET and POST HTTP requests. XMLHttpRequest supports both of these, and a variety of other verbs. Many of those verbs don't make a lot of sense for Ajax applications, but there are four in particular that are well suited:
GET
Used to retrieve information from the web server, parameters attached to the URL, and the URL exposed in the request.
POST
Used to send information to the web server. Data is passed to the server via the function parameter.
DELETE
Used to send a request to delete a specific object. Data is passed to the server via the function parameter.
PUT
Used to send an update to the web server. Data is passed to the server via the function parameter.
The first two, GET and POST, are commonly used in web applications, but the latter two may not be familiar to you. All four of these HTTP methods are supported by web services that are considered RESTful—applications based on Representational State Transfer (REST), a recommended approach to providing web services.
The need for four separate methods isn't just one of semantics. A GET request is one that shouldn't have a side effect—it's used to retrieve information only. Google once came up with beta functionality, the Google Web Accelerator, which promised more efficient applications by automatically prefetching all GETs within a page and caching the data. Unfortunately, some of the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Processing the Ajax Response
To process the Ajax response and display the recipe, we must make two changes in our existing application. The first is embedding the request response directly in the page and the second is modifying the page layout to provide a place for the response.
In the last example in the previous section, the getRecipe function makes its request to the same drink.php web application used with the earlier, traditional web application, and the existing server-side application is designed to create a web page rather than to return data. This functionality is apparent when reviewing the data returned in the XHR object's responseText property. Both the page formatting and the data are returned, but an Ajax application needs only the data.
We must therefore change the server program from a web application to a web service that will support machine-to-machine interaction over a network. Specifically, we want the web service to return the data using a predetermined web service protocol (in this case, REST), rather than the simpler approach of setting application variables. Since the same functionality still has to be available to the nonscripted application, whatever approach we use must work whether the application is used within a traditional web application or invoked as a web service.
For our purposes, the change is simple: add echo $result at the end of the recipe.php application to print the result out. With this one small change, the application works whether embedded in a PHP block in a web page or called as a REST service.
The Ajax request in the getDrink function is modified to call the recipe.php web service:
// get recipe using Ajax
function getRecipe(evnt) {
   if (!xmlhttp) xmlhttp = aaGetXmlHttpRequest(  );
   if (!xmlhttp) return;
   var drink = encodeURIComponent(document.getElementById('drink').value);
   var qry = "drink=" + drink;
   var url = 'recipe.php?' + qry;
   xmlhttp.open('GET', url, true);
   xmlhttp.onreadystatechange = printRecipe;
   xmlhttp.send(null);
   if (evnt && evnt.preventDefault(  ))
     evnt.preventDefault(  );
   return false;
}
When running the application using the modified
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Endpoints, the JavaScript Sandbox, and Widgets
The use of XMLHttpRequest has one significant limitation: the same-domain restriction. A request through this object can be made only to the same domain from which the page was first requested, a key part of the JavaScript security sandbox (you can play only in your own "sandbox," thus avoiding the chaos that could result if code could connect anywhere). Among the reasons for this restriction is to ensure that the web page that contains the XHR request can't be used by a malicious site to access resources on a company intranet living behind a firewall. There are ways around this restriction, such as through signed script or setting security parameters in the browsers, but these options are being phased out as new browser versions are released.
Cross-domain access restrictions aren't normally a problem in a web application. After all, most of the web services are accessed from the same domain. In addition, if data is pulled from another domain, we can create proxies—server-side applications that access the data and then pass it on to the client—to assist us.
There is one circumstance, though, where we can't depend on the server to manage the data access of external data for us: the use of widgets.
Widgets have a history on the desktop and other environments, but they are fairly new in web development. Widgets are small objects, usually embedded in a sidebar, that provide a simplified application or access to data, such as getting weather conditions from a weather site or tag data from del.icio.us. provides a screenshot of a weather.com widget created using the Rico Ajax library.
Sometimes the JavaScript file providing the functionality is hosted completely on the remote server, which means there's no problem with cross-domain access—both JavaScript and data reside on the same server. This is how Google Maps works. However, sometimes the widget requires local JavaScript but remote data and web services. What's a developer to do?
This is where JSON really proves its power. JSON is more than just a format and a structure—it's a doorway. You can create a script object within one document and within one domain, set its
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
That Security Stuff
I imagine by this point you've torn great furrows into your scalp by the number of ways I've demonstrated of opening your web page to the worst sort of damage.
In particular, working around the security restrictions in the browser by using dynamic scripting with a call to an external service, which you do not control, means that your application is open to potential security violations.
Just such a security violation was discovered in Google's popular Gmail application in 2006. One service associated with the application would return a list of contacts for a given individual. This functionality was created as a JSON web service, and as long as the user was logged in, a call to this service returned the user's list of contacts. However, calls of this nature could be placed from any location, and the web service didn't check to ensure that they were from a "safe" domain. As such, a web site could easily make the call to the JSON service and then send the contacts list using an Ajax call to another service, or even an XHR request on its own site, thus opening up the contacts for yet more spam email.
Creating a JSON or even an XML service endpoint for sensitive data makes no sense, and neither does making a call on an endpoint service from a nontrusted site. Keeping these security issues in mind is important, though, because these kinds of services are important for implementing widgets.
If you read through the Ajax security restrictions at the Open Web Security Project (OWASP) wiki at www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines, you might think that there is no use of Ajax that's safe, and that's true—there is no safe use of Ajax. There are only safeguards you can put in place.
As mentioned earlier, Douglas Crockford provides a JSON parser at http://www.json.org/js.html that you can incorporate into your application rather than using eval. His parser ensures that there's no hidden scripting embedded in the object that can bite you. Using XML within the DOMParser is actually a safer bet for dynamic scripting. None of these options is going to be completely secure unless you either control the endpoint or web service, or you have a high degree of confidence and trust in a service you're using externally.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
A First Look at Performance
Throughout this book, especially in the later chapters, we'll look at some performance issues and tweaks associated with Ajax applications. I did want to mention one first, though, and that is HTTP's two-connection limitation that most browsers put on pages pulled from a specific domain.
When you open a web page and download material from the Web, only two parallel connections to the same domain are opened at any one time. This means that if you're downloading images, JavaScript files, and other material embedded into the page, the download will queue based on the number of connections. This becomes a more acute problem when you're using Ajax calls in your script, all of which could be held up waiting on connections to open from processing other calls or downloading other material.
One way to improve performance is to consider offloading some of the incidental material, such as images, to another domain so that you free up connections from the current domain specifically for Ajax calls. The other domain can be on the same server, as the connection limitation built into browsers is based on domain name, not IP address. So you can create CNAME subdomains such as images.sitename.com, js.sitename.com, or database.sitename.com, effectively allowing your browser to create more than two concurrent connections, thus increasing the speed with which the page and the Ajax requests are made.
Using multiple subdomains to increase the number of parallel HTTP requests can frustrate dial-up modem users who have only limited bandwidth. Still, as broadband use increases significantly, this becomes less of an issue. You need to be aware of who your customers are and plan accordingly.
Another performance enhancement could be to compress your JavaScript so that the file sizes are smaller. However, this can obscure your JavaScript code, making it more difficult to read and reuse, if this is of interest to you. You can easily find and try out several JavaScript compression tools by searching for "javascript compression."
Rather than using small JavaScript files, each of which has to be loaded individually, you might consider packaging JavaScript files that are used together most frequently into one file. However, balance this with loading code that might not be used in a specific application. It's better to have smaller files than to load unnecessary code.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
One Last Word on Asynchronous Versus Synchronous
Though the "A" in Ajax stands for "asynchronous," the XMLHttpRequest object doesn't have to be used asynchronously. A synchronous request is one where the browser is locked up waiting for a response. An example of this behavior would be the following:
var state = document.forms[0].elements[0].value;
var url = 'ajax.php?state=' + state;
xmlhttp.open('GET', url, false);
xmlhttp.send(null);
alert(xmlhttp.getAllResponseHeaders(  ));
In this code, a string representing a state is accessed from a form field and used to build an HTTP GET request on the web service, ajax.php. The third parameter in the open method is false, which means the request is made synchronously. The request is sent without any parameters (the null value), and immediately after the send, an alert message box is opened and the response headers are printed out.
Now, if the service is quick, the response is almost immediate. However, if the service is slow, no other page activity can happen until the request finishes. The effect is little different from when you first open a web page and you can't typically do anything with the page until it's finished loading.
Most Ajax applications use the XMLHttpRequest object asynchronously. In this case, an asynchronous request is sent, but the browser continues processing the code following the request rather than waiting for a response from the server. To process the response when it is sent, a function is assigned to the onreadystatechange property of the XMLHttpRequest object. In the function, then, the ready state and request status are tested, and when the ready state is equal to 4, the request is finished.
The asynchronous version of the above code could be like the following:
   // get recipe using Ajax
function getRecipe(evnt) {
   if (!xmlhttp) xmlhttp = aaGetXmlHttpRequest(  );
   if (!xmlhttp) return;
   var drink = encodeURIComponent(document.getElementById('drink').value);
   var qry = "drink=" + drink;
   var url = 'recipe.php?' + qry;
   xmlhttp.open('GET', url, true);
   xmlhttp.onreadystatechange = printRecipe;
   xmlhttp.send(null);
   if (evnt && evnt.preventDefault(  ))
     evnt.preventDefault(  );
   return false;
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Ajax Tools and Terminology
JavaScript has undergone a metamorphosis since its earliest beginnings. With newer versions, in addition to more complex and rich JavaScript libraries, it may seem as if you're using an entirely new language—full of strange and odd operators and functions. The popularity of Ajax has generated interest in more formal approaches to JavaScript development and this has led to the creation of new concepts and associated terminology and coding syntax. The positive effect of such effort is more robust and richer applications. The downside, however, is having to learn the lingo of the Ajax development community, as well as having to spend a considerable amount of time with the libraries before you can incorporate them into your own applications.
This chapter looks at some of the more popular Ajax libraries, both as an introduction to the library and as a way of introducing some of the more commonly occurring Ajax concepts and terminologies. In addition, it also covers some of the more common "gotchas" associated with using the libraries, many of which were designed more for developing a new form of desktop application than adding Ajax to existing web sites and applications.
Most Ajax libraries provide a basic set of functionality, such as methods that can access any web page object without having to use the DOM methods. Most libraries also provide the ability to communicate with a web service. The major difference between library types is whether they contain functions to do specific tasks or contain frameworks to provide infrastructure support on which other libraries are built.
Libraries can also be layered, one building on another, or mashed together, which provides its own challenges. For example, if two libraries assign a different function to a window onload event handler, they must be set up correctly or one library will overwrite the other and the setup routine may not be properly executed. These library conflicts can be the worst to debug, too, because if you're not familiar with either library's code, you're also not familiar with how they can compete with each other.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Prototype
Probably the best known of the Ajax libraries, and one of the most used, is Prototype. It's actually a fairly small and self-contained library. It loads quickly and forms a core on which other libraries are built, including script.aculo.us and Rico, both of which are discussed later.
Prototype is less a framework than a scripting language equalizer, providing a set of objects that cut through some of the complexity of accessing and working with page elements across different browsers. It was created and is still maintained by Sam Stephenson, and the latest version (Prototype 1.5 at the time of this writing) can be downloaded from http://prototypejs.org. This site also has documentation for the library's API, as well as articles and tutorials on its use.
Adding Prototype to your projects is simple; you can include it in an application using the following:
<script type="text/javascript" src="/path/to/prototype.js"></script>
One of the defining characteristics of Prototype is its incorporation of several Ruby language-like functions and behavior. Ruby is a simple-to-use language, but it's also cryptic, and Prototype's use of these functions in JavaScript can cause confusion, particularly if you're not familiar with Prototype's unique components. Key among these components are functions known as the dollar and dollar F.
The dollar function, $( ), returns a reference to the element whose name is passed into the function:
var elem = $('some_element');
The element is identified using the id attribute:
<div id="some_element">
...
</div>
This is equivalent to using the following DOM method call:
var elem = document.getElementById('some_element');
In addition to returning the element, the $( ) function also appends several Prototype-specific properties.
The function $F( ) returns the value of a form field, given its identifier:
var value = $F('form_field');
...
<input type="text" id="form_field" />
This is equivalent to:
var value = document.getElementById('form_field').value
Prototype doesn't provide new functionality as much as it repackages commonly needed functionality into handily accessible units. Using
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
script.aculo.us
The script.aculo.us library is based on Prototype, extending the functionality with higher-level features and providing a framework in which to create more sophisticated Ajax effects. It got its name using a variation of domain naming of the social bookmarking site, del.icio.us, though there is no association between the two. It can be downloaded from http://script.aculo.us. The version used in the examples in this chapter is 1.7.0.
To use script.aculo.us, you'll need to include both the Prototype and script.aculo.us JavaScript files. You don't need to download Prototype, though, as it's bundled with the script.aculo.us download package:
<script src="javascripts/prototype.js" type="text/javascript"></script>
<script src="javascripts/scriptaculous.js" type="text/javascript"></script>
The script.aculo.us library consists of different effects, each in its own separate file. If you're using only one script.aculo.us effect, you can specify it as part of the URL of the script file within the script src attribute:
<script src="scriptaculous.js?load=effects" type="text/javascript></script>
This script tag loads the main script.aculo.us.js library, which is primarily nothing more than a loader program. The URL in the tag triggers the loader to also load the effects.js file. How this occurs is that the loader gets the script URL, parses out the library (or libraries) to load, and then calls a function that uses document.writeln to "add" the libraries. If no library is named, the script.aculo.us loader pulls in all of the libraries.
Adding JavaScript using document.write or the DOM to insert new script elements is also called On-Demand JavaScript, a known Ajax pattern, as defined in Michael Mahemoff's book, Ajax Design Patterns (O'Reilly).
At the time of this writing, the different libraries that could be included are:
  • builder
  • effects
  • dragdrop
  • controls
  • slider
There are dependencies between libraries, which are detailed in the script.aculo.us documentation.
Using document.writeln or document.write to add script tags to include new JavaScript libraries is a handy way to dynamically "load" libraries as they're needed. Unfortunately, this doesn't work if you serve the document up as XHTML, since dynamically adding what could be crufty markup into a properly formatted XHTML document isn't allowed. In fact, script.aculo.us doesn't work in a properly formatted XHTML document.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Rico
Rico is another Ajax library built on Prototype. Like script.aculo.us, Rico includes several packaged effects, including fade, and like all Ajax frameworks, it includes functions to simplify Ajax service calls. Rico can be downloaded from http://openrico.org. Rico also has a nicely implemented round corner effect that can be added to page elements. However, whether you want the overhead for this is debatable. I have a feeling that rounded corners will begin to lose some of their popularity—at least until they're available in most browsers as CSS.
Rico has an interesting LiveGrid, which connects to a data source through an Ajax request and serves up new data as the page reader scrolls down the data table. This effect is also known as Ajax pagination or live scrolling.
Ajax pagination is a mixed bag. When implemented properly, it's a terrific way to pull in external data without your readers even being aware that it is happening. Google uses this approach when it brings in a seemingly never-ending map with the Google Maps web services.
However, done incorrectly, pagination can be a nightmare. Recently, Yahoo! reworked its Yahoo! TV web site to include several Ajax effects, including Ajax pagination. The performance and "busyness" of the site due to the pagination change in particular raised howls of protest from current users. The pagination added an overall burden to page load times, and the effect wasn't implemented with any form of caching to create a smooth "endless scrolling" effect.
Rico provides encapsulated behavior called the LiveGrid, which supports pagination by working with a live backend database to query the data as needed. The Rico developers provide a demonstration of a LiveGrid Yahoo! search at http://openrico.org/rico/demos.page.
Like script.aculo.us, Rico provides demos of functionality but not a lot of formal documentation. The typical approach in learning how to use any of these libraries is to find an example and take a look at the source. One of my favorite examples is the Rico Weather Watch (http://openrico.org/demos/weather_demo), which is shown in .
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Dojo
Dojo is an open source effort managed by the Dojo Foundation. Unlike the other libraries, which are maintained by individuals or small groups, the Dojo effort actively encourages additions to the Ajax library from various sources.
The basic Dojo Toolkit is actually quite large and provides a rather complex "pluggable" framework, which allows for the development of Dojo-style widgets—external extensions that don't impact the underlying code. You can download the toolkit at http://dojotoolkit.org.
The released version of the library provides both human-readable source and JavaScript source that has had all extraneous whitespace removed (which makes the library smaller and more or less impossible to read).
There are several tools and sites that provide JavaScript compression. A good place to start is to simply search for "JavaScript compression" in your favorite search engine.
Dojo has extensive documentation, accessible at http://manual.dojotoolkit.org/index.html. The mechanics of widget-building for Dojo are beyond this book, and I'll refer you to a tutorial on the subject at http://openrico.org/demos/weather_demo.
Like other Ajax libraries, Dojo originally had little documentation. Considering how complex it was, this was more than a small handicap in using the toolkit. Luckily, the project did start a wiki (a site where more than one person can edit the contents) for documentation, though like all wikis, the coverage can be sketchy. Another place to find documentation is at http://dojotoolkit.org/docs.
Dojo provides its own cross-browser and JavaScript language functionality, but unlike Prototype, it also provides a framework for developing extensions and bootstrapping the Dojo environment. According to the Dojo site's documentation, Dojo consists of several modules, including the following (just a sampling):
dojo
The Dojo bootstrap, which loads whatever modules are being used
dojo.lang
JavaScript utilities
dojo.string
JavaScript string utilities
dojo.dom
DOM manipulation routines
dojo.style
CSS manipulation routines
dojo.html
HTML specifications
Dictionary
A dictionary/hash object
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Other Libraries
There are a growing number of Ajax libraries available to use, from the simple to the complex. We'll briefly examine a few others to give you an idea of the wealth of useful functionality already created for your use.
A handy list of many