JorgeLuisBorges
JorgeLuisBorges

Reputation: 538

Immediately stop a setTimeout loop without finishing current cycle

Im creating a user operated random selector. Users hit a button and the system selects two random results (which will be videos).

The page will then alternately highlight two random results - they user can hit the button again and they can choose the video they want.

Its all working quite nicely, but the alternating highlighting is done with a setTimeout loop which finishes its current cycle, rather than stopping immediately.

how would I get it so that when the user presses the 'select' button the flit function stops immediately - not when the current loop is over?

Here's the fiddle

http://jsfiddle.net/zandergrin/tmwst5z9/4/

ps - apologies, but this is a work in progrees - I know there's a few messy bits in here... var interval = 0;

function random() {
    // create the array
    var posts = ["post 1", "post 2", "post 3", "post 4", "post 5", "post 6", "post 7", "post 8", "post 9", "post 10"];
    var results = posts

    // Shuffle array
    .sort(function () {
        return .5 - Math.random()
    })

    // Get first 2 items
    .slice(0, 2);
    var post1 = results[0];
    var post2 = results[1];

    // add them to the DOM
    $('#res1').html(post1);
    $('#res2').html(post2);

    // loop it
    interval = setTimeout(random, 100);

}

function start() {
    // Hide the start button
    $("#start").css("display", "none");
    $("#stop").css("display", "block");
    // Start the randomizer
    random();

}


function stop() {
    // Hide the stop button and stop the random() timeout
    clearTimeout(interval);
    $("#stop").css("display", "none");
    $("#select").css("display", "block");

    // set the inital background colour
    $("#res1").css({'background': '#123','color': '#fff'});
    $("#res2").css({'background': '#eee','color': '#000'});

    //create a function to flick between items
    function flit() {
        //color the results
        setTimeout(function () {
            $("#res1").css({'background': '#eee','color': '#000'});
            $("#res2").css({'background': '#123','color': '#fff'});
        }, 800);

        //colour again after a delay
        setTimeout(function () {
            $("#res1").css({'background': '#123','color': '#fff'});
            $("#res2").css({'background': '#eee','color': '#000'});
        }, 1600);

        //loop it
        timer = setTimeout(arguments.callee, 1600);
    };
    //run the flick function
    flit();

}


function select() {
    // stop thie flit function - doesnt stop immediately!
    clearTimeout(timer);
    $("#select").css("display","none");
    $("#refresh").css("display", "block");
}

function refresh() {
    location.reload();
}

Upvotes: 0

Views: 815

Answers (2)

dman
dman

Reputation: 11064

In addition to @sholanozie answer, I would recommend placing those setTimeout's in a array(ie arrayOfTimeouts), and then:

function select() {
    // stop thie flit function - doesnt stop immediately!
    arrayOfTimeouts.forEach(function(setTimer) {
        clearTimeout(setTimer);
});

Upvotes: 1

soulprovidr
soulprovidr

Reputation: 754

Your problem is in the flit() function - you need to assign references to the setTimeout calls so you can call clearTimeout on them. Right now, you're stopping flit() from being called in the select() method, but the two timers are still queued to execute in the future.

Upvotes: 3

Related Questions