views:

925

answers:

2

Here's my dilema. I have 2 animations that need to run sequentially.

The first animation runs on a group of elements acquired through jQuery's siblings() function.

The second animation runs on a single element. (The one upon which siblings() was called.) This needs to take place after the first animation has finished.

If I don't use queue() or a callback after the first animation, they run simultaneously.

If I do use queue() or a callback after the first, then the second animation ends up running numerous times (once for each of the siblings).

So how do I successfully queue an animation to run ONCE after a group animation?

(I found a hack that works, but I'm hoping there's a proper way to accomplish this.)

Thanks.

Simplified example:

<html>
<head>
<title>tester page</title>
<style> 
 <!--
.fadebutton, .resizebutton {
cursor: pointer;
color: white;
margin: 10px 0 10px 0;
background: blue;
padding: 2px;
display: table;
}
.box {
width: 100px;
height: 100px;
background: orange;
margin: 10px;
float: left;
}
 -->
</style>
<script src="http://www.google.com/jsapi"&gt;&lt;/script&gt;
<script type="text/javascript">google.load("jquery", "1.3.2");</script>
<script type="text/javascript"> 
$('document').ready(function() {
$('.resizebutton').toggle(  function() { $(this).parent().animate({width: '+=50px', height: '+=50px'}, 1000); },
        function() { $(this).parent().animate({width: '-=50px', height: '-=50px'}, 1000); });
$('.fadebutton').click(function() {
 var $theBox = $(this).parent();
 $theBox.siblings().fadeOut(1000, function() { $theBox.find('.resizebutton').click(); });
});
});
</script>
</head>
<body>
<div>
<div class='box'><div class='fadebutton'>Fade</div><div class='resizebutton'>Resize</div></div>
<div class='box'><div class='fadebutton'>Fade</div><div class='resizebutton'>Resize</div></div>
<div class='box'><div class='fadebutton'>Fade</div><div class='resizebutton'>Resize</div></div>
<div class='box'><div class='fadebutton'>Fade</div><div class='resizebutton'>Resize</div></div>
<div class='box'><div class='fadebutton'>Fade</div><div class='resizebutton'>Resize</div></div>
</div>
<div>
<div style="clear: both; padding: 0 0 10px 0; ">Clicking the 'resize' button triggers a toggle that increase or decreases the box's size.</div>
<div>Clicking on the 'fade' button fades the box's siblings, then triggers the 'resize' button in that box. Trouble is that the 'resize' gets fired as many times as there are siblings.</div>
</div>
</body>
</html>
A: 

You should be able to trigger the second animation by passing in a callback to the first animation so you're notified it completes.

Christopher Stott
Unless I'm misunderstanding you, I stated in my question that doing that causes the callback to run multiple times (once for each sibling). I want it to run only once.My example has a callback which runs multiple times instead of once. Was this what you meant by 'passing in a callback to the first animation'?
patrick dw
+4  A: 

Does your hack look something like this?

$('.fadebutton').click(
function() 
{
 var $theBox = $(this).parent();
 var doneOnce = false;
 $theBox.siblings()
        .fadeOut(1000, 
             function() 
             { 
                  if(!doneOnce)
                  {
                  doneOnce = true;
                  $theBox.find('.resizebutton').click(); 
                  }
             }
 );

Here is the working code.

Ryan Lynch
Ah, that looks better than mine. Mine was simply to have an animation that does essentially nothing running parallel to the siblings() animations. So I was able to do the callback off that single animation. I like yours better. So it sounds like this is a (minor) shortcoming of jQuery, which is fixed only via hacks like the one you gave. Not a big deal, I guess. Thanks for the help!
patrick dw
Eh, If I was going to extend the `$.animate()` function to add a flag to play once I would probably implement in a similar way.
Ryan Lynch