pause and resume array of setTimeouts

471 views Asked by At

I found good answers here to how pause and resume a setTimeout. Very useful.

But how can I resolve a similar issue but with an array of setTimeouts? I need a click on any element to pause and then resume after the click on the setTimeout in the array where it was stopped last time and so on.

My code so far works except the fact that it resumes the timeout sets at the beginning. Is there a way to check on which setTimeout element the pause was made and resume at this point again? I presume the second definition of var fadeTrailer has to subtract those elements that have been activated already. Somehow it should work with the index. But I don’t know how. Thanks for help!

//automatic fader
fadeTrailer = [

        setTimeout( function() {
            //first action
        }, 9500),

        setTimeout( function() {
            //second action )   
        }, 19000),

        setTimeout( function() {
            //third action  
        }, 32000),

];

$("#Trailer").on( 'click.resumeTrailerFade', function() { resumeTrailerFade(); } ); 

function resume

function resumeTrailerFade() {

$.each( fadeTrailer, function(i, timer) {
    clearTimeout(timer);
} );

fadeTrailer = [

    setTimeout( function() {
        //first action
    }, 9500),

    setTimeout( function() {
        //second action )   
    }, 19000),

    setTimeout( function() {
        //third action )    
    }, 32000),          
];

};

I hope this is the right way to do this here. Good but also difficult forum for beginners ;-) What I did now is that I declared a timeline variable at the start as:

var fadingTimeline = [

setTimeout( function() {
    //anything
fadeState = 0;
}, 9500),

setTimeout( function() {
    //anything
    fadeState = 1;  
}, 19000),

setTimeout( function() {
    //anything
    fadeState = 2;  
}, 32000),

];

Then I put in the first appearance:

//automatic fader
                    fadeTrailer = fadingTimeline;

                    // interrupts automatic fader and restarts it (to give user time to stay on each work when clicking elements in it)                     
                    $("#Trailer").on( 'click.resumeTrailerFade', function() { resumeTrailerFade(); } ); 

Then for the resumeTrailerFade() I tried to grep the array of the elements by index using the fadeState variable like:

function resumeTrailerFade() {

$.each( fadeTrailer, function(i, timer) {
    clearTimeout(timer);
} );

//filter timeline array for already passed setTimeouts
fadeTrailerRemain = $.grep( fadingTimeline, function(n) {
    return ( n.index < fadeState );
});

}

I know the last part is silly code, just for explaining my idea. Is there someone out there able to follow my idea and put it into real working code? Would be so awesome!

2

There are 2 answers

0
Stephen Thomas On BEST ANSWER

Edited: Somehow I missed Igoel's comment where he says the same thing. Sorry about that.

There is no simple way to query a timeout to see how much time has elapsed. You can store the start time of a timeout in a separate variable and then calculate the difference explicitly.

FWIW, note that JavaScript timeouts are not necessarily accurate as JavaScript is a single-threaded execution environment.

6
Garavani On

the code you showed me, is in fact awesome for me! I changed it a little (as I don’t need buttons etc.) So I declared the variables this way:

var first = function() {
  // do the first thing
}
var second = function() {
  // do the second thing
}
var third = function() {
  // do the third thing
}
var fourth = function() {
  // do the fourth thing
}
var fifth = function() {
  // do the fifth thing
}
//…

var timer;
var timeFrames = {
  95: [first],
  190: [second],
  320: [third],
  420: [fourth],
  510: [fifth],
  //…
};
var timerPaused = false;   
var maxStep = 510;
var stepSize = 100;
var currentStep = 0;

var intervalTimer = function() {

if ( !timerPaused ) { currentStep ++; }
if ( !!timeFrames[currentStep] ) {
    if ( !!timeFrames[currentStep][0] ) {
        ( timeFrames[currentStep][0])(timeFrames[currentStep][1] );
    }
}
if ( currentStep >= maxStep ) {
    timer = window.clearInterval(timer);   
    currentStep = 0;
  } 
}  

On the right place inside a function where I needed it so start automatically I put:

//automatic trailer fader                       
timer = window.setInterval( intervalTimer, stepSize );
// interrupts automatic fader 
// restarts it (to give user time to stay on clicked elements within the fading content)
$("#Trailer").on( 'click.resumeTrailerFade', function() { 
  timerPaused = true;
  setTimeout( function() { timerPaused = false; }, 15000 ); // give some extra time when anything clicked before resume automatic fade again
} );

Then finally to abolish all I put:

//stops automatic trailer fader definitely without resume
timerPaused = true;
window.clearInterval(timer);
$("#Trailer").off( 'click.resumeTrailerFade' );

Works perfect even I am a aware that for you profs there might be still some strange things in it. So feel free to comment about it. Every help to improve is welcome!

Thank you so far for great help, without it I would never have made it.