Thursday, September 2, 2010

jQuery: Simple Ajax Loading Screen

So another thing jQuery made easy for me this week was a loading screen. What I wanted was a loading screen to be displayed for all Ajax calls. I started preparing for this by thinking of the states I'd need to watch and then the search and replace that wouldn't work quite right to ensure all of my Ajax would kick off the loading screen, and then turn it off again when the call was successful.

Well, it seems in jQuery this is pretty easy. Check the code below, as it is all it took.

busyDialog = {
 
 init: function () {
  var el = $(document.createElement('div')).attr('id', 'busyDialog')
   .css({
    'width': '100%',
    'height': '100%',
    'background-image': 'url(lib/images/ajax-loader.gif)',
    'background-position': 'center',
    'background-repeat': 'no-repeat',
    'position': 'fixed',
    'z-index': '9999',
    'display': 'none',
    'cursor': 'progress'
   });
  
  $(el).ajaxStart(function(){
      $(this).show();
   });
  $(el).ajaxStop(function(){
      $(this).hide();
   });
  $('body').prepend(el);
 }
}

Personally, I have this thing loaded into a widget class.  When the app instantiates I call the init method and I'm set.  This would be sickeningly easy to prototype into jQuery as a plugin.

What happens in the code above is that we create a new div and place a loading animated gif in the center of it.  You can get an animated gif over at AjaxLoad.  The div is created at 100% width and height so that the use cannot interact with the screen while the loading dialog is active.  The loading div is initially invisible.  Two event handlers (ajaxStart and ajaxStop) are employed, which is where the real helpfulness of jQuery comes in.  jQuery allows us to specify global handlers (here showing and hiding the loading div) for all Ajax requests.  We are still able to have our custom success handlers for each individual Ajax call.  Wicked.

The final step is to throw the div into the DOM.  We do this as the first child of 'body'.

4 comments:

  1. Very nice, how can you create a "mask"?
    So you have a kind of blurred background like blockUi does?

    ReplyDelete
  2. I always add a div at a higher z-index and set the opacity low. That mask then prevents interaction with the primary page at the lower z-index.

    ReplyDelete
  3. What if you have multiple ajax calls, but you only want for one specific ajax call to use this. How can I use this (in the right way)?

    ReplyDelete
  4. You can manually activate the busyDialog() for any of your ajax calls by calling it before posting, and turning it off in your callback. I usually add it to all calls for consistency using the ajaxStart and ajaxStop global event handlers as above. Most ajax calls are so fast in my app I never even see the dialog, but a person with a poor connection or lots of data sees it when necessary.

    ReplyDelete