Search code examples
jqueryjquery-callback

How do I make jQuery wait for a recursive function to finish?


I'm trying to animate a series of elements, one by one, and then, when all of them have finished animating execute some code.

Here's what I have so far:

// this function is called on mouseleave or a click
function hideItems(){
    var opts = {duration:100, direction:"down", easing:"easeOutExpo"};
    $("li").last().hide("drop", opts, function hidePrev(){
        $(this).prev("li").hide("drop", opts, hidePrev);
    });
    $("ul").css('display','none');// i need this to wait
}

I'm going over all the li elements, and hiding them. I need the ul element hidden after the li elements have been iterated over.

I've tried something along these lines without success:

// this function is called on mouseleave or a click
function hideItems(){
    var opts = {duration:100, direction:"down", easing:"easeOutExpo"};
    $("li").last().hide("drop", opts, function hidePrev(){
        $(this).prev("li").hide("drop", opts, hidePrev);
    }).then(function(){
        $("ul").css('display','none');
    });// this fails with: 'Uncaught TypeError: undefined is not a function'
}

Solution

  • Just use a recursive function that is selecting the last visible li via the :visible pseudoclass:

    var opts = {duration:100, direction:'down', easing:'easeOutExpo'};
    
    function recursiveHide(){
        $('li:visible').last().hide('drop', opts).promise().then(function(){
            if ($('li:visible').length){
                recursiveHide();
            } else {
                $('ul').hide();
            }
        });
    }
    recursiveHide();
    

    Also note that you need to call .promise() on an animated jQuery-Object to gain access to its thenable interface.

    See a fiddle.