Yamaha32088
Yamaha32088

Reputation: 4163

setTimeout timing is off on the first .each() element

I am having an issue trying to get the timing consistent with the following code. Basically as soon as the page is loaded it should immediately start looping through the li elements and highlighting them, removing the previously highlighted element. It works for the most part but the very first element seems to take about twice as long before it starts looping and then the rest seem to be perfectly timed. I have included a fiddle here

This is the code I am using to loop

function addColorClass(boom) {
    $(boom).addClass('li-color');

    if($(boom).is(':last-child')) {
        $(boom).prev().removeClass('li-color');
        setTimeout(function() { cycleFeatures(); $(boom).removeClass('li-color'); }, 1000);
    } else {
        $(boom).prev().removeClass('li-color');
    }

}

function cycleFeatures() {
    i = 1;
    var timer = new Array();
    jQuery('.features').first().addClass('li-color');
    $('.features').each(function($) {
        i++;
        var thiz = this;
        timer[i] = setTimeout(function() { addColorClass(thiz); }, i * 1000);   
    });
}

cycleFeatures();

It is an infinite loop so when it reaches the last li element it will recall the cycleFeatures() function. You can see in the fiddle that the first element seems to stay highlighted about twice as long as all the other elements. I have been banging my head against the wall trying to figure it out, to no avail. Can someone please help me figure out how to keep the highlighted duration consistent.

Upvotes: 0

Views: 63

Answers (4)

010 Pixel
010 Pixel

Reputation: 165

You have set setTimeout twice and that might be one of the reasons for this.

Here is the working fiddle: http://jsfiddle.net/6gzhLqzz/7/

function cycleAll(active) {
    if ( !active ) active = 0;
    var total = jQuery(".list2 .features").length;
    setTimeout(function(){
        prev = active - 1;
        if ( prev < 0 ) prev = total-1;
        jQuery(".features").eq(prev).removeClass("li-color");
        jQuery(".features").eq(active).addClass("li-color");
        active++;
        if ( active >= total ) {
            active = 0;
        };
        cycleAll(active);
    },1000);
}

cycleAll();

Upvotes: 0

mash
mash

Reputation: 15229

Here's a different way to approach the problem that should be easier to understand than your solution, and should work more consistently.

var moveLight = function($ele) {
    $(".li-color").removeClass("li-color");
    $ele.addClass("li-color");
};

var idx = 0;
var loop = function() {
    $loopEles = $("li");
    moveLight($loopEles.eq(idx));
    idx = (idx + 1) % $loopEles.length;

    setTimeout(loop, 1000);
}

loop();

http://jsfiddle.net/6gzhLqzz/6/

Upvotes: 2

Barmar
Barmar

Reputation: 781013

The problem is that you initialize i to 1. The loop increments i, so the first timeout is 2 seconds, the next one is 3 seconds, and so on. So there's a 2 second delay the first time.

Simply change it to

var i = 0;

You should also use the var keyword to make it a local variable. It doesn't need to be global.

FIDDLE

Upvotes: 0

Jagadeesh
Jagadeesh

Reputation: 188

setTimeout() function is put in a queue even when it needs to execute after 0 ms. Once the regular flow is completed then the browser starts executing the queue from setTimeout

line 1

setTimeout(0)

line 2

setTimeout(20)

the execution series would be

line 1 line 2 settimeout(0) settimeout(20)

hope this helps

Upvotes: 0

Related Questions