Question

I'm using OpenX at work, and one of my boss requirements is a expandable banner. For that (and made a horrible simplification of the whole story) I made this script.

function retro(){
  var acs = jQuery('#trial_center').height() - 5;
  jQuery('#trial_center').css('height', acs + 'px');    
}
jQuery(document).ready(function(){
  jQuery("#trial_center").mouseover(function(){
   setTimeout("jQuery('#trial_center').css('height', '500px')", 1000);                      
})
jQuery("#trial_center").mouseleave(function(){    
  var c = 89;    
  while (c > 0) {  
    setTimeout("retro()", 1000);   
    c--;
  }
 })
}); 

The problem I have is in the mouseleave event: the original idea was to made this loop several times (89 times), and each time, decrease the height of the banner until it get his original size. Why this? Because my boss want an "effect", and this effect must be in sync with the customer's flash. The problem is that instead of decrease his size progressively, apparently the script made all the operations an "after" the sum of setTimeout calls, updated the page. So, the result is exactly as the banner shrinks one time from the expanded size to the original size.

I don't know what is wrong with this, or if exists other more intelligent solution.

Any help will be very appreciate.

Thanks in advance

Was it helpful?

Solution

Your loop setting the timeout is just setting 89 timers for one second later than the loop runs, and the loop will run in milliseconds — so they'll all fire about a second later. That doesn't sound like what you want to do.

Two options for you:

1. Use animate

jQuery's animate function seems like it does what you want. You can tell jQuery to animate the size change, and you tell it how long to take to do so:

jQuery('#trial_center').animate({
    height: "500px" // Or whatever the desired ending height is
}, 1000);

That will animate changing the height of the container from whatever it is at the point that code runs to 500px, across the course of 1,000 milliseconds (one second). Obviously you can change the duration to whatever you like.

2. Set up the timer loop manually

If for whatever reason you don't want to use animate, you can do this manually (of course you can; jQuery can't do anything you can't do yourself, it just makes things easier). Here's how to set up a timer loop:

jQuery("#trial_center").mouseleave(function(){    
  var c = 89;

  // Do the first one right now, which will schedule the next
  iteration();

  // Our function here lives on until all the iterations are
  // complete
  function iteration() {
    // Do one
    retro();

    // Schedule this next unless we're done
    if (--c > 0 {
      setTimeout(iteration, 100); // 100ms = 1/10th second
    }
  }
});

That works because iteration is a closure over c (amongst other things). Don't worry about the term "closure" if it's unfamiliar, closures are not complicated.


Separately: You're using mouseover to set the height of the trial_center element a second later; you probably wanted mouseneter rather than mouseover. mouseover repeats as the mouse moves across it.


Off-topic:

It's best not to use strings with setTimeout; just pass it a function reference instead. For example, instead of

setTimeout("retro()", 1000);

you'd use

setTimeout(retro, 1000); // No quotes, and no ()

And for the other place you're using, instead of

setTimeout("jQuery('#trial_center').css('height', '500px')", 1000);

you'd use

setTimeout(function() {
    jQuery('#trial_center').css('height', '500px');
}, 1000);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top