Developing Sites With AJAX: Design Challenges and Common Issues

Advertisement

Almost every movie has a scene in which a character pull the protagonist aside and says, “There’s something you should know about [insert another character’s name here].” Most of the time, we find out some dark secret about a supposed friend of the protagonist or that the main ally is actually an evil overlord. This is that moment, and I am here to tell you a few things about our friend in the Web 2.0 world: AJAX.

We seem to have AJAX licked. The Web technology is ubiquitous, and libraries and frameworks make it dead easy for us to create highly interactive Web applications and to spice up our static pages and blogs.

For example, we could take the following HTML…

<div id="target"></div>
<p><a href="#" class="ajaxtrigger">Let there be AJAX magic</a></p>

… and add this jQuery code:

$('.ajaxtrigger').click(function(){
  $('#target').load('ajaxcontent.html');
});

In a browser, if we clicked on the link labelled “Let there be AJAX magic,” the content of the HTML document ajaxcontent.html would be loaded and written into the element with the ID target. You can try this very simple AJAX example here1. It’s simple and easy to use, but what’s really happening there? What is AJAX?

What Is AJAX?

After the main HTML document has loaded, AJAX loads content from the server and replaces parts of the document with that content rather than reload the main document. It’s as simple as that. AJAX stands for “Asynchronous JavaScript and XML2” and was meant to load only XML documents, but we soon used it to load everything under the sun, and so the XML part was quickly forgotten. The asynchronous part is the killer feature; but what is it?

AJAX Model3
The traditional model for web applications (left) compared to the Ajax model (right).

Let’s start by analysing how a normal Web interaction works:

  1. The user enters a URI (like http://wait-till-i.com/index.php4) into a user agent (usually a browser).
  2. The browser turns this URI into an IP and requests the file located at the URI specified endpoint.
  3. The browser loads the file and, if it recognizes the document type, tries to display it.
  4. If the document is in HTML, we get an interface that we can interact with; for example, by clicking a link or entering data into a form and submitting it.
  5. In both cases, the whole document is replaced and the sequence restarts.

This has worked since the beginning of the Web and has become expected behaviour for Web surfers. With AJAX, we disrupt this sequence of events. Instead of reloading the document or loading a new one, we replace only a part of the interface, either when the user requests it or automatically every few seconds to display new information.

The benefits of AJAX are pretty clear:

  • We maintain a consistent interface, rather than discard it only to bring it up again with a few slight changes after a long and annoying loading process.
  • We request only the data that we need, when we need it, saving us a lot of server traffic.
  • We are able to offer data without wrapping HTML around it to make it an interface.
  • We allow for simultaneous interaction; a user would be able, for example, to fill out a form while an attachment uploads in the background.

However, with great power comes great responsibility, and with AJAX we have taken it upon ourselves to simulate browser behavior for end users.

AJAX Should Not Break The Web

The first thing to make sure of is that you do not break the Web with your AJAX solutions. The above example would, though:

<div id="target"></div>
<p><a href="#" class="ajaxtrigger">Let there be AJAX magic</a></p>

This is not useful HTML. If JavaScript is not available or anything else goes wrong, you would be offering the end user a link that goes nowhere. This is annoying; I’ve come to your website, took the step of clicking a link, got excited by the prospect of awesome content but don’t get anything. Not good. So, rather than keep the URI in the JavaScript part of the AJAX solution, leave it in the HTML:

<div id="target"></div>
<p><a href="ajaxtest-fullpage.html" class="ajaxtrigger">
  Let there be AJAX magic
</a></p>

This would ensure that the link works; if there is a JavaScript error, the browser would simply move on to load and display ajaxcontent.html. The jQuery code would change accordingly:

$('.ajaxtrigger').click(function(){
  var url = $(this).attr('href');
  $('#target').load(url);
  return false;
});

Instead of hard-wiring a URI to load, we just read the href attribute of the link. The return false is needed to stop the browser from following the link after jQuery has initiated the AJAX request. This also means that any link with the class ajaxtrigger will load content via AJAX and display it in the element with the ID target. You can try this reusable AJAX example here5.

There is a problem, of course, because the document we load might be a full HTML document, with a head and a body and so on. This works well in the browser, but the AJAX request would load and inject this document it into another document, which is invalid HTML and would cause display issues. Try this out by clicking the “Load a full document” link on the page referred to above.

Let’s say that ajaxtest-fullpage.html is the following:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  [... some links and title and so on ...]
</head>
<body>
<div id="doc" class="yui-t7">
  <div id="hd" role="banner"><h1>Excerpt from Alice's Adventure Underground</h1></div>
  <div id="bd" role="main">
    <blockquote
     cite="http://ia341030.us.archive[...]-h.htm">
      <p>Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had  peeped into the book her sister was reading, but it had no pictures or conversations in it, and where is the use of a book, thought Alice, without pictures or conversations? So she was considering in her own mind, (as well as she could, for the hot day made her feel very sleepy and stupid,) whether the pleasure of making a daisy-chain was worth the trouble of getting up and picking the daisies, when a white rabbit with pink eyes ran close by her.</p>
    </blockquote>
    <p>Excerpt taken from 
      <a href="http://ia341030.us.archive[...]-h.htm">archive.org</a>.
    </p>
  </div>
  <div id="ft" role="contentinfo">
    <p>Demo by <a href="http://wait-till-i.com">Chris Heilmann</a></p>
  </div>
</div>
</body>
</html>

jQuery is all about selectors, which is why the load() function allows you to cut down on the returned HTML by defining a selector. This means that you can change the script to the following (you can try the selector filtering example for yourself6):

$('.ajaxtrigger').click(function(){
  var url = $(this).attr('href');
  $('#target').load(url+' #bd blockquote');
  return false;
});

This loads only the blockquote into the other document, so you wouldn’t be creating invalid HTML with the AJAX call. However, we lose the other benefit of AJAX, which is to load less content. If the page is 100 KB and you want to show only the main text, which is 2 KB, why should your users have to wait for 98 KB to load?

To work around this, you need to go server-side. In PHP, you can get information about the request that was sent to load the page. One bit of information is the request method; JavaScript libraries such as jQuery send a specific header across when they load a document with AJAX. You can use this in PHP to set up conditional content:

<?php if($_SERVER['HTTP_X_REQUESTED_WITH']=='XMLHttpRequest'){?>
This is content requested by AJAX.
<?php }?>

<?php if($_SERVER['HTTP_X_REQUESTED_WITH']==''){?>
This is the normal content requested in a browser
<?php }?>

Try this header, switching out example for yourself7: click the “Load a document with AJAX” link, and then right-click (or Command-click) the same link to open it in a new tab (or hit the “Load the same document without AJAX” link). The results should be “This is content requested by AJAX” and “This is the normal content requested in a browser” respectively.

This way, you can keep all of the header and footer information in includes and load them only when the request could not be done with AJAX. Try the header includes example8 to see it in action:

<?php if($_SERVER['HTTP_X_REQUESTED_WITH']==''){?>
  include('header.php');
<?php }?>

<blockquote
 cite="http://ia341030.us.archive[...]-h.htm">
  <p>Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, and where is the use of a book, thought Alice, without pictures or conversations? So she was considering in her own mind, (as well as she could, for the hot day made her feel very sleepy and stupid,) whether the pleasure of making a daisy-chain was worth the trouble of getting up and picking the daisies, when a white rabbit with pink eyes ran close by her.</p>
</blockquote>
<p>Excerpt taken from 
  <a href="http://ia341030.us.archive[...]-h.htm">archive.org</a>.
</p>

<?php if($_SERVER['HTTP_X_REQUESTED_WITH']==''){?>
  include('footer.php');
<?php }?>

Using this “unobtrusive AJAX” approach does a few things:

  • You don’t create broken links, ever.
  • You make it easier to maintain functionality; no need to hunt for URIs in the JavaScript—everything is in the HTML.
  • You allow users to open links in another window or tab.
  • You maintain the AJAX-enabled and AJAX-disabled content in the same document without duplicating content.

“Unobtrusive JavaScript” is the term for this method of developing highly interactive websites. It was coined by Stuart Langridge in 20029, and I wrote a self-training course10 for it in 2004. Incidentally, Stuart was also the first author to cover AJAX in a JavaScript book, the unfortunately named DHTML Utopia11. My own not-quite-so-succinctly-titled book Beginning JavaScript with DOM Scripting and AJAX12 was, I think, the second. Both books follow the approach shown here and create AJAX solutions that fall back to non-JavaScript versions.

Jeremy Keith tried to further popularize this idea of “safer AJAX” in 2006 by calling it “Hijax”13, and he wrote a book titled Bulletproof AJAX14 in 2007. Sadly, though, I have encountered people who use this as an excuse, saying, “We’re building an AJAX solution now, and we’ll move it to Hijax later.” This will not work! Do it right the first time and you’ll have a stable solution. There is no “We’ll fix it in the next iteration” when it comes to essential functionality in Web development: 12 years of professional development have taught me that much.

AJAX Design Challenges

In dealing with AJAX as designers, we have to reconsider the ways in which we define interfaces. Rather than concentrate on the look and feel of the page and subsequent pages, we need to drill down to an atomic level. Each part of an AJAX interaction needs to be defined. Also, think about non-JavaScript versions of widgets.

With AJAX interfaces, we move into a world of applications that have states and views and out of a world in which our document or page model was based on ideas carried over from print. This for me is a good thing. The Web is a rich medium, not a sequence of linked designs.

AJAX And Usability

As mentioned, we use AJAX to disrupt the normal browsing behaviour of our users. This can be a good thing: no one claims that browsers do everything right, but understanding just how many things we should take care of when taking over the browser is important.

What Browsers Do That You Need to Simulate

We sometimes forget just how many things the browser does for us:

  • When we click a link, an indicator alerts us to a loading process (whether an animated icon, progress bar, etc.).
  • For large files, the progress bar gives us an idea of how far we’ve reached in the loading process.
  • If we get tired of waiting, we can hit the “Stop” button or try again by reloading the page.
  • If a page cannot be found, we are shown an error page.
  • If a page takes too long to load, we are shown an error page.
  • Other errors we encounter (for example, a page that needs authentication, or a document that has been moved) are also displayed on a special page.
  • We can right-click a link to open it in a new tab or window, instead of replacing the current document.
  • We can bookmark a page and come back to it at any time in the future.
  • When we need to undo something that’s gone wrong, a “Back” button takes us back one step in our journey.

All of this needs to be accounted for in a full-fledged AJAX application, because AJAX should improve the end user’s experience rather than make it harder. Let’s now enhance our AJAX script until we can say that we’ve covered the basics.

Bookmarking and the Back Button

One thing I won’t go into in detail is the “Back” button and bookmarking functionality. To make this work, you need to update the URI of the current page with a fragment and reload a hidden frame in the page. There are all kinds of annoying differences between browsers, too, and you can use something like the history plug-in15 for jQuery to get this to work.

Alerting the User That Something Is Loading

Probably the first thing to fix is to tell the user that something is loading when they click a link or push a button. If the page shows no apparent change, the user will think something is wrong and keep clicking. This is an unfortunate human reflex, because the more you tell a computer to do something, the slower and more confused it gets.

A simple way to provide the user with feedback is to show a loading message. To do this in jQuery, we need to get away from the load() method and instead use ajax(), which gives us information about what happens to the request, such as:

  • The beforeSend event that is fired before the AJAX request is initiated, and
  • The success event that is fired when the AJAX request is successful.

Putting them together, we can add a loading message16 to the target element when the AJAX request starts, which is replaced when the data has successfully loaded:

$(document).ready(function(){
  var container = $('#target');
  $('.ajaxtrigger').click(function(){
    doAjax($(this).attr('href'));
    return false;
  });
  function doAjax(url){
    $.ajax({
      url: url,
      success: function(data){
        container.html(data);
      },
      beforeSend: function(data){
        container.html('<p>Loading...</p>');
      }
    });
  }
});

Error Handling

As you may have guessed, the next logical step is to handle error cases. This is something far too many AJAX solutions haven’t gotten right, and seeing a great application become useless just because one call has timed out is very frustrating.

We have to prepare for three different errors:

  • The user tries to load an external file that is not available because of AJAX security settings;
  • There is some server error (for example, “Page not found”);
  • The resource takes too long to load.

The following script takes care of all this, and you can see it in action on the error handling demo page17.

$(document).ready(function(){
  var container = $('#target');
  $('.ajaxtrigger').click(function(){
    doAjax($(this).attr('href'));
    return false;
  });
  function doAjax(url){
    if(url.match('^http')){
      var errormsg = 'AJAX cannot load external content';
      container.html(errormsg);
    } else {
      $.ajax({
        url: url,
        timeout:5000,
        success: function(data){
          container.html(data);
        },
        error: function(req,error){
          if(error === 'error'){error = req.statusText;}
          var errormsg = 'There was a communication error: '+error;
          container.html(errormsg);
        },
        beforeSend: function(data){
          container.html('<p>Loading...</p>');
        }
      });
    }
  }
});

The changes are:

  • We test whether the link URI starts with http and then report an error that loading it with AJAX is not possible.
  • If the link doesn’t begin with http, we start a new AJAX request. This one has a few new features:
    • We define a timeout of 5 seconds (i.e. 5000 milliseconds);
    • We add an error handler.
  • The error handler either sends us what happened on the server as req.statustext or gives us the error message timeout when the 5 seconds are up. So, we need to check what we got before we write out the error message.

Highlighting Changes

We’re almost done enhancing the usability of our AJAX solution. One last touch is to make it very obvious that something on the page has changed. The standard way of doing this is called the yellow fade18 and was introduced in 2004 by 37signals in its Basecamp application.

With this technique, you change the background colour of the element to yellow and then fade it smoothly back to white. This grabs the user’s attention without overloading them (unlike zooming in on the content in or popping it up, PowerPoint style, which would overwhelm), and it is pretty easy to implement.

jQuery has a plug-in in the effects package called Highlight19 that does exactly that. Using it, we can highlight the AJAX returns20, making it very obvious that something has changed:

$(document).ready(function(){
  var container = $('#target');
  $('.ajaxtrigger').click(function(){
    doAjax($(this).attr('href'));
    return false;
  });
  function doAjax(url){
    if(url.match('^http')){
      var errormsg = 'AJAX cannot load external content';
      container.html(errormsg).
        effect('highlight',{color:'#c00'},1000);
    } else {
      $.ajax({
        url: url,
        timeout:5000,
        success: function(data){
          container.html(data).
            effect("highlight",{},1000);
        },
        error: function(req,error){
          if(error === 'error'){error = req.statusText;}
          var errormsg = 'There was a communication error: '+error;
          container.html(errormsg).
            effect('highlight',{color:'#c00'},1000);
        },
        beforeSend: function(data){
          container.html('<p>Loading...</p>');
        }
      });
    }
  }
});

Notice the different colors for the error case and success case.

This is about all we need to do to make AJAX more usable. But to make it accessible to everyone out there, we have to do a bit more.

AJAX And Accessibility

Accessibility does not mean much more than hard-core usability. If the “average” user is confused by an interface that doesn’t work as they expect, imagine the predicament of users who cannot see the interface at all. Or think someone who has trouble noticing changes from one page to the next and all of a sudden has to deal with small changes on individual pages—changes they are not notified about. Imagine a keyboard user tabbing through a document to activate a link and out of the blue being confronted by 10 more links. There are a lot more cases such as these, and your interface should be able to handle them at least at a very basic level.

Much Ado About Screen Readers

If you research the topic of AJAX and accessibility, you will come across a lot of tutorials that deal with the problem of screen readers. I won’t go into details—this could be its own article—but here are the main points:

  • Screen readers are tools that read out to visually impaired users what is on the screen (or in the HTML and hidden by CSS).
  • Screen readers work on top of the normal browser and enhance its functionality. Specifically, they allow for quicker keyboard navigation (for example, jumping from headline to headline with a shortcut).
  • They take a copy of a document after it has loaded and apply changes to it.
  • This means that screen readers understand JavaScript, but they only execute a request when the page has loaded. If you change a document with JavaScript and AJAX after it has loaded, you need to notify the screen reader somehow that something has changed and refresh the copy of the page. This can be done by refreshing a form field21 as a hack.

The real problem with screen readers, and any assistive technology, is that they add yet another level of complexity to our Web interaction.

We have HTML interfaces such as links and forms that need to work with all kinds of input devices: keyboard, mouse, voice recognition software, to name a few. Then the browser needs to somehow tell the assistive software (whether a screen reader or software that zooms the screen or a voice recognition tool) that something has changed, and that other tool has to translate it into an understandable format. All of this can, and frequently does, fail.

Much like how HTML 5 is being pushed to replace HTML 4 because the latter is not rich enough to support the interfaces we want to build, WAI-ARIA22 is a standard that works around the problem of assistive technology and browsers not talking to each other.

With WAI-ARIA, you can tell a screen reader, for example, that a particular element on the page changes frequently and will be refreshed with AJAX. Again, this topic is too big to cover here, but some good articles are out there23 in case you are interested.

Important Feature #1: Keyboard Access

One very important requirement of accessibility and AJAX is providing keyboard access, and doing this in a very basic way is not hard. The element that triggers the AJAX call has to be something that users can access with the keyboard (i.e. either a link or a button). You can test this yourself: simply use the Tab key to jump from one keyboard-accessible element to the next in your document. Can you access all of the functionality, and is it obvious where you are at any given moment?

This is where you as a designer can do a lot to make your AJAX interface more accessible. Patrick Lauke has written a wonderful article on keyboard-access styling24 to get you on your way.

Important Feature #2: Notify at the Source

The second, very important, part is to notify users in the element that they activated that something is happening. You’ll often see interfaces where the activation button or link is in one spot but the content gets loaded somewhere else on the screen. One example of this is the contact form on Get Satisfaction:

Modal Pop-Up form by get satisfaction25
Large view26

When we can see the screen in full, everything is pretty obvious. But consider an end user who has to magnify the screen to 1600% to be able to read it. Or someone who gets easily confused and uses a tool to focus on the part of the screen they are interacting with and blur out the rest. Their experience is different:

zoomed button

By clicking this, the user expects to be able to submit feedback. Instead, all they get is a darker screen, which could be a hardware problem (running out of battery?) or something else entirely. They have no information on which to base their next move.

You don’t even have to go as far as considering people with disabilities: just use a netbook whose viewport is a mere 300-pixels high (like my first-generation Eee PC) or a mobile interface that zooms into a certain part of the page (like my Blackberry with Opera Mini).

In any of these cases, your AJAX solution will be neither usable nor accessible if the section that is replaced is far removed from the button that fires the AJAX request.

You have two workarounds. The most obvious one is to keep the elements close together. If that is not possible, the other workaround is to change the content of the element that fires the AJAX request once the user clicks on it. This indicates to the end user what is going on.

notifications at the source and the target make it obvious to any user what happened.

As an added assistance, you can shift the keyboard focus to the target element when the AJAX request has been processed. Be aware, though, that this could confuse some users; being jumped around the screen without meaning to can be scary. Pretty, smooth-transitioning solutions look good to the rest of us, but they can be a total nightmare for users with learning disabilities.

Putting all of this together, take a look at this more accessible example27. It adds a span to the link to show the state of the AJAX request, it highlights the content when it has finished loading, and then it shifts the focus to the new element. Here is the final code. Check the comments (// example) to see what is going on.

$(document).ready(function(){

  // this is the container we'll load content into
  var container = $('#target');

  // adding a tabIndex of -1 makes it keyboard accessible,
  // and we can set the focus to it
  container.attr('tabIndex','-1');

  // if a user clicks on an element with the class ajaxtrigger...
  $('.ajaxtrigger').click(function(){

    // define trigger as the link
    var trigger = $(this);

    // read its href attribute (which is the URI we'll load with AJAX)
    var url = trigger.attr('href');

    // if the element does not have a class called "loaded" 
    if(!trigger.hasClass('loaded')){

      // add a new span to the element.
      trigger.append('<span></span>');

      // add a class called 'loaded' to the element
      trigger.addClass('loaded');

      // and define msg as the last span in the element
      var msg = trigger.find('span::last');

    // otherwise, simply define msg as the last span in the element
    } else {
      var msg = trigger.find('span::last');
    }
    // ^ this condition means we only add the span once and not
    //   every time users click the element.
    
    // call the doAjax function with the URI to load, 
    // the span inside the link to change and the 
    // target element to replace.    
    doAjax(url,msg,container);

    // tell the browser to not follow the link 
    return false;
  });

  // here's where the AJAX magic happens
  function doAjax(url,msg,container){

    // if the URI starts with http...
    if(url.match('^http')){
      // show an error and set the class of the span to 'error'
      msg.html(' (error!)').addClass('error');

      // tell the end user in the target element what the error is
      var errormsg = 'AJAX cannot load external content';

      // update the container with the error
      updateContainer(errormsg,'#c00');

    // if the URI does not start with http          
    } else {
      
      // start an AJAX request using the url
      $.ajax({
        url: url,

        // give the request five seconds time, otherwise call it 
        // a timeout error
        timeout:5000,
        
        // if all went well
        success: function(data){

          // set the span content to ready
          msg.html(' (ready.)');

          // update the container with the right data
          updateContainer(data,'#ff9');
        },
        
        // if there was an error
        error: function(req,error){
          
          // say in the link that there was an error and set the 
          // class of the span to 'error'
          msg.html(' (error!)').addClass('error');

          // if the error just says error, get the real status 
          // text from the browser (jQuery doesn't do this right)
          if(error === 'error'){error = req.statusText;}

          // tell the user that there is a communication error
          var errormsg = 'There was a communication error: '+error;

          // update the container with the error
          updateContainer(errormsg,'#c00');
        },
        
        // if the link was clicked but the AJAX request was not fired...
        beforeSend: function(data){

          // remove any "error" classes and set the span message to loading
          msg.removeClass('error').html(' (loading...)');
        }
      });
    }
  };
  
  // update the container 
  function updateContainer(content,colour){
    container.
      // set the content
      html(content).
        // shift the browser focus
        focus().
          // flash the container for a second in the 
          // specified colour
          effect('highlight',{color:colour},1000);
  }

});

The code is a bit longer than in that our other examples, but the payoff makes it very much worthwhile.

Important Feature #3: De-Clutter Your Interface

With a library such as jQuery, you can make anything on the page interactive and make it initiate AJAX requests. You could use roll-overs or drag-and-drop interfaces, and these are great to look at, but ask yourself: are they really intuitive? Browsers do not yet have any drag-and-drop functionality or even roll-overs. Roll over your menu bar; you have to click to initiate any action.

But by using JavaScript tricks, you can make any element keyboard accessible28. And if you build widgets, go even further by following the rules of keyboard navigation29. You could even create a screen reader-compatible drag-and-drop interface30. But again, ask yourself a few questions:

  • Is it worth the hassle?
  • Does it really make the interface easier to understand?
  • Does it make it more natural to use?
  • Does it help all users reach their goal faster, or have you implemented the feature just because it looks cool?

Making the interface as simple as possible does not mean neutering your creativity. On the contrary, the easiest and simplest interfaces are the ones that have gone through a lot of research and design iterations. Great usability means not recognizing that something has been done to make the interface easy.

What Not To Use AJAX For

Never rely on AJAX to handle sensitive information, because modern debugging tools allow anyone to see what is happening on the page. Using the Firebug extension, I can get all of the information about the HTTP traffic of a certain document, including the AJAX requests:

AJAX requests as shown in Firebug

By analyzing these requests, I could glean information that you wouldn’t want to show the world; for example, the endpoints of the services on your system (such as mail scripts), which I could exploit for my own purposes.

Nothing in your JavaScript or HTML is secure. I can change it on the fly and work around your protection mechanisms.

If you are not building a Web application but are merely offering articles for people to read or a catalogue to flip through, you probably shouldn’t go the AJAX route anyway.

The other thing to consider is search engines. If you load all of your content with AJAX, you aren’t offering much in your documents for search engines to index. Static HTML content is still best for search engine indexing—as well as performance, because pages can be packed and cached nicely on your server, if you do it right. Loading via AJAX brings up the content much faster for users and saves on bandwidth, but you will see less traffic from search engines. Something to consider.

The External Content Problem

One built-in security setting of AJAX is that you cannot load content on another server. This is critical, otherwise people would be able to call and inject whatever script they please from the Web. Definitely a bad idea.

You may sometimes need, though, to retrieve third-party content; i.e. load external content in your document as data (because you can always use iFrames to embed other documents). This is where we have to get clever with the technologies at our disposal.

The most common workaround for AJAX not being able to load something like http://icant.co.uk/index.php is to write a server-side script that loads the page and then prints it out. This is called a proxy, and you can see an example of the solution here31.

Of utmost importance when using a proxy is to whitelist the URIs that you want to load. Do not simply load any URI off the Web, or else attackers would be able to read files from your server and use your server to send out spam and attack other servers, making it look as though you were the perpetrator.

Other ways to retrieve external content is by getting data in a special format called JSON-P32 or by using a hosted proxy service such as YQL33. I’ll keep this brief because there are several solutions to this problem. If you are interested in learning more, check out this blog post on the subject34.

What To Use AJAX For

When used wisely, AJAX makes our life on the Web easier. If you’re wondering when and how to use it, check out the examples in the Design Pattern Gallery35, which are based on real user research. For starters, think about these use cases:

  • Adding a large attachment to a message.
    Nothing is more annoying than waiting for your browser to upload something without having a clue how fast and how far along it is. Browser progress bars give us a hint but no real numbers. The Yahoo User Interface uploader36, as well as jQuery implementations such as Uploadify37, show how that would look like in the browser.
  • Handling a lot of small data sets.
    A great example of this is the comments section in WordPress. Rather than having to click a lot of checkboxes or reload the page every time I want to delete or approve comments, all I do is click a few links.
  • Rating content.
    No need to reload the entire page if you just want a simple Yay or Nay from the user in response to a question.
  • Displaying constantly changing content.
    For example, financial tickers or instant updates from Twitter and Facebook.
  • Add your own use here.

I hope you’ve gained a few more insights into what AJAX is and how you can use it to improve the user experience in a way that is safe and doesn’t leave certain segments of users out in the cold. AJAX makes stuff smoother, but nothing is more annoying than a supposed enhancement spoiling the whole experience.

(al)

Footnotes

  1. 1 http://icant.co.uk/articles/things-to-know-about-ajax/very-simple-ajax.html
  2. 2 http://www.adaptivepath.com/ideas/essays/archives/000385.php
  3. 3 http://www.adaptivepath.com/ideas/essays/archives/000385.php
  4. 4 http://wait-till-i.com/index.php
  5. 5 http://icant.co.uk/articles/things-to-know-about-ajax/reusable-ajax.html
  6. 6 http://icant.co.uk/articles/things-to-know-about-ajax/selector-filtering.html
  7. 7 http://icant.co.uk/articles/things-to-know-about-ajax/header-switching.html
  8. 8 http://icant.co.uk/articles/things-to-know-about-ajax/header-includes.html
  9. 9 http://www.kryogenix.org/code/browser/aqlists
  10. 10 http://onlinetools.org/articles/unobtrusivejavascript/
  11. 11 http://www.sitepoint.com/books/dhtml1/
  12. 12 http://beginningjavascript.com
  13. 13 http://domscripting.com/blog/display/41
  14. 14 http://bulletproofajax.com/
  15. 15 http://plugins.jquery.com/project/history
  16. 16 http://icant.co.uk/articles/things-to-know-about-ajax/loading-message.html
  17. 17 http://icant.co.uk/articles/things-to-know-about-ajax/error-handling.html
  18. 18 http://37signals.com/svn/archives/000558.php
  19. 19 http://docs.jquery.com/UI/Effects/Highlight
  20. 20 http://icant.co.uk/articles/things-to-know-about-ajax/highlight-changes.html
  21. 21 http://juicystudio.com/article/improving-ajax-applications-for-jaws-users.php
  22. 22 http://www.w3.org/WAI/intro/aria
  23. 23 http://www.alistapart.com/articles/waiaria
  24. 24 http://24ways.org/2009/dont-lose-your-focus
  25. 25 http://coding.smashingmagazine.com/wp-content/uploads/2010/02/get-satisfaction-small.jpg
  26. 26 http://coding.smashingmagazine.com/wp-content/uploads/2010/02/get-satisfaction-small.jpg
  27. 27 http://icant.co.uk/articles/things-to-know-about-ajax/ajax-events.html
  28. 28 http://www.yuiblog.com/blog/2009/02/23/managing-focus/
  29. 29 http://www.w3.org/TR/wai-aria-practices/#kbd_generalnav
  30. 30 http://dev.opera.com/articles/view/accessible-drag-and-drop/
  31. 31 http://icant.co.uk/articles/things-to-know-about-ajax/load-proxy.html
  32. 32 http://icant.co.uk/articles/things-to-know-about-ajax/load-json.html
  33. 33 http://icant.co.uk/articles/things-to-know-about-ajax/load-external.html
  34. 34 http://www.wait-till-i.com/2010/01/10/loading-external-content-with-ajax-using-jquery-and-yql/
  35. 35 http://developer.yahoo.com/ypatterns/
  36. 36 http://developer.yahoo.com/yui/examples/uploader/uploader-advanced-queue.html
  37. 37 http://www.uploadify.com/demo/

↑ Back to topShare on Twitter

An international Developer Evangelist working for Mozilla in the lovely town of London, England.

Advertising

Note: Our rating-system has caused errors, so it's disabled at the moment. It will be back the moment the problem has been resolved. We're very sorry. Happy Holidays!

  1. 1

    Great article. Thanks for sharing.

  2. 2

    Brilliant, cheers!

  3. 3

    Thank you for your time invested in creating this article. This is definitely a bookmark.
    Cheers!

  4. 4

    Great advice on AJAX. Building in some safeguards is always a good idea. Excellent job explaining the facts.

  5. 5

    AJAX is like Flash, it makes things look nice but it’s not required. It fails when accessibility testing is done and most AJAX simply has to be removed. So make your site without any AJAX then try to add a small amount in if required. Ensure the site functions are still available to all users. Don’t create any more barriers than you need to.

    1) A user can always turn JavaScript off, completely.
    2) AJAX such as jQuery lightbox become invisible to screen readers.
    3) New accessibility legislation in Canada, namely Ontario, requires website accessibility according to the AODA.
    4) I’d suggest using the AJAX features to enhance existing parts of the site, for example a admin area of a web application. Dealing with forms, selecting data, it can be wonderful!

    Oh and this sites Edit Comment does not work with JavaScript off…..

  6. 6

    Hey Steve,
    “3) New accessibility legislation in Canada, namely Ontario, requires website accessibility according to the AODA.”

    There is no requirement in Canada or Ontario yet. They cannot even make the polls accessible for disabled people to vote.
    Get your facts straight.
    If you do not live in Canada do not represent us.

  7. 7

    This is an amazing tutorial for people who just got started with AJAX and jQuery. Amazingly detailed. Thanks Christian!

  8. 8

    nice one, bookmarked, cheers!

  9. 9

    A long discussion on AJAX, and no mention of Security? Tisk tisk.

    Anything exposed to the browser in JavaScript — like AJAX — means it’s open to exploit.

    You may be perfectly happy to allow your current visitors to submit a rating via AJAX, but do you want a 3rd party to be able to flood the server with those same requests?

    Likewise, allowing a logged in user to upload a large photo to your site is a great use for AJAX. Do you want someone who’s not logged in to be able to do that? Probably not.

    Care should be taken to ensure that the requests are coming from actual visitors on your site, not just anyone…

  10. 10

    I will look at this article as a reference when I’m doing my next AJAX implementation. Thanks for a great article!

  11. 11

    Thanks for these best practices. Great article.

  12. 12

    Thanks a lot for this great article! There were a lot of new impressions I will try to cope with the next time I’m working on an AJAX-project.

  13. 13

    Greatly well done tutorial.

    As a tip:Just remove those strong tags you added inside the code, because they become code as well instead of making text bolder.

  14. 14

    “Never rely on AJAX to handle sensitive information, because modern debugging tools allow anyone to see what is happening on the page. Using the Firebug extension…”

    “Modern debugging tools” like firebug allow to do this with or without ajax, even if your site is https protected, why? Because the secure link is established from the server to your browser, if your browser is the one doing the snooping or hacking it’s all an open book.

    AJAX is still GETting and POSTing to the same server than any normal HTML form. It is not more or less secure.

  15. 15

    You may be right, but the problems you have described do not apply on AJAX only but web development in general.

  16. 16

    I agree.
    Well, the best form to try reduce the incoming spams using the ajax post/get scripts, is a server-side check, like getting refeer, reading hidden dummy input’s that persons would not fill but bots love to fill them, and things like that.

  17. 17

    Hi Christian,

    I’ve dabbled with Ajax in the past but this article really clears up a few things for me. Thanks very much for sharing.

    Cheers

    Mark

  18. 18

    I liked the article in general (Though, I personally, dislike using libraries like JQuery, but that’s eithere here nor there).

    The only other comment that i’d make is that when done properly, even when done as suggested in this article, AJAX does not change search engine visibility at all. By having proper links with URIs and an AJAX handler on top which overrides the normal functionality, spiders will still be able to properly index your site. Spiders are basically just a “User with Javasctipt tuned off” after all. So, if you make your AJAX site correctly, so that it can still be used without Javascript, search indexing should not be effected in the least.

  19. 19

    I didn’t know about $_SERVER[‘HTTP_X_REQUESTED_WITH’]

    I’ve been appending the data on the way out with an ajax marker. This is much better. Thanks!

  20. 20

    About half a year ago I tried my luck with Ajax in in pure Javascript, but with no results except tons of frustration. I wish I have read your article at that time. Good job

  21. 21

    Big thanks man … Bookmarked …

  22. 22

    This is quite possibly the most useful article I’ve read on the web in a long time. I’ve been slowly learning and trying to implement AJAX functionality in my designs and recently started to consider accessibility issues and encountering java-disabled browsers. I’ve spent most of the day implementing some of the stuff from this article in my existing sites and it’s awesome! Thank you very much for writing and sharing this with the community!

  23. 23

    Very nice, thanks for taking the time to write this article. Definitely bookmarking and passing it around to a few developers I know.

  24. 24

    Superb resources. Thanks for sharing.

  25. 25

    I would disagree on the “AJAX Should Not Break The Web” section. Fallbacks to traditional javascript-less alternatives is actually a worse approach. It means there are 2 versions of your application to keep track of, keep in sync, etc.

    Applications should require that a valid client be used to interact with them. If that means requiring javascript to function so be it. Flash, so be it. That lets us say “If you view our app with a supported client, it will work as we intend it to. And if you don’t, you’ll need to get one.”.

    Take some real world examples: A CD cannot play in a Cassette player. A Mac program cannot run on Windows. You get the point.

    Supporting fallbacks to javascript-less functionality is more of a hack than simply requiring that your viewer views your application in an expected way.

  26. 26

    I hate when Ajax used for paginator, and you cannot use middle-click to open in new tab. You may only have one page at once. And this ajax gives no benefit. They make it only to add fading effect (though this animation delays new appearing of new content, and this is annoying too).

    I rather leave that site forever. Unfortunately, this is common practice in ajax sites (fortunately, there are not many of them)…

    To be honest, never seen unobstrutive javascript in real word, maybe because programmers are lazy (if I’d be programmer, I would use these cool tricks).

  27. 27

    WOW..AJAX…its a awesome plug in…
    thanks

  28. 28

    Take a real world example: an MP3 plays on Mac, Linux, OSX, Unix and dozens of handheld devices. We use digital formats to overcome the limitations of their physical counterparts. Your argument shows me that you haven’t read or understood progressive enhancement at all – instead you argue about a world that will never exist as people should not be forced to upgrade just because you are too lazy to build software that is clever and adapts to the environment it is used in.

    There is one question about using PE or not: Do you want to build working interfaces?

    http://dev.opera.com/articles/view/graceful-degradation-progressive-enhance/

  29. 29

    As always another great post at the right time, I’m still learning Javascript and getting into AJAX so this will be a great post to reference back to if I get stuck.

  30. 30

    pretty long article for something that should have been discussed three years ago
    and is already being applied by most web developers
    …still its a good read for those people new to AJAX

  31. 31

    this article was great… however mainly focused on read and update… i rather want to see some tips at better use of Ajax on CRUD (Create, Read, Update and Delete) application

  32. 32

    I finally understand AJAX and its capabilities, Thanks man hope you can make more indept articles like this about more ajax uses.

  33. 33

    Hey Christian,

    Great job on this, quite a wealth of information here.

    Regarding the definition of Ajax and your habitual use of the term in all caps (“AJAX”) — it is my view that Ajax should not be written with all caps as if it were an an Acronym. You mentioned that the “XML” part has been forgotten, which is true, but I think it’s more accurate to say that the entire Ajax methodology has evolved to now represent something more than just what its initials originally meant.

    This is confirmed by Jeremy Keith in what is probably the most important book available on Ajax, “Bulletproof Ajax”, on page 4, where he says:

    “The X for XML is particularly problematic. It implies that XML is a requirement for Ajax applications… Jesse James Garrett later updated his essay, making it clear that Ajax is not an acronym.”

    The “essay” he’s talking about is, of course, the one you linked to under the heading “What is AJAX?”. Keith uses the word “Ajax” (title case) throughout his book.

    Well, I don’t mean to nitpick or anything, but I do think it’s important that the concept of Ajax be better represented. Amazingly, the other day I read a blog post that defined Ajax as a programming language, which could not be further from the truth.

    Thanks again, I’m always looking forward to reading your stuff.

  34. 34

    Hi,

    Most of you know, there was a wonderful article about javascript absense in webdesignerdepot.
    That’ll be a good a read after this.
    http://www.webdesignerdepot.com/2010/02/how-to-plan-for-the-absence-of-javascript/

    :)

  35. 35

    Thanks a lot for this!
    I’m going to spend a lot of time mulling over this and jQuery, since AJAX has always been a bit of a block for me.
    This seems concise and coherent enough to break that block though!

  36. 36

    Yeah I thinks so too.

  37. 37

    Nice Article…love the “$_SERVER[‘HTTP_X_REQUESTED_WITH’]” stuff.

  38. 38

    One of the best articles since your re-design.

  39. 39

    Great article, I learned a lot about AJAX and the examples are perfect. :D

    Just one thing, at the very beginning of the article you say:

    1. The user enters a URI (like http://wait-till-i.com/index.php) into a user agent (usually a browser).
    2.The browser turns this URI into an IP and requests the file located at the URI specified endpoint.
    3. The browser loads the file and, if it recognizes the document type, tries to display it.
    …etc

    Number 2. is techically wrong, who actually turns the URI into an IP is called a DNS server (at least the .com part), not the browser. This is important because we’re talking about the whole client-server architecture when we make http requests. Sorry for being nitpicky, I know it’s meant to be understood as “the browser gets an IP from a URI from somewhere”, but I think it’s important to make it clear.

    Congrats again for this great article!

  40. 40

    very good article! thanks

  41. 41

    While I love most of the articles here on Smashing, I would love to see someone write an article about something Javascript related and actually use Javascript. I know jQuery is great for developers who do not have or don’t want to have a deeper knowledge of Javascript, but lots of developers DO use Javascript and would love to read an article about it.

    Yes jQuery is a great tool for many people and many things, but lets stop treating it as the only way to add Javascript type functions to a website, please.

  42. 42

    Having used Ajax on a variety of different sites and applications, and seen it’s use throughout most of relevent online society, I am a strong supporter of a future that exists almost fully Ajaxified, if you will. I think just as CSS has became a standard, as has EI7+ (see “Google drops EI6″), progressions such as this will also have to take center stage.

    For now, I say we support browsers with JS disabled, just as we supported IE6 until a few weeks ago, but gradually we will have to make a transition to this new technology, and the users will have to adapt as they always have. Old ways of doing things and the methods we use to access them have to change. Imagine a future where we, as designers, must make our code support IE6, JS disability, CSS progressions (for browsers that don’t support CSS2 and 3), and whatever other unforeseen changes to the web that have came about by then. What was a one hour job has now turned into a three. The standards of efficiency to do not support this. Because as it stands, the fields of Desktop Applications and their Web counterparts are blurring, and within a few years, I’d expect some would be indistinguishable. Call me clairvoyant or what you want, but I can’t see the Web of Tomorrow without Ajax-like methods used on the simplest of things.

  43. 43

    Thank you for that great article! I’ve learned a lot! Go on… :-)

    Cheers

    Roh

  44. 44

    @ Bryan, did you read the article?
    eg. “Never rely on AJAX to handle sensitive information, because modern debugging tools allow anyone to see what is happening on the page.”

  45. 45

    Hey Sean,

    Whether you like it or not the legislation is coming so implementing accessible site design now only makes sense. Responses like yours are the reason Web 2.0 is a failure. Certain computer users need more training in etiquette – http://lmgtfy.com/?q=internet+etiquette

  46. 46

    It’s just like Flash, both have the same limitations. Sometimes it faster and easier to use flash, othes AJAX, but both lack semantics, so don’t use them for delivering information, use them to buld apps.

    Flash: Faster, AS3 is absurdly powerfull, cross browser/platform consistency, but: propietary code, dificult DOM integration, compiled files suck!

    AJAX: easy DOM integration, open source, but: JSON is SLOW on many browsers, and you have many cros browser compatibility issues.

    I love them both.

  47. 47

    @Joe (I may not be replying to the correct comment)

    I ABSOLUTELY agree with you!
    If Ajax or Flash is used propperly (for apps) you can rightfully require flash or Javascript enabled. end of story.
    If you are delivering content don’t use them.

  48. 48

    What you are describing there is already existing – it is called the mobile web (which is not “building for iPhone”). If you think it is tough to support a few dozen browsers, try to support multiple OSes and handhelds and browsers in x configurations.

  49. 49

    I made a conscious decision to use jQuery here for one reason: people here use jQuery and if I show them good development practices in the tool they use I won’t get 2132 emails saying “jQuery does this really easily – here’s a plugin”.

    I’ve written a few books on JavaScript (http://beginningjavascript.com for one) but I am happy that people use libraries if all they want to do is implement something rather than writing another JS solution that does not get maintained and fixed when yet another browser quirk comes with a new browser.

    My personal choice is YUI as I work for Yahoo, use it here and have a chance to get things fixed right at the source.

    I am totally with you though – and I said that many a time in my presentations – use libraries, but do understand what they do. If you have no clue about JavaScript and you want to build the new gmail/facebook/twitter you are on very thin ice indeed.

    Thanks for mentioning this, I was really pondering for a long time if I should bite the bullet and use jQuery for this or go for native JS.

  50. 50

    I don’t agree that Ajax is anything close to what Flash is. However I do think that Ajax is a great way to implement web standards friendly user interaction that you cannot accomplish with regular HTML and CSS.

    As far as the whole “the user can disable JavaScript” argument. Really? What kind of user is disabling JavaScript? Developers… I think it’s a smart idea to build an application or website without the requirement of JavaScript, but there are plenty of sites out there that require JavaScript for Ajax purposes.

    I wouldn’t worry about Firebug stuff either. A standard GET or POST is shared with the user and the server. Firebug is just showing that activity. Unless you’re scared of someone sitting in the cube next to you going through your Firebug log, I wouldn’t worry about Firebug at all.

    Good article. I’d like to see a part 2 that explains better practices of building Ajax enabled applications.

  51. 51

    Great article on AJAX and its uses. I want to try out the teach yourself Unobtrusive Javascript boot camp you got; hopefully it’ll give me more insight.

    As always, I find programming from Javascript to PHP much harder than just designing at this point but I have a good grasp on HTML and CSS.

  52. 52

    The point is not that users disable JavaScript out of spite or because of being paranoid (although the noscript http://noscript.net/ use is on the rise) – it is that companies by policy turn off javascript (financial departments in Europe for example) or that you will find company blackberries for example not to support it.

    This is the same flawed argument as saying designers are the only ones who use large font sizes as they are on high resolutions – people who can’t read your content otherwise will have to, too.

    There is an amazing arrogance amongst web developers thinking that you can alter your surfing setup – in a lot of cases people are not allowed to do that or even have no clue whatsoever how to do that. The web is not only for people who love computers much like you are not only allowed to watch TV if you can understand how an LCD works.

  53. 53

    I can agree with Joe and Chris :) . Its all about the effort your willing (required) to do. If you can afford the work, do it! If not, force your users to use your clientlimitations.

  54. 54

    I learned so much that my head is pulsating. Great!

  55. 55

    “1
    2
    3 Let there be AJAX magic
    4

    This would ensure that the link works; if there is a JavaScript error, the browser would simply move on to load and display ajaxcontent.html.”

    Should be, “… on to load and display ajaxtest-fullpage.html.”

    Great article.

  56. 56

    Wonderfull….. Thanks a lot!!

  57. 57

    I’m 3 days late, but good article.

    Actually with jQuery I prefer using preventDefault() over return false; to prevent the elements like buttons and links from triggering their default events when clicked.

  58. 58

    Really useful information about Ajax.
    It simplified the functionality of Webpages.

  59. 59

    Thanks for your time and this great article. This is high-quality information.

  60. 60

    good one ! Thanks for sharing.

  61. 61

    It’s ironic that you refer to netiquette, as you failed at this point:

    Reference Past Communications
    Include a portion of a message that you are replying to when it is relevant.

    That’s what the ‘Reply’ link under each comment is for. :P

  62. 62

    Great one mate. First article I read after 3 years on ajax. I thought I knew when to use but your guidelines are very helpful in design phase.

  63. 63

    Once again what to say?
    A great article…… :)

  64. 64

    Well done! My only critique is that that’s a lot of code compared to a simple load statement. I don’t think all that is necessary every time you use AJAX. And frankly, sometimes you shouldn’t care about the 3% of internet users in the US and 1% in the EU that have javascript disabled because you don’t have time. As the saying goes, we can make it cheap, fast, or good. Pick two. Having said that, writing unobtrusive javascript and AJAX is a beautiful thing.

  65. 65

    Your Ajax definition:
    “After the main HTML document has loaded, AJAX loads content from the server and replaces parts of the document with that content rather than reload the main document. It’s as simple as that.”
    isn’t exactly true, you don’t always “load something from server and replace page’s part with this response”. Ajax is for generic async request and callback to punch when request is finished. What to do in that callback function is your choice.

  66. 66

    really great and useful article .. thanks for sharing ..

  67. 67

    I like this article. A great and useful one.

  68. 68

    Great article! I’m currently a student studying usability in web app design and this is exactly what I needed to be able to include the Ajax features I would like while maintaining usability.

  69. 69

    Hello,
    Thank you for this informative tutorial. I’m having problems with the “AJAX Should Not Break The Web” section, the script loads the section of the file, but what if the file has CSS code? I want to include that CSS code as-well.
    Thank You

  70. 70

    Great article, Chris. Was good to read that I am doing some things in the good way but definitely learned a lot from the article. I mostly used load() for quick loading of html chunks but I will reconsider this in future projects. The whole error handling is very interesting as well so picked up some good stuff from that as well.

  71. 71

    Great thank you very much for all informations. Can I have reference site in ajax.

    Me i advice .envolweb.com and ab-cb.com very fun.

    Thank you for your answers.

  72. 72

    thanks, great job!

  73. 73

    This Article is still one of the best published on SM.

  74. 74

    Great tutorial, thank you

  75. 75

    nice article Thanks.

    For security i think it affects all of JavaScript not just AJAX.

↑ Back to top