3

I have a product listing page and want to load up a detail view for each product via AJAX and display it within the page. I have a more complex set of conditions I want to set up animations with, but I'll keep it simple here.

Basically, upon click, I want to run the AJAX request and simultaneously animate (in some cases, a series of animations...) the content wrapper open and show a 'loading' state. Once BOTH of those are done, I then want to drop in, and animate the content. I thought jQuery Deferred Objects would be the way to go, but I don't have a good grasp on them and my attempts haven't gotten me where I want to be.

I tried something like this:

var dfr = $.Deferred();
dfr.then(function() { return wrapper.fadeIn(5000); });

$.when(dfr, $.get('/detail.html'))
.then(function() {
    console.log('All done, run additional animations...');
});

dfr.resolve();

... but it gets triggered as soon as the AJAX request is done, even if the animation is still running.

I also tried this:

var dfr = $.Deferred();
dfr.then(function() { return wrapper.fadeIn(5000); });
dfr.then(function() { return $.get('/detail.html'}) });
dfr.done(function() { console.log('All done, run additional animations...'); });
dfr.resolve();

... but that just executes all of the then/done calls simultaneously. I also tried switching in pipe in place of the then calls, to no avail.

I would love to understand Deferred Objects (is this even an appropriate/intended use for them..?) and, of course, how I can achieve my goals for this page. Any help or tips are much appreciated....

Chris Forrette
  • 3,194
  • 2
  • 28
  • 37
  • +1, I've never used the Deferred functionality but it looks very interesting. Look at http://stackoverflow.com/questions/4869609/how-can-jquery-deferred-be-used It looks like the second example of the accepted solution is probably what you need. Something like: $.when( $.getJSON('/some/data/'), $.get('template.tpl') ).then(function( data, tmpl ){ // code to call upon completion of both }); – Dan A. Mar 30 '12 at 03:15

3 Answers3

3

This page has an example of doing exactly what you're talking about: http://www.erichynds.com/jquery/using-deferreds-in-jquery/

It's more like this:

function animateStuff() {
   var dfd = $.Deferred();
   wrapper.fadeIn(5000, dfd.resolve); 
   return dfd.promise();
}

$.when( animateStuff(), $.get("/whatever") )
   .then(function() {
      // do something really great
})
Jamund Ferguson
  • 16,721
  • 3
  • 42
  • 50
1

jQuery collections are observable (they have a promise method). So you can do this very simply:

$.when( wrapper.fadeIn( 5000 ), $.get( "/whatever" ) ).done(function() {
    // animation and ajax request complete
});

If you need to chain animations on various elements, use .pipe():

function chainAnim() {
    return wrapper.fadeIn( 5000 ).promise().pipe(function() {
        return internal.fadeIn( 1000 );
    });
}

chainAnim().done(function() {
    // wrapper than internal faded in
});

You can still use $.when, of course:

$.when( chainAnim(), $.get( "/whatever" ) ).done(function() {
    // animation and ajax request complete
});
Julian Aubourg
  • 11,346
  • 1
  • 29
  • 29
0

It may help to register a handler when your ajax requests have finished:

$('.content').ajaxStop(function() { 
   animateContent();
});

More on .ajaxStop() here

Marty Cortez
  • 2,325
  • 1
  • 17
  • 22