Multiple AJAX loading indicators
One of my biggest issues in the latest version of this site was how to get multiple AJAX loading indicators working on one page.
Getting a single AJAX loading progress indicator into your web application can be a relatively straightforward task thanks to a simple piece of Javascript from Thomas Fuchs:
// lang javascript
Ajax.Responders.register({
onCreate: function() {
if($('busy') && Ajax.activeRequestCount>0)
Effect.Appear('busy',{duration:0.5,queue:'end'});
},
onComplete: function() {
if($(’busy’) && Ajax.activeRequestCount==0)
Effect.Fade(’busy’,{duration:0.5,queue:’end’});
}
});
However, from what I could tell (and subsequently experienced) is that by using this code, you are limited to only one progress indicator per page. This caused me problems, as on my Archives page I have a progress indicator for when the application is fetching monthly archives, but also for the live search function that appears on every page. Whenever I activated an AJAX request by using either function, both the loading indicators would be displayed, thus confusing the user.
So, how is it possible to get around this? Well, from what I can see it’s impossible to pass the ID of a loading indicator into Thomas’ script. The trick is to move the hiding and displaying of the indicators into function calls for the “onComplete” and “onCreate” events within your specific AJAX request:
// lang javascript
function getMonthResults(vars)
{
var url = 'archives_month.php';
var pars = 'm=' + vars;
var target = 'monthResults';
var myAjax = new Ajax.Updater(target, url, {
asynchronous:true,
onCreate: function() { showLoader('mArchive_loader'); },
onComplete: function() { hideLoader('mArchive_loader'); },
parameters: pars,
method: 'get'
});
var element = document.getElementById(target);
}
The two events now call separate functions that pass the ID of the loading indicator, allowing you to define which indicator to hide or display:
// lang javascript
function showLoader(loader)
{
new Effect.Appear($(loader), {duration: 0.5});
}
function hideLoader(loader)
{
new Effect.Fade($(loader), {duration: 0.5});
}
Simple as that. Now, I’m not saying that this is the “offical” or “ideal” way of going about this task, but it’s the one that worked for me. You can also extend the show and hide functions, to add an effect to your target container by passing the target as well as the loader to the function. For example, I have used the following as my show and hide functions:
// lang javascript
function loadingRequest(loader, target)
{
new Effect.Appear($(loader), {duration: 0.5});
$(target).style.display = "none";
}
function completedRequest(loader, target)
{
new Effect.Fade($(loader), {duration: 0.5});
new Effect.BlindDown($(target));
}
This means that when the AJAX request has completed, the results will slide into view using the “BlindDown” effect from the Scriptaculous library. A nice added extra.
Technorati Tags: AJAX, Javascript
Before using
My favorite of the three features I mentioned above is snippets. This is one of TextMate’s features that I took some time to really get used to. I’m one of those people who tends to retype code over and over again, just because I don’t want remove my fingers from the keyboard to select and copy a block of code. Snippets allows me to assign a keyword to code that I regularly have to retype, then all I need to do is type this keyword and hit tab. The code magically appears and even lets you tab between input locations within it. This has been an amazing time saver, TextMate already has hundreds of snippets pre-bundled.