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.
Results 1 to 15 of 15
  1. #1
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts

    countdown timers

    Hi All,

    There are a million scripts out there for countdown timers, a few great ones from this forum. What I'm not sure on is how to tie a timer into the local PC time. I'm trying to give page viewers an approx idea of when the next batch job will run.

    I want a timer to countdown in 5 minute intervals, on a constant loop, so resetting every 5 minutes on the 5 minute mark (e.g. 1pm, 1.05, 1.10 etc). This bit is simple. However, it needs to be tied into the users PC time, so that the timer syncs with the time when the page loads. For example, if someone loads a page at 11:13:43am, the counter would start at 1:17.

    Any ideas? I hope my explanation is clear enough, happy to clarify if need be.

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,919
    Thanks
    79
    Thanked 4,423 Times in 4,388 Posts
    My head hurts.

    How does 11:13:43am become a counter starting a 1:17???

    And how does syncing it with the user's PC's time give them an *ACCURATE* time when the batch job will run on the server?? I have seen PC's with their time many seconds, sometimes more than a minute, off from the server time. Plus, of course, the server may be in a different time zone, to top it all off.
    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
    Senior Coder
    Join Date
    Sep 2010
    Posts
    2,030
    Thanks
    15
    Thanked 240 Times in 240 Posts
    All that you have in javascript is setInterval and setTimeout, setInterval will call a function at the specified intervals, setTimeout at the specified timeout. That's all there is to it.
    Welcome to http://www.myphotowizard.net

    where you can edit images, make a photo calendar, add text to images, and do much more.


    When you know what you're doing it's called Engineering, when you don't know, it's called Research and Development. And you can always charge more for Research and Development.

  • #4
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,919
    Thanks
    79
    Thanked 4,423 Times in 4,388 Posts
    Got it. You meant the time would count down 0:01:17 (I took it as 1 hour 17 minutes) so that it would fire at 11:15:00 AM.

    Okay, that's trivial. But, again, this may or may not be even close to matching the SERVER time, when the batch job runs (I assume it runs on the server).

    A better way to do this is to send the server time to the browser and use it for counting down, ignoring the user's PC time.

    You can easily do this with PHP/JSP/ASP.
    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.

  • #5
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,919
    Thanks
    79
    Thanked 4,423 Times in 4,388 Posts
    But regardless of where the time comes from, it's simple enough: The first "tick" has to be adjusted to the starting time but after that it's just a regular setInterval.

    Code:
    var start = new Date(); // but better to get this from the server!
    var seconds = start.getSeconds() + start.getMinutes() * 60;
    var secsPast5minutes = seconds % ( 5 * 60 );
    var secsTillNext5minutes = ( 5 * 60 ) - secsPast5minutes;
    setTimeout( tick, secsTillNext5minutes );
    var ticker = null;
    
    function tick( )
    {
        ... display a message ...
    
        // if this was first time, start the interval timer instead:
        if ( ticker == null ) { ticker = setInterval( tick, 5 * 60 * 1000 ); }
    }
    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.

  • Users who have thanked Old Pedant for this post:

    longman (08-06-2013)

  • #6
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts
    Hi guys,

    Thanks for the replies. Apologies OP, didn't mean to make your head hurt!

    you are correct in what I am trying to do. I understand also what you are saying about the server time, however in this instance a few seconds will not make any difference as it is an approximate. I want to keep things client side if possible.

  • #7
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts
    Thanks for the code snippet OP. Now my head hurts as to how this can generate an actual countdown timer, or is it simply to set the start point and needs to be sent to a counter script?

    Sorry if it's obvious, it obviously isn't to me right now.

  • #8
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,919
    Thanks
    79
    Thanked 4,423 Times in 4,388 Posts
    I thought you said you had seen many countdown timers you liked? Other than the fact they didn't display time at next 5 minute mark?

    I'm still not 100% sure what you want to display, but something like this?

    I changed my mind about how to write the code when I realized I wanted to display the time at the next 5 minute mark. This way makes it easier to do that.

    Code:
    <!DOCTYPE html>
    <html>
    <body>
    Next batch run at <span id="when"></span><hr/>
    
    <script type="text/javascript">
    var next5 = new Date();
    next5.setMinutes( Math.floor( next5.getMinutes() / 5 ) * 5 + 5 );
    next5.setSeconds( 0 );
    
    showTime(); // initial display
    
    // then get started: 
    setTimeout( tick, next5.getTime() - (new Date()).getTime() );
    var ticker = null;
    
    function showTime( )
    {
        var hr = next5.getHours();
        var ampm = hr > 11 ? " PM" : " AM";
        if ( hr > 12 ) hr -= 12;
        if ( hr == 0 ) hr = 12;
    
        var mn = next5.getMinutes();
        if ( mn < 10 ) mn = "0" + mn;
    
        document.getElementById("when").innerHTML =
            hr + ":" + mn + ampm;
    }
    
    function tick( )
    {
        // bump time by 5 minutes...
        next5.setMinutes( next5.getMinutes() + 5 );    
        // show it...
        showTime();
    
        // if this was first time, start the interval timer instead:
        if ( ticker == null ) { ticker = setInterval( tick, 5 * 60 * 1000 ); }
    }
    </script>
    </body>
    </html>
    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.

  • #9
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,919
    Thanks
    79
    Thanked 4,423 Times in 4,388 Posts
    Thinking more about it...since you only want it to fire every 5 minutes, there's no real incentive to use setInterval. So let's simplify things:
    Code:
    <!DOCTYPE html>
    <html>
    <body>
    Next batch run at <span id="when"></span><hr/>
    
    <script type="text/javascript">
    var next5 = new Date();
    // to start out, next5 is actually last *prior* 5 minute mark
    next5.setMinutes( Math.floor( next5.getMinutes() / 5 ) * 5 );
    next5.setSeconds( 0 );
    next5.setMilliseconds( 0 );
    // then get started:
    tick( );
    
    function tick( )
    {
        // bump time by 5 minutes...
        next5.setMinutes( next5.getMinutes() + 5 );    
    
        // show it...
        var hr = next5.getHours();
        var ampm = hr > 11 ? " PM" : " AM";
        if ( hr > 12 ) hr -= 12;
        if ( hr == 0 ) hr = 12;
    
        var mn = next5.getMinutes();
        if ( mn < 10 ) mn = "0" + mn;
    
        document.getElementById("when").innerHTML =
            hr + ":" + mn + ampm;
    
        // schedule the next tick:
        setTimeout( tick, next5.getTime() - (new Date()).getTime() );
        
    }
    </script>
    </body>
    </html>
    This has the advantage that it is self-adjusting, in case something "hung" the timer one time. It will automatically get back in sync the next time.
    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.

  • Users who have thanked Old Pedant for this post:

    longman (08-06-2013)

  • #10
    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
    This has the advantage that it is self-adjusting, in case something "hung" the timer one time. It will automatically get back in sync the next time.
    setInterval has self adjusting built in. On a five minute setInterval if one were delayed by four minutes then the next would trigger a minute later.
    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.

  • #11
    New Coder
    Join Date
    Aug 2013
    Posts
    50
    Thanks
    0
    Thanked 11 Times in 11 Posts
    Quote Originally Posted by felgall View Post
    setInterval has self adjusting built in.
    Oh, really? Care to test this for me in Chrome? Change max_time to 1000 if you want a long test.

    As you can see, Chrome does no drift accommodation (adjustment). Other browsers also do not. Firefox does, though.

  • Users who have thanked joesimmons for this post:

    Old Pedant (08-06-2013)

  • #12
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,919
    Thanks
    79
    Thanked 4,423 Times in 4,388 Posts
    MSIE 10 seems to do drift accomodation. Individual drifts can be pretty far off (I saw up to 32 milliseconds) but then it "pulls it back in" on the next interval. Even saw a couple of -1's mixed in with mostly 3's through 5's.

    But yeah, Chrome shows no accomodation whatsoever. It just keeps drifting further and further off. But always just lagging a little more. It looks to me like Chrome implements setInterval as a series of setTimeout's. That is, after completing the function after the first interval, it then issues an internal setTimeout of the same period.

    In any case, it certainly gets *MUCH WORSE* the shorter the interval!

    With an interval of 100ms, after 10 seconds it is off by 35ms!!
    With an interval of 1000ms (1 sec), after 10 seconds it is off by only 2 ms.

    Nice test, Joe Simmons. And welcome to the forums. Been lurking long?
    Last edited by Old Pedant; 08-06-2013 at 10:07 PM.
    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.

  • #13
    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
    But yeah, Chrome shows no accomodation whatsoever. It just keeps drifting further and further off. But always just lagging a little more. It looks to me like Chrome implements setInterval as a series of setTimeout's. That is, after completing the function after the first interval, it then issues an internal setTimeout of the same period.
    That sounds like a bug to me. The whole point of setInterval is that it is supposed to trigger at regular intervals. A properly working setInterval cannot be implemented as a series of setTimeouts.

    I wasn't aware of that issue. I'll have to add it to my list of reasons why people should not use Chrome as their browser.
    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.

  • #14
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts
    Thanks Old P, as usual you response has been a great learning experience. I did actually sort it out after my last post to get what I want by integrating your earlier code into an existing countdown timer.

    Thanks everyone else for your robust comments. Good thing I only need this to work on IE and FF.

  • #15
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts
    So this is what I've got, by incorporating parts of Old Pedants code with a counter I found online. It works perfectly the first time. I can't get it to reset though. I've tried using setTimeout("countdown",1000) in place of the alert, but all it does is stop. Could it have something to do with the global variables not being re-declared as only the function is recalled?

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    <title>Counter</title>
    
    <script type="text/javascript">
    
    	var mins;
    	var secs;
    
    	function countdown() {
    		var start = new Date();
    		var seconds = start.getSeconds() + start.getMinutes() * 60;
    		var secsPast5minutes = seconds % ( 5 * 60 );
    		var secsTillNext5minutes = ( 5 * 60 ) - secsPast5minutes;
    
    		var Tot = secsTillNext5minutes;
    		minVar = Math.floor(Tot/60);
    		secVar = Tot % 60;
    		mins = 1 * CDm("" +minVar);
    		secs = 0 + CDs(":"+secVar);
    		CDredo();
    	}
    
    	function CDm(obj) {
    		for(var i = 0; i < obj.length; i++) {
    			if(obj.substring(i, i + 1) == ":")
    			break;
    		}
    		return(obj.substring(0, i));
    	}
    
    	function CDs(obj) {
    		for(var i = 0; i < obj.length; i++) {
    			if(obj.substring(i, i + 1) == ":")
    			break;
    		}
    		return(obj.substring(i + 1, obj.length));
    	}
    
    	function CDdis(mins,secs) {
    		var disp;
    		if(mins <= 9) {
    			disp = " 0";
    		} else {
    			disp = " ";
    		}
    		disp += mins + ":";
    		if(secs <= 9) {
    			disp += "0" + secs;
    		} else {
    			disp += secs;
    		}
    		return(disp);
    	}
    
    	function CDredo() {
    		secs--;
    		if(secs == -1) {
    			secs = 59;
    			mins--;
    		}
    		document.getElementById("countdowndisp").firstChild.nodeValue = CDdis(mins,secs);
    		((mins != 0) || (secs != 0)) ? countdown = setTimeout("CDredo()",1000) : alert("cycle");
    	}
    
    </script>
    </head>
    <body onload="countdown()">
    Next publish will occur in approximately: 
    <span id="countdowndisp">&nbsp;</span> minutes<br><br>
    </body>
    </html>


  •  

    Posting Permissions

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