Solved

setTimeout does not respect its delay

Posted on 2000-03-11
26
454 Views
Last Modified: 2008-03-10
I have written a script that is used like a countdown, that when it reaches zero (0), it launches a parent.location.href=URL in an other frame.

It works great if i let it go by itself.

But i also have a Skip button that let me go to the next URL without waiting the countdown to reach zero (0)

When i hit SKIP, the page skip immediatly to the next one, but the countdown goes from 1x speed to 2x speed, and it is not coded like that...
i really dont understand..

Hope you can help, i will give you a piece of the script to think about it...

----------Javascript bit-----------

stopp=0
play=0
limit=31

function begintimer(){

if (!document.images)
return

if (limit == 0){
extract(cursec);
window.location="Javascript:++fois;Skip()";}
}
else{

cursec=limit-1

if (stopp == 0) {setTimeout("down()",1000)}

}}
//  stopp=0 means that the countdown is in progress (no pause)-->
</script>


<script>
<!-- times by the setimeout, gets the limit variable toward zero (0)
function down(nummm){
--limit
extract(cursec)
begintimer()
}//-->
</script>

<script>
<!-- when the countdown reaches 0, reset and set to a new limit diffrent to each displayed page

function restart(num){
stopp=0
limit=num
begintimer()
}//-->
</script>

<script language=JavaScript>
<!-- to skip from a page to an other 9 pages here is 1 as example
fois = 0
Pose = 0
Second = 0

function Skip(txt){

if (play == 0) {
play=1
fois=2
Skip()
}

if (fois == 1) {
play=0
parent.tv.location.href="tv1.htm";Pose = 0;Pause();restart(32);
hiLite('D1','Queue1');hiLite('D2','Queue2');hiLite('D5','Queue2');hiLite('D6','Queue2');
hiLite('img01','empty');hiLite('img02','Up1a');hiLite('img03','Up2');}<!-- Black en Loop! -->
// -->
</script>

<script language=JavaScript>
<!-- to pause any page
function Pause(txt){
if (Pose == 1 && play == 1){parent.tv.location.href="pause.htm";stopp = 1;}
if (Pose == 2 && play == 1){Pose=0;Skip();}
}//stop hiding -->
</script>

<script language=JavaScript>
<!-- visual countdown with preloaded images
function extract(s){
if (!document.images)
return
if (s<=9){
document.g.src=c0.src
document.images.h.src=eval("c"+s+".src")
}
else {
document.images.g.src=eval("c"+Math.floor(s/10)+".src")
document.images.h.src=eval("c"+(s%10)+".src")
}  }
//stop hiding -->
</script>

<body onload=begintimer()>
<a href="Javascript:Skip()">
</body>
0
Comment
Question by:njacques
  • 14
  • 11
26 Comments
 
LVL 2

Expert Comment

by:squint
ID: 2609252
You need to provide a global variable to store the "timeout ID", then use this variable with the clearTimeout function.

Without sitting down and going through all of the code, I can't tell for sure what the problem is.  But I believe that the "stopp" variable is being reset to 0 when the next item loads, thus the "down" function still gets called.

Use a "timeout ID" like this to "unregister" a function.

var timeoutID = setTimeout("down()",1000);

....

//  To unregister the timeout
clearTimeout(timeoutID);



0
 
LVL 8

Expert Comment

by:jbirk
ID: 2609491
FOr something like this I would use setInterval() and clearInterval()...  Also the code in whole can use some cleaning up.  If you want I can rewrite it for you (but later today... I don;t have time now).

-Josh
0
 

Author Comment

by:njacques
ID: 2609702
I know the code is not at is best... im working on that, but i want it to work properly before modifying some things and store a backup.

I am interested in your setInterval()/clearInterval method... please direct me to such an example that i could strip to my needs!

Thakns
0
 
LVL 8

Expert Comment

by:jbirk
ID: 2609865
Well, I don't know of a place off hand that uses this...  I can provide an example myself though...

Let's take your beginTimer function first (I'm removing the other code for simplicity...):
var itimerID;
var count = 10; // or whatever you want it to start at...
function begintimer()
 {itimerID=setInterval("down()",1000);
 }

function down()
{count = count - 1;
 if (count == 0)
  {clearInterval(itimerID);
   // now do whatver happens when it reaches 0...
  }
}

-Josh
-Josh
0
 

Author Comment

by:njacques
ID: 2609931
I have played with your settings and mine...

i have also stripped all the esthetic code so you and i can figure out the problem...

i invite you to visit:

http://pages.infinit.net/njacques/vmc/test.htm

this is the address of the stripped version of the page containing only the countdown!

Still going faster & faster

NJ
0
 
LVL 8

Accepted Solution

by:
jbirk earned 100 total points
ID: 2610701
The problem was because you were starting another cycle of count downs in the case when it reached 0.  If you look through your code you'll see that it checks for the case of limit==0 amnd if it's true it restarts the timer.  But that function continues to call begintimer regardless of the value of limit...  so here we've just introduced an additional loop...

Anyway, it also went from 11 to 1, I thought maybe you wanted 10 to 0... so I changed it a bit. Here's the modified functions:

stopp=0
play=0
limit=11

function begintimer(){
setTimeout("down()",1111);
}

function down(){
--limit;
extract(limit);
if (limit == 0)
 {if (play == 0) {restart(11);}
  if (play == 1) {window.location="Javascript:++fois;Skip()";}
 }
else
 begintimer();
}

function restart(num){
stopp=0;
limit=num;
begintimer();
}

-Josh
0
 

Author Comment

by:njacques
ID: 2610752
Your solution is great.. now when the coundown is left alone even for a great lenght of time, it stays ok...

But my problem is that the script loads pages on another frame when it reaches zero, but the user can also manually skip to the next one.. i have updated my test.html so that it reflects this...

So in automatic mode it works and in manual, it still screws up...

I think you are on the right track..

Thanks a lot if you would take a little more of your time!

http://pages.infinit.net/njacques/vmc/test.htm

0
 

Author Comment

by:njacques
ID: 2610757
I would also like to know if you have an easy way to implement a pause funtion???
0
 
LVL 8

Expert Comment

by:jbirk
ID: 2611044
I'm not 100% sure what you are trying to do with the loading of pages but this line:
if (play == 1) {window.location="Javascript:++fois;Skip()";}
Is not good.  It should be more like:
if (play == 1) {++fois;Skip();}
Then do the changing of the location in skip...
Likewise, this:
<a href="Javascript:++fois;Skip()">
Should be:
<a href="Javascript:;" onClick="JavaScript:++fois;Skip();return false;">

-Josh
0
 

Author Comment

by:njacques
ID: 2612135
The window location= must be a remnent of an other function i ripped...

im not at home right now, but i will see if it works as soon as i get there, i will confirm you if it works!
0
 

Author Comment

by:njacques
ID: 2614123
I have updated the page to reflect your proposed changes.

http://pages.infinit.net/njacques/vmc/test.htm

But it seems the Skip function still mess up the delay... i have checked all the code. but i wonder why the restart function works when it reaches zero and not when it is manually skipped...

What do you think?
0
 
LVL 8

Expert Comment

by:jbirk
ID: 2614454
When you call skip(), it is calling restart which starts a whole new cycle.  So the code is getting called twice now, thus speeding it up...  So something else needs to be done...  I'm not sure what the 'play' variable is supposed to do.  It's currently not function for anything.  Perhape you can rewrite to use it like this:

function down(){
--limit;
extract(limit);
if (play == 0)
 {if (limit == 0)
    restart(11);
   else
    begintimer();
 }
else
 {play = 0;
  ++fois;
   Skip();
 }
}

Then for the link use:
<a href="JavaScript:;" onClick="play=1;return false;">
Be sure to leave the javascript:; in there.  It should be there for the href...

This way a flag is set which alerts the current countdown to interrupt itself and start over.  Instead of starting a new countdown on top of the previous one.

-Josh
0
 

Author Comment

by:njacques
ID: 2614631
What if i was to build several begintimer() functions : begintimer1() ; begintimer2() ect...

and they would have all there attach variable and there Settimout with a specficic timeouID each ( timeouID1 ; timeouID2 ect..)

Would the independant functions influence each other, or being that there variables are not linked in any way they would go freely as each other.

I know this is not the best way to optimize a code but im desparate to make it work... here is in a nutshell what the project is about:

1- Countdown from 30 to 0 when zero reached, reset to 30 and loop and loop and loop

2- until the user press skip, then a new page and countdown arrives and when it reach 0 goes to the other page,but the user can manually skip to step 3

3- a new page arrives and a new countdown that arrives and when it reach 0 goes to the other page, manual skip possible too!

4- new page / new countdown... lets limit ourself to 2 linear elements when the last step reaches zero, it jump to step one to start all over




0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 8

Expert Comment

by:jbirk
ID: 2615773
It should be workins ok as it is now.  I don;t there's any need to have multiple countdowns going.  Plus since you're using setTimeout and not setInterval, there is no need for clearTImeout.  All clearTimeout does is stop a timeout from occuring if it's scheduled to occur.  If the timeout has triggered and the code for it is being executed already, calling clearTimeout has no effect since there is no timeout to clear...

If the way that it is working now is not how you want it to function, I guess I don't understand what you want clearly.

On #2 you state "a new page and countdown arrives", I'm not sure I understand what that means.  And how does the user manually skip to step three?

Please elaborate...  I know it probably seems obvious to you what you want, but I'm just not getting it...

-Josh
0
 

Author Comment

by:njacques
ID: 2617125
OK... il try to be more specific...

Step one  corresponds to a page in a side frame that is loaded by the main frame containing the countdown. In step one, the counter is from 30 to 0 and loops to infinity 30-0 30-0. until the user presses a button (image map) that will load a new page in the side frame (step 2) the main frame stays the same, but the countdown is reset and starts with a new start value. when the counter reaches zero, a third page is loaded in the side frame and the coundown in the main frame resets and starts to a new value again (step 3). when the step3 countdown reaches zero, it goes back to step one that loops.

The manual skip enables the user not to wait my predefined timing, he doesnt like the page, he can skip to the next one..

The site in fact is like a big webpages slideshow.
with a delay between each page. if the user want to go to the next page, he skips...

The fact that the step one loops helps the preloading of image and the user can read the content of the main frame before he manually wants to start the show...

Hope this clears up some things...
0
 
LVL 8

Expert Comment

by:jbirk
ID: 2618679
OK, I think I understand a little better now....

It's looks like you've been working on this a bit (the test site has changed:)

Anyway, is this like what you are looking for?

state=0; // the current slide state 0 is the main start page...
         // noything happens until state becomes 1
ticks=30; // the number of ticks left in the current countdown
play=1;  // signifies that the countdown is playing.  If it's set to 0 the countdown is interrupted.

function begintimer(){
setTimeout("tick()",1111);
}

function tick(){
ticks--;
extract(ticks);
if (!play) return; // if the countdown is stopped...
if (ticks == 0) // reached end of countdown... check state
 {if (state == 0) {restart(30);} // kkep looping in state 0
  else if (state == 1)
   {restart(25); // restart with however many seconds are needed for this slide
    top.slideframe.location="slide1.html";
      state++;
   }
  else if (state == 2)
   {restart(35); // restart with however many seconds are needed for this slide
    top.slideframe.location="slide2.html";
      state++;
   }
  else if (state == 3)
   {restart(45); // restart with however many seconds are needed for this slide
    top.slideframe.location="slide3.html";
      state++;
   }
  else if (state == 4)
   {restart(30); // reset to original slide and loop infinitely
    top.slideframe.location="original.html";
    state=0;
   }
 }
else
 begintimer();
}

function restart(num){
ticks=num;
begintimer();
}


To stop and start the timer, set play to 0 and 1, respectively.  To start the slide show, set state=1.  To advance a frame immediately, set ticks to 0 (it may take a second but it will still shortcut.

I think that should work for your needs.

Good luck!
-Josh
0
 

Author Comment

by:njacques
ID: 2620262
Your new version works a lot better than my new version. Seeing what you have done, i think you understand what i want to accomplish.

But there is still a problem that i am sure that is very easy to fix, i tried but it messed up more that it helped.

The countdown in automatic mode works Great. (to bypass the loop i would put state=1 in variable declaration header)

but when i got back to state=0, i got stuck in the loop. i have put ticks=0 in my Skip link but 0 - 1 = -1 and my extract to timer function does not support negatives so i added this:

if (ticks >= 0)extract(ticks);

but i think its a sign that the skip does not work...

I am very pleased of the worked you have done and hope we can make it work.. i think we are near completion. Thank you to sticking to this!

http://pages.infinit.net/njacques/vmc/test.htm
0
 
LVL 8

Expert Comment

by:jbirk
ID: 2620710
Ahh...  I think skip should be set to change ticks to 1.  This way it decrements it to 0 when the next tick occurs...  That should fix that problem.

Also just to be safe the change the biginning of ticks to:
ticks--;
if (ticks < 0)
 ticks = 0;

This removes the possibility of a negative screwing up the rest of the function.

-Josh
0
 

Author Comment

by:njacques
ID: 2621400
Your recommended changes have been made!

But when i skip from the loop, i go to step 1, if i skip again i go to step 3... i really dont know why.. but it seems to be a variable that gets its way over step 2...

Help!
0
 
LVL 8

Expert Comment

by:jbirk
ID: 2622301
OK, I looked at what you had.  You add code which incremented the state when it went sub zero...  I fixed that, and modified the link javascripts a touch...  Check out the entire thing here: (too much code to post)
http://aegis.mcs.kent.edu/~jbirk/EE/timer/timer2.html
You can just view the source from there.

Note that when you first start it, it goes to state 1 and then state 2 right away.  This is what it's supposed to do.  After that it only goes one state at a time.

-Josh
0
 

Author Comment

by:njacques
ID: 2624133
Your changes are terrific, i can now skip and fall in the right state. from 0 to 1, from 1 to 2, from 2 to 3, from 3 to 4, but in 4 to 0, automatic mode works (when ticks gets to zero he begins the 5 second loops) but if from state4, i manually skip, i end up in state 1 (10 sec coutndown)

I have tried several thing, but since step 4 put state to 0 and skip takes state 0 to state 1. i'll never be able to get back to the 5 second loops.
0
 
LVL 8

Expert Comment

by:jbirk
ID: 2628257
It seems that you've made some modification which caused this.  Go back to my version.  You will see that it doesn't do that.  Also you changed the html links.  They should look like this:
<a href="javascript:;" onClick="if (state == 0) state = 1; ticks=1;">Skip to the next page</a><br>
<a href="javascript:;" onClick="play=!play; if (play) tick();">Pause/Resume counter</a>

And you sitll have not changed this line:
if (ticks < 0){ticks = 0;++state;}
to:
if (ticks < 0) ticks = 0;
If you incerement the state here it will cause problems.

-Josh
P.S.  Sorry for the delay.  I was locked out of my e-mail AND EE yesterday :(
0
 

Author Comment

by:njacques
ID: 2634677
Sorry i forgot to update the test page, the lines you are talking about are ok in the version im currently working on. Also, the same thing i reported on the last message happens in the new version; and as well as your own test page.

Start the test...
Let loop for some time...
then skip to the 10 sec countdown...
wait a few seconds and skip to the 20 sec countdown...
wait a few seconds and skip to the 30 sec countdown...
wait a few seconds and skip to the 40 sec countdown...
wait a few seconds and skip. It should go back to the loop state, but in fact it goes to the 10 sec countdown..

if i let the 40 seconds countdown expire, it goes to the loop, manual skip seems to be the problem!
0
 
LVL 8

Expert Comment

by:jbirk
ID: 2634901
No, it's working properly on my page.  Try it again, and watch the state, not the seconds.  If you look at this section of the code, I think the confusion will become apparent:

else if (state == 4)
{restart(41); // reset to original slide and loop infinitely
 // change url to home page slide here...
state=0;
}

It's restarting into the beginning state when this step is reached. (state=0;) BUT it's also setting the timer to begin at 41 instead of 6.  This makes it look like you're on the 4th page but you're not, it's the first page like it should be with a longer than normal timer for the first time.  I thought this is what you wanted for their return, but if not just change the restart to be:
{restart(6);

If you intended to have a fourth slide here then, add a fifth state:
else if (state == 4)
{restart(41);
 // change to fourth slide here
state++;
}
else if (state == 5)
{restart(6); // reset to original slide and loop infinitely
 // change url to home page slide here...
state=0;
}


The confusion may be that the state is one ahead of the slide which the user is currently on.

I hope this clears it up for you:-)

-Josh
0
 

Author Comment

by:njacques
ID: 2637119
Adjusted points from 50 to 100
0
 

Author Comment

by:njacques
ID: 2637120
He! Now it works exactly like i wanted it to work!...
Thank you to have helped me that much...

Here is an extra 50 points to sticking to my project!

To those who are checking this for reference, here is the final code:

LONG LIVE EE!!!!

-------Javacript---------

<html>
<head><title>Countdown test</title></head>

<script>
<!--
var dn
c1=new Image(8,24); c1.src="c1.gif"
c2=new Image(8,24); c2.src="c2.gif"
c3=new Image(8,24); c3.src="c3.gif"
c4=new Image(8,24); c4.src="c4.gif"
c5=new Image(8,24); c5.src="c5.gif"
c6=new Image(8,24); c6.src="c6.gif"
c7=new Image(8,24); c7.src="c7.gif"
c8=new Image(8,24); c8.src="c8.gif"
c9=new Image(8,24); c9.src="c9.gif"
c0=new Image(8,24); c0.src="c0.gif"
cb=new Image(8,24); cb.src="cb.gif"

function hiLite(imgName,imgObjName) {
if (document.images) {
document.images[imgName].src = eval(imgObjName + ".src");
}} //-->
</SCRIPT>

<script>
<!--

state=0; // the current slide state 0 is the main start page...
// noything happens until state becomes 1
ticks=6; // the number of ticks left in the current countdown
play=1;  // signifies that the countdown is playing.  If it's set to 0 the countdown is interrupted.

function begintimer(){
setTimeout("tick()",1111);
}
function tick(){
document.f.face.value="State "+state+" Ticks "+ticks
ticks--;
if (ticks < 0) ticks = 0;
extract(ticks);
if (!play) return; // if the countdown is stopped...
if (ticks == 0) // reached end of countdown... check state
{if (state == 0) {restart(6);} // keep looping in state 0
else if (state == 1)
{restart(11); // restart with however many seconds are needed for this slide
 // change url to first slide here
state++;
}
else if (state == 2)
{restart(21); // restart with however many seconds are needed for this slide
 // change url to second slide here
state++;
}
else if (state == 3)
{restart(31); // restart with however many seconds are needed for this slide
 // change url to third slide here
state++;
}
else if (state == 4)
{restart(41);
// change to fourth slide here
state++;
}
else if (state == 5)
{restart(6); // reset to original slide and loop infinitely
// change url to home page slide here...
state=0;
}  
}
else
begintimer();
}

function restart(num){
ticks=num;
begintimer();
}
//stop hiding -->
</script>


<script language=JavaScript>

<!-- start of javascript hide from older browsers
function extract(s){
if (!document.images)
return
if (s<=9){
document.g.src=c0.src
document.images.h.src=eval("c"+s+".src")
}
else {
document.images.g.src=eval("c"+Math.floor(s/10)+".src")
document.images.h.src=eval("c"+(s%10)+".src")
}  }
//stop hiding -->

</script>

<script language=JavaScript>

<!-- start of javascript hide from older browsers
//stop hiding -->

</script>

<body onload=begintimer()>
<img src="c0.gif" width=8 height=24><img src="c0.gif" width=8 height=24><img src="colon.gif" width=8 height=24><img src="c0.gif" width=8 height=24><img src="c0.gif" width=8 height=24><img src="colon.gif" width=8 height=24><img src="c0.gif" name="g" width=8 height=24><img src="c0.gif" name="h" width=8 height=24><br>
<br>
<br>
<a href="javascript:;" onClick="if (state == 0) state = 1; ticks=1;">Skip to the next page</a>
<br>
<a href="javascript:;" onClick="play=!play; if (play) tick();">Pause/Resume counter</a>
<br><br>
<form name="f">
<INPUT TYPE="text" NAME="face" size=20 VALUE="test">
</form>

Images you may need:<br>
<br>
<img src="c0.gif" width=8 height=24><br>
<img src="c1.gif" width=8 height=24><br>
<img src="c2.gif" width=8 height=24><br>
<img src="c3.gif" width=8 height=24><br>
<img src="c4.gif" width=8 height=24><br>
<img src="c5.gif" width=8 height=24><br>
<img src="c6.gif" width=8 height=24><br>
<img src="c7.gif" width=8 height=24><br>
<img src="c8.gif" width=8 height=24><br>
<img src="c9.gif" width=8 height=24><br>
<img src="colon.gif" width=8 height=24><br>

</body>
</html>
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

I've been trying to accomplish this for a while and it just struck me yesterday how to accomplish this task. I have done searches all over the internet looking for ways to email pages from my applications and finally I have done it!!! Every single s…
Introduction HTML checkboxes provide the perfect way for a web developer to receive client input when the client's options might be none, one or many.  But the PHP code for processing the checkboxes can be confusing at first.  What if a checkbox is…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now