Section 20.3. Ajax and Dynamic Scripting


20.3. Ajax and Dynamic Scripting

The term Ajax describes an architecture for web applications that prominently features scripted HTTP and the XMLHttpRequest object. (Indeed, for many, the XMLHttpRequest object and Ajax are virtually synonymous.) Ajax is an (uncapitalized) acronym for Asynchronous JavaScript and XML.[*] The term was coined by Jesse James Garrett and first appeared in his February 2005 essay "Ajax: A New Approach to Web Applications." You can find this seminal essay at http://www.adaptivepath.com/publications/essays/archives/000385.php.

[*] The Ajax architecture is compelling, and having a simple name for it has served to catalyze a revolution in web application design. It turns out, however, that the acronym is not particularly descriptive of the technologies that compose Ajax applications. All client-side JavaScript uses event handlers and is therefore asynchronous. Also, the use of XML in Ajax-style applications is often convenient, but always optional. The defining characteristic of Ajax applications is their use of scripted HTTP, but this characteristic does not appear in the acronym.

The XMLHttpRequest object upon which Ajax is based was available in web browsers from Microsoft and Netscape/Mozilla for about four years before Garrett's essay was published but had never received much attention.[] In 2004, that changed when Google released its Gmail web mail application using XMLHttpRequest. The combination of this high-profile and professionally executed example along with Garretts early 2005 essay opened the floodgates to a torrent of interest in Ajax.

[] I regret that I did not document XMLHttpRequest in the fourth edition of this book. That edition of the book was heavily standards-based, and XMLHttpRequest was omitted because it has never been endorsed by any standards-setting body. Had I recognized the power of scripting HTTP at the time, I would have broken my rules and included it anyway.

The key feature of an Ajax application is that it uses scripted HTTP to communicate with a web server without causing pages to reload. Since the amount of data exchanged is often small, and since the browser does not have to parse and render a document (and its associated stylesheets and scripts), response time is greatly improved, and the result is web applications that feel more like traditional desktop applications.

An optional feature of Ajax applications is the use of XML as the encoding for data interchange between client and server. Chapter 21 shows how to use client-side JavaScript to manipulate XML data, including doing XPath queries and XSL transformations of XML into HTML. Some Ajax applications use XSLT to separate content (XML data) from presentation (HTML formatting, captured as an XSL stylesheet). This approach has the additional benefits of reducing the amount of data to transfer from server to client and of offloading the transformation from the server to the client.

It is possible to formalize Ajax into an RPC mechanism.[*] In this formulation, web developers use low-level Ajax libraries on both the client and server side to facilitate higher-level communication between client and server. This chapter does not describe any such RPC-over-Ajax libraries because it focuses instead on the lower-level technology that makes Ajax work.

[*] RPC stands for Remote Procedure Call and describes a strategy used in distributed computing to simplify client/server communication.

Ajax is a young application architecture, and Garrett's essay describing it concludes with a call to action that is worth reproducing here:

The biggest challenges in creating Ajax applications are not technical. The core Ajax technologies are mature, stable, and well understood. Instead, the challenges are for the designers of these applications: to forget what we think we know about the limitations of the Web, and begin to imagine a wider, richer range of possibilities.

It's going to be fun.

20.1.11. Ajax Example

The XMLHttpRequest examples that have appeared so far in this chapter have been utility functions that demonstrate how to use the XMLHttpRequest object. They have not demonstrated why you might want to use the object or illustrated what you can accomplish with it. As the quote from Garrett illustrates, the Ajax architecture opens up many possibilities that have only begun to be explored. The next example is a simple one, but it captures some of the flavor and utility of the Ajax architecture.

Example 20-8 is an unobtrusive script that registers event handlers on links in the document so that they display tool tips when the user hovers the mouse over them. For links that refer back to the same server from which the document was loaded, the script uses XMLHttpRequest to issue an HTTP HEAD request. From the returned headers, it extracts the content type, size, and modification date of the linked document and displays this information in the tool tip (see Figure 20-1). Thus, the tool tip provides a kind of a preview of the link's destination and can help a user decide whether to click on it or not.

Figure 20-1. An Ajax tool tip


The code relies on the Tooltip class developed in Example 16-4 (however, it does not require the extension to that class developed in Example 17-3). It also uses the Geometry module of Example 14-2 and the HTTP.getHeaders() utility function developed in Example 20-4. The code involves several layers of asynchronicity, in the form of an onload event handler, an onmouseover event handler, a timer, and a callback function for the XMLHttpRequest object. Therefore, it ends up with deeply nested functions.

Example 20-8. Ajax tool tips

 /**  * linkdetails.js  *  * This unobtrusive JavaScript module adds event handlers to links in a  * document so that they display tool tips when the mouse hovers over them for  * half a second. If the link points to a document on the same server as  * the source document, the tool tip includes type, size, and date  * information obtained with an XMLHttpRequest HEAD request.  *  * This module requires the Tooltip.js, HTTP.js, and Geometry.js modules  */ (function() {  // Anonymous function to hold all our symbols     // Create the tool tip object we'll use     var tooltip = new Tooltip();     // Arrange to have the init() function called on document load     if (window.addEventListener) window.addEventListener("load", init, false);     else if (window.attachEvent) window.attachEvent("onload", init);     // To be called when the document loads     function init() {         var links = document.getElementsByTagName('a');        // Loop through all the links, adding event handlers to them         for(var i = 0; i < links.length; i++)             if (links[i].href) addTooltipToLink(links[i]);     }     // This is the function that adds event handlers     function addTooltipToLink(link) {         // Add event handlers         if (link.addEventListener) {  // Standard technique             link.addEventListener("mouseover", mouseover, false);             link.addEventListener("mouseout", mouseout, false);         }         else if (link.attachEvent) {  // IE-specific technique             link.attachEvent("onmouseover", mouseover);             link.attachEvent("onmouseout", mouseout);         }         var timer; // Used with setTimeout/clearTimeout         function mouseover(event) {             var e = event || window.event;             // Get mouse position, convert to document coordinates, add offset             var x = e.clientX + Geometry.getHorizontalScroll() + 25;             var y = e.clientY + Geometry.getVerticalScroll() + 15;             // If a tool tip is pending, cancel it             if (timer) window.clearTimeout(timer);             // Schedule a tool tip to appear in half a second             timer = window.setTimeout(showTooltip, 500);             function showTooltip() {                 // If it is an HTTP link, and if it is from the same host                 // as this script is, we can use XMLHttpRequest                 // to get more information about it.                 if (link.protocol == "http:" && link.host == location.host) {                     // Make an XMLHttpRequest for the headers of the link                     HTTP.getHeaders(link.href, function(headers) {                         // Use the headers to build a string of text                         var tip = "URL: " + link.href + "<br>" +                             "Type: " + headers["Content-Type"] + "<br>" +                             "Size: " + headers["Content-Length"] + "<br>" +                             "Date: " + headers["Last-Modified"];                         // And display it as a tool tip                         tooltip.show(tip, x, y);                     });                 }                 else {                     // Otherwise, if it is an off-site link, the                     // tool tip is just the URL of the link                     tooltip.show("URL: " + link.href, x, y);                 }             }         }         function mouseout(e) {             // When the mouse leaves a link, clear any             // pending tool tips or hide it if it is shown             if (timer) window.clearTimeout(timer);             timer = null;             tooltip.hide();         }     } })(); 

20.1.12. Single-Page Applications

A single-page application is exactly what its name implies: a JavaScript-driven web application that requires only a single page load. Some single-page applications never need to talk to the server after loading. Examples are DHTML games in which all interaction with the user simply results in scripted modifications to the loaded document.

The XMLHttpRequest object and Ajax architecture open up many possibilities, however. Web applications can use these techniques to exchange data with the server and still be single-page applications. A web application designed along these lines might consist a small amount of JavaScript bootstrapping code and a simple HTML "splash screen" to be displayed while the application was initializing. Once the splash screen was displayed, the bootstrap code could use an XMLHttpRequest object to download the actual JavaScript code for the application, which would then be executed with the eval() method. The JavaScript code would then take charge, loading data as needed with XMLHttpRequest and using the DOM to render that data as DHTML to be displayed to the user.

20.1.13. Remote Scripting

The term remote scripting predates the term Ajax by more than four years and is simply a less catchy name for the same basic idea: using scripted HTTP to create a tighter integration (and improved response time) between client and server. One widely read 2002 article from Apple, for example, explains how to use an <iframe> tag to make scripted HTTP requests to a web server (see http://developer.apple.com/internet/webcontent/iframe.html). This article goes on to point out that if the web server sends back an HTML file with <script> tags in it, the JavaScript code those tags contain is executed by the browser and can invoke methods defined in the window that contains that <iframe>. In this way, the server can send very direct commands to its client in the form of JavaScript statements.

20.1.14. Ajax Cautions

Like any architecture, Ajax has some pitfalls. This section describes three issues to be aware of when designing Ajax applications.

First is the issue of visual feedback. When a user clicks on a traditional hyperlink, the web browser provides feedback to indicate that the content of the link is being fetched. This feedback appears even before that content is available for display so that the user knows the browser is working on her request. However, when an HTTP request is issued via XMLHttpRequest, the browser does not provide any feedback. Even on a broadband connection, network latencies often cause noticeable delays between issuing an HTTP request and receiving the response. It is valuable, therefore, for Ajax-based applications to provide some kind of visual feedback (such as a simple DHTML animation: see Chapter 16) while waiting for a response to an XMLHttpRequest.

Note that Example 20-8 does not heed this advice to provide visual feedback. This is because in this example, the user does not take any active action to initiate the HTTP request. Instead, the request is initiated whenever the user (passively) hovers the mouse over a link. The user does not explicitly ask the application to perform an action and therefore does not expect feedback.

The second issue has to do with URLs. Traditional web applications transition from one state to the next by loading new pages, and each page has a unique URL. The same is not true with Ajax applications: when an Ajax application uses HTTP scripting to download and display new content, the URL in the location bar does not change. Users may want to bookmark a particular state within the application and will find that they cannot do this with the browser's bookmarking facility. They can't even cut and paste a URL from the browser's location bar.

This issue, and its solution, are well illustrated by the Google Maps application (http://local.google.com). As you zoom and scroll the map, lots of data is transferred back and forth between client and server, but the URL displayed in the browser does not change at all. Google solves the bookmarking problem by including a "link to this page" link on every page. Clicking the link generates a URL for the currently displayed map and reloads the page using that URL. Once this reload is done, the current state of the map can be bookmarked, the link emailed to a friend, and so on. The lesson for Ajax application developers is that it remains important to be able to encapsulate application state in a URL and that these URLs should be available to users when necessary.

A third issue that is often mentioned in discussions of Ajax has to do with the Back button. By taking control of HTTP away from the browser itself, scripts that use XMLHttpRequest bypass the browser history mechanism. Users are accustomed to navigating the web with Back and Forward buttons. If an Ajax application uses HTTP scripting to display substantial chunks of new content, users may to try to use these buttons to navigate within the application. When they do, they'll be frustrated to find that the Back button backs their browser all the way out of the application rather than just reverting to the most recently displayed "chunk."

Attempts have been made to solve the Back button problem by tricking the browser into inserting URLs into its history. These techniques are typically mired in browser-specific code, however, and are not really satisfactory. And even when they can be made to work, they subvert the Ajax paradigm and encourage the user to navigate with page reloads instead of scripted HTTP.

In my opinion, the Back button problem is not as serious a problem as it is made out to be, and it can be minimized with thoughtful web design. Application elements that look like hyperlinks should behave like hyperlinks and should do real page reloads. This makes them subject to the browser's history mechanism, as the user expects. Conversely, application elements that perform scripted HTTP, which is not subject to the browser's history mechanism, should not look like hyperlinks. Consider the Google Maps application again. When the user clicks and drags to scroll a map, he does not expect the Back button to undo his scrolling action, any more than he expects the Back button to undo the effect of using the browser's scrollbar to scroll within a web page.

Ajax applications should be careful not to use words like "forward" and "back" in their own intra-application navigation controls. If an application uses a wizard-style interface with Next and Previous buttons, for example, it should use traditional page loads (instead of XMLHttpRequest) to display the next screen or the previous screen because this is a situation in which the user expects the browser's Back button to work the same way as the application's Previous button.

More generally, the browser's Back button should not be confused with an application's Undo feature. Ajax applications may implement their own undo/redo options, if this is useful to their users, but it should be clear that this is different from what is provided by the Back and Forward buttons.




JavaScript. The Definitive Guide
JavaScript: The Definitive Guide
ISBN: 0596101996
EAN: 2147483647
Year: 2004
Pages: 767

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net