Reputation: 4873
I have a Javascript function (Not jQuery) that animates a box opening or closing. The problem is that I close the box, run some code that changes the content, and then reopen it.
Now the "problem" is that the rest of the code is too fast, and so it never even manages to close, let alone reopen. I could make the animation not be allowed to run again internally unless the last one was finished, but this would limit it if I say, were to want to run it twice on two different objects.
So what's the best method to prevent this? My thought was possibly a timeout that says to wait before running the animation, but that seems hacky, an I wasn't sure if there was a better solution?
Thanks.
function animate(boxID, step, limit, speed){
// Add timeout property to animate function/object if it doesn't exist already
if(animate.timeout == undefined) animate.timeout = 0;
// Clear the current timeout
clearTimeout(animate.timeout);
// Initialize box and current box height
var box = document.getElementById(boxID);
var h = box.clientHeight;
// Check if we want the step needs to be changed to pos/neg based on which direction is wanted to be going
if(h < limit && step < 0 || // Positive
h > limit && step > 0){ // Negative
step *= -1;
}
// If the step is positive, then we need to be below the limit, or if negative, then greater than the limit
if((step > 0 && h <= limit - step) || (step < 0 && h >= limit - step)){
// Set new height
box.style.height = h + step + "px";
// Start new timeout
animate.timeout = setTimeout(function(){ animate(boxID, step, limit, speed, 1); }, speed);
}
else{
box.style.height = limit + "px"; // Set to the exact height
}
}
Upvotes: 0
Views: 1965
Reputation: 4783
You could achieve this with a callback. Your animate
function gets a plus parameter, a function to call when the animation is ready:
function animate(boxID, step, limit, speed, onReady){
When the animation is done, you call it:
else{
box.style.height = limit + "px"; // Set to the exact height
if (onReady) { onReady(); }
}
You also want to forward the callback to the timeout call:
setTimeout(function(){ animate(boxID, step, limit, speed, 1, onReady); }, speed);
So, you can call the function for multiple boxes like this:
animate(box1_id, close_step, close_limit, close_speed, function () {
// now box1 is closed, put something in. then:
animate(box1_id, open_step, open_limit, open_speed, null);
});
// then the same for box2, etc…
This way box1 and box2 will close simultaneously, and only reopen after the thing have been put inside.
Also, you can't store the timer on the function, because now it's running on multiple boxes. So you may store it on the boxes, or a separate place instead. For example create an object outside of the function and put all the boxes' timers in that:
var timeouts = {};
timeouts[box1_id] = setTimeout(…);
Upvotes: 1