views:

156

answers:

6

Once all three loads are complete...

$("#sidebar a").live("click", function(e){ 
    $(this).addClass("selected loading");
    $("#conceptual").load(conceptualUrl, null, function(){ $(this).removeClass('loading').show("fast");  });
    $("#development").load(developmentUrl, null, function(){ $(this).removeClass('loading').show("fast"); });
    $("#operational").load(operationalUrl, null, function(){ $(this).removeClass('loading').show("fast"); });
});

How can I remove the loading class from the link once ALL THREE loads are complete?

$("#sidebar a.loading").removeClass("loading");

Thanks!

A: 
var to_be_loaded = 3;
var loaded_so_far = 0;

$("#sidebar a").live("click", function(e){ 
    $(this).addClass("selected loading");
    $("#conceptual").load(conceptualUrl, null, function(){ checkLoad(); $(this).removeClass('loading').show("fast");  });
    $("#development").load(developmentUrl, null, function(){ checkLoad(); $(this).removeClass('loading').show("fast"); });
    $("#operational").load(operationalUrl, null, function(){ checkLoad(); $(this).removeClass('loading').show("fast"); });
});

function checkLoad() {
    loaded_so_far ++;
    if(loaded_so_far == to_be_loaded) $("#sidebar a.loading").removeClass("loading");
}
Makram Saleh
A: 

Set a global variable to 3 before you start the loads; have each callback decrement it by 1 and then check to see if it's zero - if so, that callback removes the loading class.

Amber
A: 

The quick and dirty way would be to track the loading with a variable that counts up each time one of the functions is run:

$("#sidebar a").live("click", function(e){ 
    var loadCount = 0;
    $(this).addClass("selected loading");
    $("#conceptual").load(conceptualUrl, null, function(){ 
        loadCount++;
        doSomething();
    });
    $("#development").load(developmentUrl, null, function(){ 
        loadCount++;
        doSomething();
    });
    $("#operational").load(operationalUrl, null, function(){ 
        loadCount++;
        doSomething();
    });

    function doSomething()
    {
        if (loadCount == 3)
        {
            $(this).removeClass('loading').show("fast");
        }
    }
});

Once the loadCount reaches the maximum, execute the doSomething() function.

Soviut
I think you may have a problem there. if (doSomething == 3). I assume you meant if (loadCount == 3). But, at any rate, the magic number 3 isn't really best in a conditional -- better to give it a name, and use that in the conditional, e.g. `if (loadCount === maxLoad)`
Jonathan Fingland
thanks, fixed the code.
Soviut
+2  A: 

Try the following:

$("#sidebar a").live("click", function(e){ 
    $(this).addClass("selected loading");
    var num_loaded = 0;
    var num_to_load = 3;   

    function show() {
       num_loaded++;
       if (num_loaded === num_to_load) {
         $(this).removeClass('loading').show("fast");
       }
    }

    $("#conceptual").load(conceptualUrl, null, show);
    $("#development").load(developmentUrl, null, show);
    $("#operational").load(operationalUrl, null, show);
});

The show function maintains visibility of num_loaded and num_to_load through closure. Since the functions are all the same, it also made sense to re-factor the anonymous callbacks into a single named function.

Jonathan Fingland
Extra } on line 10. Otherwise excellent - thanks!
Rick
@Rick thanks, fixed
Jonathan Fingland
A: 

Something a little fancy that you can reuse throughout the site. Should work fine.

var Loader = function () {
    var options = arguments[0];
    this.actions = options.actions;
    if (!this.actions || !this.actions.length) {
        throw 'Loader: FATAL ERROR: Nothing to do. All your base are belong to us.';
    }
    this.onComplete = options.onComplete || function () {};
    this.next();
}

Loader.prototype = {
    next: function () {
        if (this.actions.length) {
            var action = this.actions.pop(), me = this;
            $(action.selector).load(action.url, action.data, me.next);
        } else {
            this.onComplete();
        }
    }
}


var loaders = []; // or maybe  asingle variable you overwrite every time, I don't know

$("#sidebar a").live("click", function(e){
    $(this).addClass("selected loading");
    loaders.push(new Loader({
        actions: [
            {selector: "#conceptual", url: conceptualUrl, data: null},
            {selector: "#development", url: developmentUrl, data: null},
            {selector: "#operational", url: operationalUrl, data: null}
        ],
        onComplete: function () {
            $("#sidebar a.loading").removeClass("loading");
        }
    }));
});

Of course you can modify the Loader to make it more powerful; add methods to enqueue new actions or drop the one currently running, maybe make it more general. Mine is just a quick and dirty example :)

Kaze no Koe
Whoa! You've got me thinking...
Rick
Good, I hope something comes out of it :)
Kaze no Koe
+2  A: 

Just use jQuery.loadAll... oh wait, it doesn't exist? Here you go:

$("#sidebar a").live("click", function(e){ 
    var side = $(this);
    side.addClass("selected loading");

    $.loadAll( {
        $(conceptual): conceptualUrl,
        $(development): developmentUrl, 
        $(operational): operationUrl
    },
    function() {
        side.removeClass('loading').show("fast");
    });
});

jQuery.fn.loadAll = function(urls, callback) {
    var loaded = urls.length;
    jQuery.each(urls, function(i, url) {
        this.load(url, function() {
           loaded--;
           if(!loaded && callback)
               callback();
        });
    });
};
joshperry