Liam
Liam

Reputation: 9855

Optimising jQuery callbacks

I have a function that works as I want it too, only it looks really messy and bloated and so im wondering, is there a better way to code the below?

function careerFlyIn(){

    var distance = $('.row').offset().top,
        $window = $(window);
    var distance = distance - 200;
    var flyInR = $('.path-description');
    var flyInL = $('.path-title');

    $window.scroll(function() {
        if ( $window.scrollTop() >= distance ) {
            $('.career-path .row:first-child').find(flyInL).animate({ 'left' : '0px' } ,400, 'easeOutBounce', function () {  
                $('.career-path .row:nth-child(2)').find(flyInL).animate({ 'left' : '0px' } ,400, 'easeOutBounce', function () { 
                    $('.career-path .row:nth-child(3)').find(flyInL).animate({ 'left' : '0px' } ,400, 'easeOutBounce', function () { 
                        $('.career-path .row:nth-child(4)').find(flyInL).animate({ 'left' : '0px' } ,400, 'easeOutBounce', function () { 
                            $('.career-path .row:nth-child(5)').find(flyInL).animate({ 'left' : '0px' } ,400, 'easeOutBounce', function () {  }); 
                        });
                    });
                });             
            })
            $('.career-path .row:first-child').find(flyInR).animate({ 'right' : '0px' } ,400, 'easeOutBounce', function () {  
                $('.career-path .row:nth-child(2)').find(flyInR).animate({ 'right' : '0px' } ,400, 'easeOutBounce', function () { 
                    $('.career-path .row:nth-child(3)').find(flyInR).animate({ 'right' : '0px' } ,400, 'easeOutBounce', function () { 
                        $('.career-path .row:nth-child(4)').find(flyInR).animate({ 'right' : '0px' } ,400, 'easeOutBounce', function () { 
                            $('.career-path .row:nth-child(5)').find(flyInR).animate({ 'right' : '0px' } ,400, 'easeOutBounce', function () {  }); 
                        });
                    });
                });             
            })
        }
    });

};

Upvotes: 0

Views: 97

Answers (3)

Hashem Qolami
Hashem Qolami

Reputation: 99534

Does this help?

$window.scroll(function() {
  if ($window.scrollTop() >= distance) {

    $('.career-path .row').each(function(i) {
      $(this).find(flyInL).delay(400*i)
             .animate({ 'left' : '0px' } ,400, 'easeOutBounce');

      $(this).find(flyInR).delay(400*i)
             .animate({ 'right' : '0px' } ,400, 'easeOutBounce');
    });
  }
});

Using jQuery .delay() method, Sets a timer to delay execution of subsequent items in the queue.

Upvotes: 1

Arun P Johny
Arun P Johny

Reputation: 388406

Try

function animate($rows, idx, selector, animate) {
    $rows.eq(idx).find(selector).animate(animate, 400, 'easeOutBounce', function() {
        if (idx < $rows.length - 1) {
            animate($rows, idx + 1, selector, animate)
        }
    });
}

var $rows = $('.career-path .row');
animate($rows, 0, flyInL, {
    'left' : '0px'
})
animate($rows, 0, flyInR, {
    'right' : '0px'
})

Note: Not tested

Upvotes: 0

iCollect.it Ltd
iCollect.it Ltd

Reputation: 93601

Create a list of the items to animate and use async recursion on the list.

function animate(elements, callback)
{
    if (elements.length){
        elements.eq(0).find(flyInR).animate({ 'right' : '0px' }, 400, 'easeOutBounce');
        elements.eq(0).find(flyInL).animate({ 'left' : '0px' }, 400, 'easeOutBounce', function (){
            // Do the remainder of the list (after first item)
            animate(elements.slice(1), callback);
        });
    }
    else {
        // All done, call the final callback
        callback();
    }
}

animate($('.career-path .row'), function() 
{ 
   // do something when all items have finished animating
});

You can apply this pattern to any set of similar async operations. In this example the left and right animations run in parallel but only one triggers the next event (left in this case).

Upvotes: 2

Related Questions