views:

438

answers:

3

I'm working on some out transitions on image when a user presses the button to move to the next image. When there are multiple images next to each other that are very narrow, those images will all transition at the same time. So I check the width on the images and add the thin ones to an array and then run the transition on each object in the array. I wanted to create a little delay between the animation of each image in the array so I'm trying to run my jQuery.animate after a 1 second timeout.

Here's the ways I've tried to get the timeout working without success:

1.

for (i=0; i < set.length; i++) {
    if (i != 0) {
     setTimeout(function() { set[i].transitionOut($('#gallery'), 562) }, 100);
    } else {
     set[i].transitionOut( $('#gallery'), 562 );
    }
}

2.

for (i=0; i < set.length; i++) {
    if (i != 0) {
     function tempTransition() {
      set[i].transitionOut( $('#gallery'), 562 );
     }
     setTimeout(tempTransition, 100);
    } else {
     set[i].transitionOut( $('#gallery'), 562 );
    }
}

3.

for (i=0; i < set.length; i++) {
    if (i != 0) {
     setTimeout('function() { set[i].transitionOut($("#gallery"), 562) }', 100);
    } else {
     set[i].transitionOut( $('#gallery'), 562 );
    }
}

transitionOut():

jQuery.fn.transitionOut = function(parent, height) {
    this.animate({
     height: '0',
     top: height + 'px'
    }, function() {
     $(this).remove();
    });
}

I got it working using CMS's closure example. But, now I'm running into a new problem. The transition only happens with the second image. When there is three images it will go animate image 1, delay, animate image 2, animate image 3. There's no delay between 2 and 3.

Here's the new code:

for (i=0; i < set.length; i++) {
    (function(i) {
     if (i != 0) {

      function tempTransition() {
       set[i].transitionOut( $('#gallery'), 562 );
      }
      setTimeout(tempTransition, 200);
     } else {
      set[i].transitionOut( $('#gallery'), 562 );
     }
    })(i);
}
A: 

Using timeout is a tricking thing when it comes to timed-animation/effect.

I didn't test your code but by browsing it, I noticed you are using setTimeout without anything to clear them.

What happens when users trigger events during the 'delay'? You have got to implement something to manage that as well.

Sorry I do not have an answer for you now, perhaps when I have more time later or someone comes out with a more elegant solution.

o.k.w
A: 

jquery fadeOut http://docs.jquery.com/Effects/fadeOut lets you create a callback, which is a function you can run when the fadeOut finishes. So if you want you can chain the fades together so when one finishes it calls the next one. If that is not what you are looking for I may be misreading your question.

Also, in example 3, I think you want to to write it like this and not have a function definition passed to the setTimeout as that won't do anything.

setTimeout('set[i].transitionOut($("#gallery"), 562)', 100);
jarrett
A: 

By looking at your code I think you have yet another closure problem, perhaps the most common problem I've seen when people work with loops and nested functions.

The i variable which your setTimeout callback function refer, is the same (because JavaScript has only function-scope, not block-scope), and by the time those functions are executed asynchronously, the loop have already finished, and the i variable will contain set.length - 1 for all cases where setTimeout is used.

As usual, try to capture the i variable using another closure:

for (var i=0; i < set.length; i++) {
  (function (i) {
    if (i != 0) {
        setTimeout(function() { set[i].transitionOut($('#gallery'), 562) }, 100);
    } else {
        set[i].transitionOut( $('#gallery'), 562 );
    }
  })(i);
}
CMS
Thank. That helped me get over the first hurdle. :)
Jonnie