Skip to main content

Ajax and XML: Five common Ajax patterns

Helpful Ajax design patterns you can use today

Jack D Herrington (jherr@pobox.com), Senior Software Engineer, Leverage Software Inc.
Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles. You can reach Jack at jherr@pobox.com.

Summary:  Asynchronous JavaScript + XML (Ajax) was certainly the technology buzzword of 2006 and looks to do just as well or better in 2007. But what does it really mean for your application? And which common architectural patterns are used widely in Ajax applications? Discover five common Ajax design patterns that you can use as a basis for your own work.

View more content in this series

Date:  06 Mar 2007
Level:  Intermediate
Activity:  2691 views
Comments:  

Sure, Ajax is the Web 2.0 buzzword that everyone wants associated with their site. But what does it really mean? And how are engineers integrating it into their sites at an architectural level. In this article, I cover the basics of Ajax and show some Ajax design patterns that have become proven best practice with Web 2.0 development.

To start, Ajax is just a buzzword that covers a set of technologies, including Dynamic HTML (DHTML) and the XMLHTTPRequest object. DHTML is a combination of three elements: Hypertext Markup Language (HTML), JavaScript code, and Cascading Style Sheets (CSS). Using JavaScript code on a Web page, you can change the page dynamically to add, remove, or change the content. That's the dynamic portion of DHTML. JavaScript code uses the XMLHTTPRequest object to request data from the server after the page has been loaded.

The combination of these two elements -- requesting data from the server on the fly and changing the page to use the data -- is the essence of what's called Ajax and the dynamic nature of Web 2.0 sites.

But that doesn't really tell you how these features are used in the real world and how you should use them on your site. For that, you need a set of simple design patterns. If you are unfamiliar with that term, it comes from the excellent book of the same name (see Resources). That book provided a set of implementation patterns for the common tasks that confront engineers. The book provided not just best practices for how to design systems but also a terminology that engineers can use to talk about their code.

This article presents five common Ajax design patterns. They vary in using HTML, XML, and JavaScript code to get data from the server. I start with the simplest pattern, which is to update your page with new HTML from the server.

Pattern 1. Replacing HTML segments

Perhaps the most common Ajax task is to request updated HTML from the server and update a portion of the page with it. You can do this can periodically -- for example, to update stock quotes. Or you can update on demand -- for example, in response to a search request.

The code in Listing 1 requests a page from the server, and then places that content into a <div> tag in the body of the page.


Listing 1. Pat1_replace_div.html

<html>
<script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dobj = document.getElementById( 'htmlDiv' );
    dobj.innerHTML = req.responseText;
  }
}

function loadUrl( url ) {
  if(window.XMLHttpRequest) {
    try { req = new XMLHttpRequest();
    } catch(e) { req = false; }
  } else if(window.ActiveXObject) {
    try { req = new ActiveXObject('Msxml2.XMLHTTP');
    } catch(e) {
    try { req = new ActiveXObject('Microsoft.XMLHTTP');
    } catch(e) { req = false; }
  } }
  if(req) {
    req.onreadystatechange = processReqChange;
    req.open('GET', url, true);
    req.send('');
  }
}

var url = window.location.toString();
url = url.replace( /pat1_replace_div.html/, 'pat1_content.html' );
loadUrl( url );
</script>
<body>
Dynamic content is shown between here:<br/>
<div id="htmlDiv" style="border:1px solid black;padding:10px;">
</div>
And here.<br/>
</body>
</html>

Listing 2 shows the content that the code is requesting.


Listing 2. Pat1_content.html
	
HTML encoded content goes here.

To see what this looks like in a live environment, view this online version of pat1_replace_div.html Open link to view pat1_replace_div.html in new window.

When I load the page in Firefox, I see the result shown in Figure 1.


Figure 1. The page with the replaced <div> tag
Page with replaced tag

Go back to the code in Listing 1 and look at a few things. The first thing to notice is the loadUrl() function, which requests a URL from the server. This function uses the XMLHTTPRequest object to ask the server for the new content. It also specifies a callback function -- in this case, processReqChange -- that's called when the browser has received the content.

The processReqChange function then inspects the object to see whether the request has been completed. If it has, the function sets the innerHTML of the <div> tag in the page into the text of the response.

The use of the <div> tag as a placeholder for dynamic content is a staple of Ajax code. These tags have no visible presence (unless you add borders and such, as I have), but they act as a good marker for where content should go. Engineers also use the <span> tag for replaceable segments, as I demonstrate later. The difference between a <div> and a <span> tag is that the former imposes a line break (like a paragraph), while the latter delineates a section of inline text.

Getting back to the processReqChange function for a moment, it's important that the function check the value of both the status and the readyState value. While some browsers will call the function only when the request is complete, other browsers will call back continuously to tell the code that the request is still running.

The tabbed display variant

Another variant of this pattern is to create a tabbed style of display. Listing 3 shows a simple tabbed Ajax interface.


Listing 3. Pat1_tabs.html

<html>
<script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dobj = document.getElementById( 'tabDiv' );
    dobj.innerHTML = req.responseText;
  }
}

function loadUrl( tab ) {
  var url = window.location.toString();
  url = url.replace( /pat1_tabs.html/, tab );
  ...
}

function tab1() { loadUrl( 'pat1_tab1_content.html' ); }
function tab2() { loadUrl( 'pat1_tab2_content.html' ); }
tab1();
</script>
<body>
<a href="javascript: void tab1();">Tab 1<a> 
<a href="javascript: void tab2();">Tab 2<a>
<div id="tabDiv" style="border:1px solid black;padding:10px;">
</div>
</body>
</html>

Listing 4 shows the content for the first tab.


Listing 4. Pat1_tab1_content.html

Tab 1 content

And Listing 5 shows the content for the second tab.


Listing 5. Pat1_tab2_content.html

Tab 2 content

To see what this looks like in a live environment, view this online version of pat1_tabs.html Open link to view pat1_tabs.html in new window.

When I bring this page up in my browser, I see the first tab, as shown in Figure 2.


Figure 2. The content for the first tab
Content for the first tab

I then click the link for the second tab. The browser retrieves the second tab's contents and shows it in the tab area, as shown in Figure 3.


Figure 3. The content for the second tab
Content for the second tab

This is the quintessential use of this design pattern -- to take requests from the user and update a portion of the display with the new material, in this case, creating the illusion of a tabbed display. The value from the application side is that you can downloaded a much lighter-weight page to customers, who can then access the material they want on demand.

Before Ajax, the common technique was to have both tabs on the page, then hide or show them on demand. This meant that the HTML for the second tab was created even if it was never viewed, wasting both server time and bandwidth. With this new Ajax method, the HTML for the second tab is created only when the user requests it.

The read more variant

To see what this looks like in a live environment, view this online version of pat1_readmore.html Open link to view pat1_readmore.html in new window.

Yet another variation on this theme is the Read more link, as shown in Figure 4.


Figure 4. The Read more link on my boring blog entry
Read more link

Suppose that I really wanted to read more about the continuing adventures of my dog walk. I can click the Read more link and have that link replaced with the complete engrossing story, as shown in Figure 5.


Figure 5. The page after clicking the Read more link
After clicking Read more

The value for customers is that they get more material seamlessly without a page refresh.

Listing 6 shows the code for this page.


Listing 6. Pat1_readmore.html

<html>
<script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dobj = document.getElementById( "moreSpan" );
    dobj.innerHTML = req.responseText;
  }
}

function loadUrl( url ) { ... }

function getMore()
{
  var url = window.location.toString();
  url = url.replace( /pat1_readmore.html/, 'pat1_readmore_content.html' );
  loadUrl( url );
}
</script>
<body>
<h1>Walking the dog</h1>
I took my dog for a walk today. 
<span id="moreSpan">
<a href="javascript: void getMore()">Read more...</a>
</span>
</body>
</html>

Listing 7 shows the content for the "read more" section.


Listing 7. Pat1_readmore_content.html

It was a nice day out. Warm and sunny. My dog liked getting out for a stretch.

This code demonstrates the use of the <span> tag instead of the <div> tag. The approach you use depends on the requirements of your user interface (UI). But as you can see, it's easy to use either approach.

Getting new HTML for the page is one thing, but what about when you want the JavaScript code on the page to actually do something intelligent with the data. How do you get the data to the browser in a structured way? Why XML, of course.


Pattern 2. Reading XML data

For some reason, Ajax has become synonymous with XML, even though XML isn't strictly required. As you can see from the examples above, you can return straight text or even fragments of HTML -- or Extensible HTML (XHTML) -- code. But sending XML can have its rewards.

Listing 8 shows Ajax code that requests records about books from the server, then displays that data in a table within the page.


Listing 8. Pat2_xml.html

<html>
<head>
<script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 && req.responseXML ) {
    var dtable = document.getElementById( 'dataBody' );
    var nl = req.responseXML.getElementsByTagName( 'book' );
    for( var i = 0; i < nl.length; i++ ) {
      var nli = nl.item( i );
      var elAuthor = nli.getElementsByTagName( 'author' );
      var author = elAuthor.item(0).firstChild.nodeValue;
      var elTitle = nli.getElementsByTagName( 'title' );
      var title = elTitle.item(0).firstChild.nodeValue;

      var elTr = dtable.insertRow( -1 );

      var elAuthorTd = elTr.insertCell( -1 );
      elAuthorTd.innerHTML = author;

      var elTitleTd = elTr.insertCell( -1 );
      elTitleTd.innerHTML = title;
} } }

function loadXMLDoc( url ) {
  if(window.XMLHttpRequest) {
    try { req = new XMLHttpRequest();
    } catch(e) { req = false; }
  } else if(window.ActiveXObject) {
    try { req = new ActiveXObject('Msxml2.XMLHTTP');
    } catch(e) {
    try { req = new ActiveXObject('Microsoft.XMLHTTP');
    } catch(e) { req = false; }
  } }
  if(req) {
    req.onreadystatechange = processReqChange;
    req.open('GET', url, true);
    req.send('');
  }
}

var url = window.location.toString();
url = url.replace( /pat2_xml.html/, 'pat2_xml_data.xml' );
loadXMLDoc( url );
</script>
</head>
<body>
<table cellspacing="0" cellpadding="3" width="100%">
<tbody id="dataBody">
<tr>
  <th width="20%">Author</th>
  <th width="80%">Title</th>
</tr>
</tbody>
</table>
</body>
</html>

Listing 9 shows the data for the page.


Listing 9. Pat2_xml_data.xml

<books>
  <book>
    <author>Jack Herrington</author>
    <title>Code Generation in Action</title>
  </book>
  <book>
    <author>Jack Herrington</author>
    <title>Podcasting Hacks</title>
  </book>
  <book>
    <author>Jack Herrington</author>
    <title>PHP Hacks</title>
  </book>
</books>

To see what this looks like in a live environment, view this online version of pat2_xml.html Open link to view pat2_xml.html in new window.

When I load the page in my browser, I see the result shown in Figure 6.


Figure 6. The XML display page
XML display page

The big difference between this page and the pages in the previous pattern is in the processReqChange function. Instead of looking at responseText, you now look at responseXML, an XML Document Object Model (DOM) available only if the response from the server was properly encoded XML.

Using responseXML, I request the list of <book> tags from the XML document. I then get the <title> and <author> elements from each. Next, I add a row to the table for each book and cells to each row to contain the author and title data.

This is a pretty rudimentary use of the XML data. More sophisticated JavaScript code can perform client-side sorting or searching based on the returned data.

Unfortunately, the downside of transferring XML data is that it takes some time for the browser to parse through the XML document. Also, the JavaScript code to find the data in the XML can be complex (as seen in Listing 8). The alternative is to request JavaScript code from the server.


Pattern 3. Reading JavaScript data

Requesting JavaScript data from the server is a technique that often goes by the classy code name JavaScript Object Notation (JSON). The value of returning JavaScript data is that it's efficient for the browser to parse and creates JavaScript data structures, which are a lot easier to use.

Let me revise the code in Listing 8 that read XML from the server to read JavaScript data from the server, instead. This new code is shown in Listing 10.


Listing 10. Pat3_js.html

<html><head><script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dtable = document.getElementById( 'dataBody' );
    var books = eval( req.responseText );
    for( var b in books ) {
      var elTr = dtable.insertRow( -1 );

      var elAuthorTd = elTr.insertCell( -1 );
      elAuthorTd.innerHTML = books[b].author;

      var elTitleTd = elTr.insertCell( -1 );
      elTitleTd.innerHTML = books[b].title;
} } }

...

All the HTML code remains the same. The processReqChange function simply changes to read an eval that the JavaScript data returned from the server. The function then uses the JavaScript objects that come out of the eval as the source of the data, which is then added to the table.

Listing 11 shows the JavaScript data from the server.


Listing 11. Pat3_js_data.js

[ { author: 'Jack Herrington', title: 'Code Generation in Action' },
{ author: 'Jack Herrington', title: 'Podcasting Hacks' },
{ author: 'Jack Herrington', title: 'PHP Hacks' }
]

To see what this looks like in a live environment, view this online version of pat3_js.html Open link to view pat3_js.html in new window.

It's easy to see why so many Ajax application engineers prefer to use JavaScript code instead of XML to encode the data. The JavaScript code is easier to read and manage as well as easier for the browser to process.

With all this data-gathering and display, you see that the key to Ajax is the display of current data -- the important part there being current. So, how do you ensure that you're always getting fresh data from the server?


Pattern 4. Avoiding browser cache

Browsers attempt to optimize Web traffic, so if you ask for the same URL twice, it's likely that rather than request the page again, your browser will simply use the page stored in the browser cache. So, another common pattern in Ajax applications is the use of some randomizing element in the URL to ensure that the browser doesn't return a cached result.

My favorite technique is to add the numeric value of the current time to the URL. Listing 12 shows this technique.


Listing 12. Pat4_cache.html

<html>
<script>
...

function loadUrl( url ) {
  url = url + "?t="+((new Date()).valueOf());
  ...
}

...

To see what this looks like in a live environment, view this online version of pat4_cache.html Open link to view pat4_cache.html in new window.

This is the code from Listing 1 but with the addition of some JavaScript text manipulation of the URL string. I append to the URL a new parameter called t that has the value of the time. It doesn't really matter whether the server recognizes the value. It's just a way to ensure that the browser ignores its URL-based page cache.


Pattern 5. Replacing multiple HTML segments

The final pattern I demonstrate is an advanced version of the first pattern: the replacement of a <div> tag with content from the server. A common problem in Web applications is that in response to user input, several areas of the display must be updated. For example, in a stock quote application, one part of the display might show the most recent quote, while another portion of the display shows a list of the most recent values.

To update multiple areas of the display, I use an XML response from the server that contains data for both sections. Then, I use a regular expression to break out the individual sections from the response. Listing 13 shows this technique.


Listing 13. Pat5_multi_segment.html

<html>
<head>
<script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var one = req.responseText.match( /\<one\>(.*?)\<\/one\>/ );
    document.getElementById( 'divOne' ).innerHTML = one[1];
    var two = req.responseText.match( /\<two\>(.*?)\<\/two\>/ );
    document.getElementById( 'divTwo' ).innerHTML = two[1];
} }

function loadXMLDoc( url ) { ... }

var url = window.location.toString();
url = url.replace( /pat5_multi_segment.html/, 'pat5_data.xml' );
loadXMLDoc( url );
</script>
</head>
<body>

This is the content for segment one:<br/>
<div id="divOne" style="border:1px solid black;padding:10px;">
</div>
And segment two:<br/>
<div id="divTwo" style="border:1px solid black;padding:10px;">
</div>

</body>
</html>

Listing 14 shows the data from the server.


Listing 14. Pat5_data.xml

<segments>
  <one>Content for segment one</one>
  <two>Content for segment <b>two</b></two>
</segments>

To see what this looks like in a live environment, view this online version of pat5_multi_segment.html Open link to view pat5_multi_segment.html in new window.

When I load this code in my browser, I see the result shown in Figure 7.


Figure 7. The two-segment display updated with data from the server
Two-segment display

In the page code, I could have used the XML response, as the material returned from the server is valid XML. But it was easier to use regular expressions instead to crack the individual segments from the XML code.


Conclusion

Ajax is as powerful as it is misunderstood and misused. The patterns I've shown in this article provide a good jumping-off point for using Ajax in your Web application. But in addition to using the code provided here, I recommend having a look at some of the great Ajax and Web UI libraries that have come along with the Web 2.0 revolution. Chief among these is the Prototype.js library, which provides easy methods to get data to and from the server as well as cross-browser-compliant methods to update Web page content. The value of using these libraries is that dedicated engineers maintain and test them on a wide variety of browsers and platforms, which can save you a lot of work and headache.

Either way you cut it, Ajax as demonstrated by the patterns in this article is something you should check into to add dynamic behavior to your applications.



Download

DescriptionNameSizeDownload method
Sample Ajax pattern files for this articlex-ajaxxml2_ajax_patterns.zip7KB HTTP

Information about download methods


Resources

Learn

  • developerWorks XML zone: Learn all about XML at the developerWorks XML zone.

  • Prototype.js: Try Prototype.js, a well-designed and well-implemented JavaScript library that provides cross-browser-compliant Ajax and DHTML objects. It's well worth your time to look at using Prototype.js instead of rolling your own Ajax JavaScript code.

  • Design Patterns (Erich Gamma, et al., Addison-Wesley, 1995): Read the seminal book on the use of patterns in software engineering.

  • IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.

  • XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.

  • developerWorks technical events and webcasts: Stay current with technology in these sessions.

  • Ajaxian: With this great resource, keep up with developments in Ajax and the front-end widgets that use it.

Get products and technologies

  • Yahoo! UI library: Get the Yahoo! UI library, a Web UI kit that you can use along with Ajax in your Web applications.

  • ATLAS library: Try the ATLAS library for Microsoft's take on an Ajax browser-compatibility layer. You don't need to use Microsoft® ASP.NET to make use of the library.

  • Scriptaculous: Download this library of cross-browser effects and widgets that uses the Prototype.js library.

  • Moo.fx: Get this lightweight widgets library that is based on Prototype.js.

Discuss

About the author

Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles. You can reach Jack at jherr@pobox.com.

Comments



Trademarks

static.content.url=/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Web development
ArticleID=197385
ArticleTitle=Ajax and XML: Five common Ajax patterns
publish-date=03062007
author1-email=jherr@pobox.com
author1-email-cc=dwxed@us.ibm.com