Search code examples
jqueryfunctiondelay

Queuing a function amongst Jquery animation


Hi I am trying to create an layered image effect but I am having trouble queueing a function along with jquery animation.

Basically I need to hide all of my .bar divs then execute the function after which will make them fadeIn one at a time. I need to do it this way as there will be multiple images and this effect will be what creates the transition between them.

<div class="container">
<div class="image">
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
    <div class="bar">
    </div>
</div>

and the css is like this

.container {width:700px;height:400px;margin:0 auto;background:#FF0;}
.image {background:green; width:700px; height:300px; }
.bar { height:300px; width:50px; background:orange; float:left;}

and the javascript/jquery is like this

$(function(){

var i = -1;

function fading(){
    function fader(){
    setTimeout(function () {          
          i++;                    
          if (i < 15) {          
             $('.bar:eq(' + i + ')').fadeIn('200');
             fader();           
          }                       
       }, 100)
    }
    fader()
}

$('input').click(function(){

    $('.bar').hide().queue(function(){
                    fading()
                    $('this').dequeue();
                    });
});


});

If anyone has ideas on how this can be done differently or achieved in the way I have laydd out that would be great


Solution

  • You can't use the animation queue in this way because your .queue call is getting mixed in with all the fadeIn() calls and won't wait until after those as they are using the animation queue also. You could create some separate queue and use that, but that is probably not worth it.

    Why not just have the fader() function trigger your next action when it finishes with the 15 layers?

    Or, you can pass a callback function into fader() which it can call when it's done with the 15 layers?

    I don't get exactly what you're trying to do, but you can kick off another function in here when you're done fading in the 15 layers (see where I added the else):

    function fading() {
        var cntr = -1;
        function fader() {
           setTimeout(function () {          
              cntr++;
              if (cntr < 15) {          
                 $('.bar:eq(' + cntr + ')').fadeIn('200');
                 fader();           
              } else {
                 // done fading in the 15 items, now you can call some other function
                 // here to start the next operation
                 afterFade();
              }
           }, 100);
        }
        fader();
    }
    

    Try simplifying your click code to this:

    $('input').click(function(){
        $('.bar').hide();
        fading();
    });
    

    .hide() is synchronous (it doesn't use the animation queue) so you can just call fading() right after it.

    You also have to reinitialize your cntr variable on the second call to fading(). In my code example above, I changed the name of the variable from i to cntr and moved it's definition and initialization into the top of the fading() function so it is automatically initialized on each subsequent call.