1

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!

Garavani
  • 755
  • 1
  • 13
  • 28
  • 1
    when you create a timeout you can save the timeout in an variable like: var t1 = setTimeout(); ....then you could save them in an array and add a flag if paused – Jacob A. Dec 03 '13 at 08:58
  • I think you are asking how to pass fadeTrailer index to resumeTrailerFade? Can you post your markup? – Sumit Dec 03 '13 at 11:58
  • Also, take a look a this. http://stackoverflow.com/questions/3969475/javascript-pause-settimeout – Sumit Dec 03 '13 at 12:07
  • Yes I saw this answer and I would be able to use it for my purposes if there would be only one setTimeout but I have an array of setTimeouts here so I am asking how to adapt a similar for this task. Thanks so far for your interesting comments! I will try and learn about those flags. – Garavani Dec 03 '13 at 13:34
  • I added a new code in my original question at the end – Garavani Dec 03 '13 at 14:19
  • I wonder why you would want to use an array of TimeOut? It seems like doing something like this: " http://jsfiddle.net/76yJK/15/ "; would suffice in the example you gave. It just sets an interval and checks the value it's currently at – Marvin Brouwer Dec 03 '13 at 16:06
  • This seems very very interesting! I will study it carefully and try to use it! Thank you very much, Marvin, for the tip! – Garavani Dec 04 '13 at 07:15
  • No problem, I did make it quite rushed. You could make it "neater" by putting this all in an object and creating a function to add the timeFrames for example. – Marvin Brouwer Dec 04 '13 at 09:53

2 Answers2

0

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.

Stephen Thomas
  • 13,843
  • 2
  • 32
  • 53
0

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.

Garavani
  • 755
  • 1
  • 13
  • 28
  • Looks fine, Personally I would change these `var timeFrames = { 95: [first], //… }; if ( !!timeFrames[currentStep][0] ) { ( timeFrames[currentStep][0])(timeFrames[currentStep][1] ); }` to these `var timeFrames = { 95: first, //… }; if ( !!timeFrames[currentStep] ) { ( timeFrames[currentStep])(timeFrames[currentStep][1] ); }` Because you don't use the arguments And I wonder why you clear the timeOut at the end, this already happens when the maxstep is reached. – Marvin Brouwer Dec 04 '13 at 15:44
  • Thanks, I changed the variables, so ended up with var intervalTimer = function() { if ( !timerPaused ) { currentStep ++; } if ( !!timeFrames[currentStep] ) { ( timeFrames[currentStep] )( timeFrames[currentStep][1] ); } if ( currentStep >= maxStep ) { timer = window.clearInterval(timer); currentStep = 0; } } Correct? 2) Do you mean the window.clearInterval(timer); in the third part of code? It is for interrupting before it ended (in another place where the automatic fader has to be killed definitely to not confuse with functions outside – Garavani Dec 04 '13 at 17:00
  • You're almost there, This will work however lets say you are at step 190, this has the value "second" so you are calling "second(second[1])" wich results in "second(undefined)" The numbers in square brackets were because the framevalues used to be "[,]" meaning it was an array I hope I've explained this a bit clear, I'd advise you to take a look at json notation and javascript arrays. My point is that you could change '( timeFrames[currentStep] )(timeFrames[currentStep][1]);' to: '( timeFrames[currentStep] )();'. – Marvin Brouwer Dec 05 '13 at 08:45
  • For me as a designer (artist :-)) it’s hard to follow all the explanations but I will try to study more about arrays. Thanks for your great help anyway. I newly changed the code, works great! – Garavani Dec 05 '13 at 08:52
  • I see, you're a designer. Have you considered using a library like [jQuery](http://jquery.com)? It seems to me you are trying to fade out an element, jQuery is very useful for things like this. – Marvin Brouwer Dec 06 '13 at 08:44
  • Indeed jQuery is my absolute favorite toy! I am trying my best to understand some things and I have to say it is fun. Also because of the great community outside there! – Garavani Dec 06 '13 at 10:47