Foolproof AJAX Progress Indicator

wait30Bruce Williams is right on in Avoiding AJAX Faux Pas where he lists four inviolable conditions your AJAX code must meet. The first two conditions address the need to show (then hide) a visual progress indicator to let the user know that a network operation (XHR) is occurring. These are important rules. Unfortunately, the implementation he presents is fraught with difficulties.

Bruce’s solution is comprised of a Ruby function showing_progress which he suggests you use in every single call to (insert_html, replace_html, replace) to wrap any options you’d normally pass to those routines. The showing_progress routine adds :loading and :complete handlers that will show, then hide an element with id ‘progress’ on your page.

The solution is kind of elegant and it works as advertised but I ran into a few problems as I got deeper into my app:

  1. I forgot to call showing_progress in new invocations of insert_html, replace_html, replace — as a result I didn’t get progress indication in those cases
  2. The solution works only for Ruby RJS code — if you write JavaScript that calls Ajax.Request and Ajax.Updater then the solution of course doesn’t help.
  3. The solution ruthlessly overwrites any :loading and :complete handlers you’ve defined in your options

How about a solution that works for both Ruby and JavaScript? It’d be nice if it didn’t rely on the programmer remembering to call it everywhere? It’d be even nicer if it didn’t interfere with your application’s :loading and :complete handlers.

Here’s the solution I’m using. I don’t recall where I first saw it but I’m pretty sure I didn’t invent it. I see Nicky Peeters was suggesting a similar thing over a year ago. Just put this code in application.js:

    1 Ajax.Responders.register({
    2 onCreate: function() {
    3  if($('progress') && Ajax.activeRequestCount>0)
    4  Effect.Appear('progress',{duration:0.5,queue:'end'});
    5 },
    6
    7 onComplete: function() {
    8  if($('progress') && Ajax.activeRequestCount==0)
    9  Effect.Fade('progress',{duration:0.5,queue:'end'});
   10 }
   11 });

And stick something like this in your layout:

    1                 <span id='progress' style='display:none;'>
    2                     <img src='/images/busy.gif'>
    3                 </span>

And you’ll have one less worry in your life.

About these ads
This entry was posted in AJAX, RJS templates, Ruby on Rails, script.aculo.us. Bookmark the permalink.

2 Responses to Foolproof AJAX Progress Indicator

  1. Geof Dagley says:

    I would add one suggestion to this. Instead of putting the span with the progress indicator directly in the layout, it should be added dynamically with Javascript. This will keep the indicator from showing up when styles are turned off and keep the markup cleaner. You would need some sort of class indicator on the element where this span should be inserted, though.

  2. Bill Burcham says:

    Good point Geof. Thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s