views:

44

answers:

3

Scenario:

I want to create a jQuery controllable jackpot "spinner" that will rapidly sequence a number of random images through a div before settling on one, with the delay interval between each equal but changeable. For mockup purposes, I'm simply changing CSS color classes to a box, although in the final I'll use background images.

I thought this would be a no-brainer to do with a loop. I'm sure there's a more efficient way to do this, but guessed the below would work fine. However, I discovered I have no way to control the CSS color swap speed. This whips through the color class changes instantly and just shows the last one. What I'd like is a delay where indicated.

jQuery delay() doesn't seem to work when chained with addClass(), though it works fine with effects. So I tried using window.setTimeout, but as far as I can see, in this context it requires a kludgey function call. The code as written below executes all the function calls after the loop has run. Is this a closure issue? Don't want to use setInterval because these will be limited iterations.

Thanks for any advice!

for (var j= 9; j >= 0; j--) {
    $('#box1').attr('class', 'boxes');   // strips all current classes, replaces them with class 'boxes', which has general CSS characteristics
    var numRand = Math.floor(Math.random() * 6); 
    var randomClass = colorArray1[numRand];  //  pull random class from an array of six choices
    $('#box1').addClass(randomClass);

    // Everything above here works fine, would like loop delay here
    // Tried using straight-up setTimeout -- doesn't appear to like loops
    window.setTimeout(outerFunc, 1000);  
};

function outerFunc() {
    alert('nobody here but us chickens!'); 
};
A: 

If you want to use .delay() with a method like .addClass(), you can add it to the queue with jQuery's .queue() method.

$('#box1').delay(1000)
          .queue(function( nxt ) { 
               $(this).addClass(randomClass); 
               nxt(); // allow the queue to continue
          });

Otherwise, if I get what you want, you could multiply the 1000 ms for the setTimeout() by the current value of j, so that each time the duration increases.

window.setTimeout(outerFunc, (1000 * j));  
patrick dw
A: 

setTimeout and setInterval work differently in javascript to the way you want to use them.

Both functions take the function that you pass in and attach them to the window DOM object. Then, after the delay you have passed in has passed, and when there is no other script currently running, they get called from the window object.

To get the functionality you are after, you will need to convert your code so that the jQuery addclass call is inside the function you are passing to setTimeout.

Gus
A: 

Perhaps recursion would work?

// this code is not tested
var j = 9;
function myFunc() {
    // code here
    j--;
    if(j >= 0) setInterval(myFunc, 1000);
}

I haven't used the queue class in jQuery myself (first I've heard of it, but it sounds cool). That might be the better answer, but this should be a decent alternative if the queue doesn't work as expected.

UPDATE: I just noticed that in your code it looks like you are expecting setTimeout to work like Thread.Sleep in .Net. setTimeout doesn't work that way. It works more like Thread.Start where your code continues on as soon as you call it.

Brian
thanks Brian, I'm going to try the queue method first, but will try recursion if that doesn't work.
boomturn