Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 20
  1. #1
    Senior Coder
    Join Date
    Dec 2002
    Location
    Arlington, Texas USA
    Posts
    1,072
    Thanks
    4
    Thanked 8 Times in 8 Posts

    Countdown timer quits when page looses focus

    I have a site that administers a timed test. When the page loads a message is displayed with instructions while the actual questions are hidden from view. Once the person clicks continue the questiosn will be displayed and the timer will start. The timer should continue until it counts down to 30 where it informs them they have 30 seconds left then continues to 0 and then it should automatically move the user off the page.

    We never had a problem until recently a few people told me the timer stopped. I found out that in Firefox if the window looses focus more than 1 time, the timer will stop. It did not stop if It only lost focus one time but the 2nd time it always stopped. This tells me some people are possibly cheating and using a calculator, or looking up answers on the web. The example below is for a math section of the test. However, there are other sections as well.

    Does anyone know how to prevent the timer from stopping? It should always run.

    BTW This happens in Firefox only. It works fine in Opera, Safari, Chrome and IE



    Code:
     
    <script language="JavaScript" type="text/javascript"> 
    var mins = 11;
    var secs = 0;
    var message = "";
    var section="Math";
    var pagenumber = 3;
    var totalpages = 5;
     
    function instructions(){
    	self.status=":  This is section "+pagenumber+" of "+totalpages
    	message ="<p>Following is a timed exercise consisting of typical arithmetic calculations.  Work as carefully and as quickly as you can.</p>";
    	message+="<p>Select the correct answer from the choices provided. Calculators are not allowed, you will want to use SCRATCH PAPER.</p>";
    	message+="<br /><p><strong>You have ELEVEN MINUTES (11) for this exercise</strong></p>";
    	message+='<br /><br /><p style="text-align:center;"><a href="javascript:void(0)" onClick="displayAssessment();" style="font:bold 1.2em arial" alt="click to continue"><strong>Continue</strong></a></p>';
    	document.getElementById('message').innerHTML = message;
    }
    function returncheck(f){
    	message = "\n                      YOU HAVE " + mins + " MINUTES and " + secs + " SECONDS LEFT.\n\n"
    	message +="                    We suggest you take this time to review your answers.\n\n"
    	message +="Click OK to continue to the next section or click CANCEL to remain in this section."
    	if (confirm(message)){ 
    		clearTimeout(Timer);
    		f.submit();
    	} else { 
    		return false;
    	}	
    }
    function start(){
    	message="Time remaining: " + mins + " minutes " + secs + " seconds";
    	self.status=message;
    	document.title = message;
    	if (secs == 0 && mins != 0){
    		secs=60;
    		mins-=1;
    	}
    	if (secs == 30 && mins == 0){
    		alert("You only have 30 seconds left");
    	}
    	secs-=1
    	if (secs==0 && mins==0) {
    		setTimeout('go2()',0000);
    	}  else {
    		Timer=setTimeout('start()',1000);
    	}
    }
    function go2(){
    	self.status="Your time has expired on the " + section + " section.";
    	alert("\nYour time has expired on the " + section + " section.");
    	clearTimeout(Timer);
    	document.forms[0].submit();
    }
    function displayAssessment(){
    	document.getElementById('message').innerHTML = "";
    	document.getElementById('message').style.display = "none"; 
    	document.getElementById('AssessmentData').style.display = "block"; 
    	start();
    }
     
     
    </script>
    </head>
    <body id="twocol" onLoad="instructions(); if(history.length>0)history.go(+1);">

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    27,554
    Thanks
    80
    Thanked 4,617 Times in 4,581 Posts
    I can't reproduce what you say is happening with a fairly simple test.

    Here's the page I used to test with:
    Code:
    <html>
    <body>
    <h1 id="continuous"></h1><br/>
    <h1 id="test"></h1>
    
    
    <script type="text/javascript">
    (
      function()
      {
          var show1 = document.getElementById("continuous");
          var show2 = document.getElementById("test");
      
          var ticker = (new Date()).getTime();
    
          function tick( )
          {
              ticker += 1000;
    
              var now = new Date();
              var mn = now.getMinutes();
              var sc = now.getSeconds();
              if ( mn < 10 ) mn = "0" + mn;
              if ( sc < 10 ) sc = "0" + sc;
              show1.innerHTML = now.getHours() + ":" + mn + ":" + sc;
    
              var now2 = new Date(ticker);
              var mn = now2.getMinutes();
              var sc = now2.getSeconds();
              if ( mn < 10 ) mn = "0" + mn;
              if ( sc < 10 ) sc = "0" + sc;
              show2.innerHTML = now2.getHours() + ":" + mn + ":" + sc;
    
    
          }
    
          setInterval( tick, 1000 );
      }
    )();
    </script>
    </body></html>
    That shows two clocks. The first ("continuous") gets its time from the system clock each second. The second ("text") only gets the time once and then "ticks" by adding 1000 milliseconds to that time each second.

    If what you say is occurring were to really occur, then the two clocks would get out of sync. That is, if any of those "ticks" were skipped, the time from the system clock would auto-correct the next time fetched but the other time would indeed miss a second.

    It's certainly possible--maybe almost expected--that eventually the clocks could get one or two seconds out of sync. After all, if there is some high-priority action occurring on the machine that blocks JavaScript from running, then you could expect a missed "tick" now and then.

    But even with many pages active in many different browsers (yes, including multiple pages open in FireFox), I can't make the "test" clock skip time.

    &&&&&&&&&&&&&&&&&&

    Now, I *COULD* cause the "time slip" by running a page like *THIS* in another browser window:
    Code:
    <script>
    var t = ( new Date() ).getTime();
    var t2 = t;
    
    while ( t2 < t + 10000 )
    {
        t2 = ( new Date() ).getTime();
    }
    alert("finished");
    </script>
    See that? It "hogs" the JavaScript runtime for 10 seconds. And, yes, it then causes a 10 second "slip" on the other page. So if your students are smart enough to create a page like that and then run it to, effectively, stop your clock... indeed they could be cheating!

    ****************************

    SO I think all the above shows you the solution, in any case.

    Instead of just using a countdown as your start( ) function is doing:
    (1) At start of the page, get the starting time and save it in a global variable.
    (2) At each tick, get the current time. Get the difference between current and starting time and base your decisions ("30 seconds left", "time is up") on that difference.

    *** HOWEVER ***

    A really clever student will look at the source code for your page, see where it is you are storing the starting time in that global variable, and then simply execute some JavaScript code (in the address line of the browser will work!) to change that global variable to sometime next year, and *KABLOOEY*. Nothing you can do about it.

    The *CORRECT* solution is to *ALSO* check the time in SERVER-SIDE code. Use a session variable to hold the starting time and, when the page is submitted to the server, get the ending time and verify that the user hasn't cheated. The only "cheat" that would then work would be for the user to somehow kill their session. But then you can detect that and automatically assume that too much time has elapsed.

    So... I wouldn't even bother changing your current JS code (though it might be a good idea to do so eventually) and, instead, add in the server side check. Yesterday.
    Last edited by Old Pedant; 12-11-2012 at 02:12 AM.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #3
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    27,554
    Thanks
    80
    Thanked 4,617 Times in 4,581 Posts
    p.s.: Allow a few seconds of "time slip" server side.

    That is, if the student is allowed 11 minutes client-side, make it 11 minutes and (say) 5 seconds server side, just in case the student has a slow connection and/or there are network delays.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #4
    Senior Coder
    Join Date
    Dec 2002
    Location
    Arlington, Texas USA
    Posts
    1,072
    Thanks
    4
    Thanked 8 Times in 8 Posts

    Timer just stops

    Bill,

    We are still having issues with the timer in firefox.

    If a page is opened in firefox, after a short while the timer just quits.

    In the first post I thought it had something to do with the page loosing focus but obviously that wasn't it. But it does stop in firefox and is replicated every time we test it. I am to the point of not allowing firefox to be used.

    Here is an example of it in action
    http://www.virtualhrcenter.com/evalu...da/example.asp

    If opened in any other browser it will work.

    BTW in the example the page just reloads itself on submission of the button

  • #5
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,642
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Perhaps if you switch from using setTimeout to using setInterval - that way you avoid any delays in the script actually being called resulting in all subsequent calls being delayed. With setInterval any delays will be made up because multiple copies of the cal will have been queued.

    For example: with setTimeout if there is a two minute delay at any point then all the subsequent setTimeout calls will be delayed by that two minutes whereas with your one second timer a setInterval call will have queued 120 calls during that time and will catch them up as quickly as it can.

    setInterval basically avoids the missed tick problem that setTimeout can have by catching up all the missed ticks as soon as the load drops enough for them all to run.

    Anyway it is relatively easy to stop the timer in this instance simply by turning JavaScript off for the current page (or opening the debugger and set a breakpoint in the script would work as well). As Old Pedant said, the correct solution is a server side one.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    27,554
    Thanks
    80
    Thanked 4,617 Times in 4,581 Posts
    Ummm...you aren't SHOWING the timer on the page, so it's hard to know when it "slips".

    I see you are doing this:
    self.status=message;
    but modern browsers don't display a status line any more.

    And it is *WAY* to easy to cheat on this.

    I can just open that page, copy/paste the entire page (say to MS Word), and then hit REFRESH every 5 minutes or so, which causes the timer to start all over.

    In the meantime, I work out all the problems...taking a few hours to do so if I want...until I'm finally ready to put in the answers.

    This is about as secure as tissue paper.

    As I said way back then, you should be timing this *ALSO* in the server side code.

    And that means that the intro screen (that just says the student has 11 minutes to complete the page) needs to be a completely separate page from the actual problem set, so that your server-side code times *ONLY* the problem set.

    Finally, you didn't implement the suggestion I had also made, where instead of relying upon the setTimeout to maintain accuracy, you base the time on the system clock, by going out and getting the Date() at each "tick" and comparing the current time vs. the start time.

    Another error:

    You display a message with 30 seconds left using alert( ), but so long as the perso n does *NOT* respond to the alert(), the page will just SIT THERE. So if he comes back tomorrow and finally clicks on the alert(), then he still has 30 seconds before time expires.

    And what do you do if somebody starts the test, turns off JavaScript, finishes the test in 3 hours, and then turns it back on again?

    Also, you are using setTimeout() instead of setInterval(), so indeed if some other process hogs the CPU the timeout is going to be delayed.

    It's just all done wrong and crying out for a rewrite, problems with FireFox or not.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #7
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    27,554
    Thanks
    80
    Thanked 4,617 Times in 4,581 Posts
    Whoops...Felgall beat me to many of the points. But I think that just proves that indeed this really needs a rework.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #8
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,642
    Thanks
    0
    Thanked 649 Times in 639 Posts
    Quote Originally Posted by Old Pedant View Post
    You display a message with 30 seconds left using alert( ), but so long as the perso n does *NOT* respond to the alert(), the page will just SIT THERE. So if he comes back tomorrow and finally clicks on the alert(), then he still has 30 seconds before time expires.


    That's what alerts look like in Opera (except that the OP's alert would say "You only have 30 seconds left" instead of "check the box below to turn off JavaScript") - what is supposed to happen regarding the timing of the page if the checkbox gets set turning off JavaScript and never returning from the alert().

    Just another reason why this script is not a good idea.

    Also the title for this thread has a typo - pages can no more loose focus than they can tight focus - lose only has one O.
    Last edited by felgall; 01-26-2013 at 12:00 AM.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #9
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    27,554
    Thanks
    80
    Thanked 4,617 Times in 4,581 Posts
    pages can no more loose focus than they can tight focus -
    Oh, I dunno. I remember some early JavaScript toy pages where the JS code wouldn't let you put your cursor where you wanted it to be. <grin/>
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #10
    Regular Coder
    Join Date
    Jan 2013
    Location
    Germany
    Posts
    578
    Thanks
    4
    Thanked 77 Times in 77 Posts
    As an addition you should think about implementing a better timer solution. Standard methods in JavaScript have horrible accuracy, I just tested 30s a few times and was off by 1–3 seconds everytime.

    Here is a tutorial on more accurate timers.

  • #11
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    27,554
    Thanks
    80
    Thanked 4,617 Times in 4,581 Posts
    Actually, Airblader, if you look at my post #2 I suggested that same basic answer way back on December 10th:
    Instead of just using a countdown as your start( ) function is doing:
    (1) At start of the page, get the starting time and save it in a global variable.
    (2) At each tick, get the current time. Get the difference between current and starting time and base your decisions ("30 seconds left", "time is up") on that difference.
    But I was ignored then, obviously.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #12
    Senior Coder
    Join Date
    Dec 2002
    Location
    Arlington, Texas USA
    Posts
    1,072
    Thanks
    4
    Thanked 8 Times in 8 Posts
    The assessment is loaded with in a page with no chrome(ie no address bar, back or forward buttons, etc etc) just the page. Should they turn off javascript the button stops working because in the actual assessment i do not use a submit object on the first page but instead use a button object which requires an onclick event to work. I also remove the right click menu options.

    If someone is smart enough to get around all of these things they don't need to cheat

  • #13
    Senior Coder
    Join Date
    Dec 2002
    Location
    Arlington, Texas USA
    Posts
    1,072
    Thanks
    4
    Thanked 8 Times in 8 Posts
    Quote Originally Posted by felgall View Post


    Also the title for this thread has a typo - pages can no more loose focus than they can tight focus - lose only has one O.
    Obviously you never make typos do you?

    Stop being anal

  • #14
    Senior Coder
    Join Date
    Dec 2002
    Location
    Arlington, Texas USA
    Posts
    1,072
    Thanks
    4
    Thanked 8 Times in 8 Posts
    Quote Originally Posted by Old Pedant View Post


    I can just open that page, copy/paste the entire page (say to MS Word), and then hit REFRESH every 5 minutes or so, which causes the timer to start all over.
    Wrong this example allows a lot of stuff that the actual assessment does not.

    An actual assessment is derived from a class that if they hit refresh it ends the assessment.


    Another error:

    You display a message with 30 seconds left using alert( ), but so long as the perso n does *NOT* respond to the alert(), the page will just SIT THERE. So if he comes back tomorrow and finally clicks on the alert(), then he still has 30 seconds before time expires.
    This is done by design. Which is why your server side solution may not be the best idea

  • #15
    Senior Coder
    Join Date
    Dec 2002
    Location
    Arlington, Texas USA
    Posts
    1,072
    Thanks
    4
    Thanked 8 Times in 8 Posts
    Quote Originally Posted by Old Pedant View Post
    Actually, Airblader, if you look at my post #2 I suggested that same basic answer way back on December 10th:

    But I was ignored then, obviously.
    You weren't ignored but I am the ONLY one left here and I can get slammed which means priorities need to be set. I am sure you know how that is.


  •  
    Page 1 of 2 12 LastLast

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •