AjaxPatterns
This is the original book draft version for the Progress Indicator Ajax pattern, offered for historical purposes and as an anti-spam measure.
You're probably better off visiting the Live Wiki Version for Progress Indicator instead, where you can make changes and see what others have written.

Progress Indicator

Activity, Feedback, Hourglass, Meter, Progress, Waiting

Goal Story

Reta has made a sale and is typing in the details. She completes the credit card details and proceeds down the page to delivery dates. Meanwhile, the status area has appeared beside the credit card details. While she completes the rest of the form, the status area continues to update with the current verification stage - initially "submitted", then "responding", then "verified".

Problem

How can you provide feedback while waiting for server responses?

Forces

  • Ajax Apps often make “XMLHttpRequest Call”s to query and update the server.

  • To provide good feedback, you should provide an idea of which page elements are affected by any update.

  • Users like to feel in control, and that control is taken away when the user's waiting for a response. It's not just the delay that should be minimised, but the perceived delay.

Solution

Indicate the progress of server calls. You can't always reduce delay, but you can include a Progress Indicator to ease the pain. A Progress Indicator helps maintain the user's attention, improves the user's understanding of how the system works, and also communicates that the system is still alive even if a response hasn't yet occurred.

The Progress Indicator is typically introduced to the DOM once n ??? call begins and removed when the call has returned. The easiest way to detect the call has returned is in the XMLHttpRequest callback function. An indicator need not relate to a single call - it can show progress for a sequence of related calls.

Sometimes it's a “Popup” element instead of a new element directly on the page. A popular idiom is a small opaque “Popup” on the corner of the page showing just a word or two ("Saving ...", "Loading ...").

For shorter delays, typical Progress Indicators include:

For longer delays, the following can be used:

  • A meter showing how much progress has been made.

  • An estimate of time remaining.

  • A sequence of messages indicating what's happening at present.

  • Content that's engaging but not directly related to the progress, such as Tip of the Day or a canned graphical depiction of system activity.

Of course, you can combine these approaches. Generally speaking, some form of unobtrusive animation is worthwhile in any Progress Indicator, because it at least tells the user something's happening, even if progress is temporarily stuck. In addition, longer delays should usually be completed with a visual effect such as “One-Second Spotlight”, since the user's focus has probably moved elsewhere by that stage.

Note that one form of indicator to avoid is changing the cursor. Many traditional GUIs switch over to a "rotating hourglass" or related icon during delays. That's probably inappropriate for Ajax, because it's something the actual browser software will do too, e.g. while loading a new page, so it's likely to create confusion.

Decisions

What sort of Progress Indicator will you use?

A well known set of guidelines is summarised in Jakob Nielsen's Usability Engineering. As a quick summary:

  • If the delay is less than 0.1 second, the user will feel it's instantaneous. No feedback necessary.

  • If the delay is between 0.1 second and 1 second, the user will notice it but it won't break their flow of thought. No feedback necessary.

  • If the delay is between 1 and 10 seconds, the user's flow of thought is interrupted as they await the response. Basic feedback necessary, i.e. an indication that a delay is occurring. Ajax examples include animated icons and simple text messages.

  • If the delay is greater than 10 seconds, the user will want to proceed onto other tasks. Detailed feedback necessary. Ajax examples include progress meters and messages showing current state.

The precise figures may require some adjustment and I suspect a web context requires them to be dropped a bit. For example, users will probably want some feedback for a delay of 0.5 seconds rather than 1 second, and more detailed information is probably appropriate after 2-3 seconds rather than 10 seconds.

Bruce Tognazzini also offers some useful guidelines.

How will you provide feedback during longer delays?

For longer delays, you need to help the user track how much progress has been made, typically using a progress meter that shows percent complete. Sometimes, a long delay can come from a single “XMLHttpRequest Call”, because although the network transfer may be quick, the back-end processing might not be. For example, the call might trigger a major database operation.

You probably won't get any useful information about its progress by monitoring the responseText component of XMLHttpRequest. The responseText tends not to populate in a linear fashion, for two reasons. Firstly, there are usually back-end calculations involved, during which no output can occur. Thus, output tends to happen in bursts, or all at the end. Secondly, the output is often compressed using the standard HTTP content encoding facility, and the compression algorithm will force data to be outputted in bursts. The XMLHttpRequest's readyState also won't tell you very much. For reasons described in “XMLHttpRequest Call” and “HTTP Streaming”, tracking support is inconsistent across browsers.

So if you can't monitor the progress of an XMLHttpRequest Call, how can you help the user understand how much progress has been made? One thing you can do is “Guesstimate”: predict the total time, and start running a timer to monitor how long since the call began. The prediction of total duration need not be hard-coded every time; you could have the application track download times and reflect them in the estimates next time round. This sort of thing is quite common, e.g. in the download time estimates given by a web browser.

If you want more accuracy, introduce a second monitoring channel. While the primary request takes place, a sequence of monitoring requests are issued to ask the server for a progress estimates. For example, the server might be looping through 1000 records, running a transformation on each of those and saving it to the database. The loop variable can be exposed in a second “Web Service”, so that the browser monitoring can inform the user.

Not all Progress Indicators concern a single “XMLHttpRequest Call”. Indeed, those requiring a progress meter are longer processes, likely incorporating several “XMLHttpRequest Call”s. There, you do have much better opportunity for real-time progress monitoring - each time a call returns, further progress has occurred. In a simple model, you can show progress is 50% complete when 2 of 4 calls have returned.

Real-World Examples

Amazon Diamond Search

Amazon Diamond Search is a “Live Search” that shows a Progress Indicator while updating the number of results (Figure 1.48, “Amazon Diamond Search”). The indicator is a simple animation depicting a block moving back and forth with a "LOADING RESULTS" message. A nice design feature is the placement of the Progress Indicator on the result status. It replaces the results once searching has begun, and remains until the new results are shown. Thus, it serves to invalidate the previous results at the start and focuses the user's attention on the new results at the end.

Figure 1.48. Amazon Diamond Search

Amazon Diamond Search

Amazon Zuggest

Like Amazon Diamond Search, Francis Shanahan's Amazon Zuggest is a “Live Search” that shows a Progress Indicator while searching is underway. This time, the indicator is a text message such as "Searching...beat". It occupies its own fixed area, and when searching is complete, morphs into another message: "Done!".

Protopage

Protopage is an Ajax portal. Each time you make a change, such as “Drag-And-Drop” a “Portlet”, an opaque "Saving ..." message appears in the bottom-right corner. This is a good model for a “Fat Client” application, where server synchronisation should be unobtrusive.

TalkDigger

TalkDigger simultaneously calls several search engines, showing a Progress Indicator on each result panel. It's interesting because it shows how to use Progress Indicators in a “Multi-Stage Download” situation.

Kayak

Kayak illustrates how to handle a longer delay. When you search for a trip, it creates a result page with several forms of progress feedback:

  • Number of search results so far.

  • A progress meter that fills up from left to right.

  • A sampling of websites that are being searched.

  • A nice graphic depicting a retro, pre-electronic, airport display board. Initially, each character is random. As the search of a particular website proceeds, the random characters are replaced with the correct character for that website. Meanwhile, the characters that remain unpopulated continue to flicker from one random character to another. Once all characters have been corrected and the website name displays correctly, the display changes to random again and starts revealing another website. all This is an excellent example of a graphic that is engaging and at the same time indicative of the processing that's occurring.

The Pick'em Game

The Pick'em Game is an office pool game, allowing you to predict this week's football winners. It provides a form where you declare a prediction and confidence level for each game. Above the form is a small instruction message, and when data is being saved, it morphs into a Progress Indicator. The indicator is a spinning disk and an "Updating Pick Sheet" message. (The demo page doesn't perform a real remote call.)

Code Refactoring [AjaxPatterns Progress Indicator Demo]

This demo introduces a progress display to the Basic Sum Demo. It's a simple animated GIF that shows up while waiting for the sum to return.

An Img tag for the animation is present in the initial HTML:

    <img id="progress" class="notWaiting" src="progress.gif">

The script will toggle the image's CSS class, depending whether we're in waiting mode or not. The stylesheet ensures it's visible when waiting, and invisible when not:

    .waiting {
      visibility: visible;
    }

    .notWaiting {
      visibility: hidden;
    }

With the styles defined, the script just has to flick the CSS class back and forth as the waiting status changes:

    function submitSum() {
      $("progress").className = "waiting";
      ...
    }

    function onSumResponse(text, headers, callingContext) {
      $("progress").className = "notWaiting";
      ...
    }

Related Patterns

A Progress Indicator is usually presented as a “Status Area”.

The Progress Indicator can sometimes reside in a “Popup”.

Once a long process has completed, use a “One-Second Spotlight” to point this out to the user.

Sometimes you don't know how long a task will take or how much progress has been made so far. A sloppy guess is better than nothing at all, so make a “Guesstimate” of the progress.

When a call comes in, you need to close off the Progress Indicator. There's a risk here that you'll end up with a single function that mixes Progress Indicator stuff with the logic of processing the response. Separate that logic using “Distributed Events”.

Metaphor

Banks and post offices often use ticket-based queueing systems, showing the number that's currently being served.

Want to Know More?

Live Wiki Version for Progress Indicator