0

I don't understand why hours of searching have left me empty handed. The situation is this: my site users can set a date and time for an event to begin. That date and time are stored in the db as a timestamp. I want to display a countdown for them. So, I query the db

SELECT TIMESTAMPDIFF(SECOND, NOW(), start) 
FROM events 
WHERE eid = '110';

That returns the number of second remaining until the event is set to begin. All I want is to be able to output, in a span, the number of days, hours, minutes, & seconds.

Here's the javascript I have thus far:

After reading the comments, searching more, and hacking a few things together, this is my updated code:

<span id="countdown-1"><?php echo $timeToEvent; ?></span>

(If there's a more appropriate way to to get my "seconds 'til event" value to the script, please correct me.)

secs = parseInt(document.getElementById('countdown-1').innerHTML,10);
setTimeout("countdown('countdown-1',"+secs+")", 1000);

function countdown(id, timer){
    function pad(num) {
        return num > 9 ? num : '0'+num;
    };
    timer--;
    days = Math.floor( timer / 86400 ),
    hours = Math.floor( timer / 3600 ),
    mins = Math.floor( timer / 60 ),
    secs = Math.floor( timer ),

    dd = days,
    hh = hours - days * 24,
    mm = mins - hours * 60,
    ss = secs - mins * 60;

    clock = dd + ' days ' + pad(hh) + ':' + pad(mm) + ':' + pad(ss) ;

    document.getElementById(id).innerHTML = clock;
    if ( timer > 0 ) {
        setTimeout("countdown('" + id + "'," + timer + ")", 1000);
    } else {
        window.location.reload(true);
    }
}

http://jsfiddle.net/mmJQq/

This code works. However, as I wrote above, I don't know if I ought to be passing the php variable $timeToEvent to the script more directly. It is slightly annoying that the actual number of seconds appears in the span for about 1 second before the javascript changes it to what I want to see. (By the way, I'm not overly concerned about accuracy in this context; I don't mind the time drift.)

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
David
  • 1,175
  • 1
  • 16
  • 29
  • You'd be better off retrieving the actual event start time from the database and performing the "time remaining" calculation in each iteration of your update code. – eggyal Mar 14 '13 at 20:57
  • 4
    You use `diff = ,` within the function, so every time the function is called, it gets reset to that time. You need separate functions to set/countdown. – Jon Mar 14 '13 at 20:57
  • 1
    You should do `setInterval(function() { updateTime(); }, 1000 );` – Ryan Mar 14 '13 at 21:17

2 Answers2

2

You are never changing diff. Every time the function runs, it's the same value still. Move diff outside the function, then decrement it by 1000 milliseconds (1 second) every time the function runs.

  var
    diff = 3850000; // Move this outside the function so that it can be changed.
                    // If you don't, it will get reset to its original value
                    // every time updateETime runs.

function updateETime() {

  function pad(num) {
    return num > 9 ? num : '0'+num;
  };


    days = Math.floor( diff / (1000*60*60*24) ),
    hours = Math.floor( diff / (1000*60*60) ),
    mins = Math.floor( diff / (1000*60) ),
    secs = Math.floor( diff / 1000 ),

    dd = days,
    hh = hours - days * 24,
    mm = mins - hours * 60,
    ss = secs - mins * 60;

    document.getElementById("countdown_time")
        .innerHTML =
            dd + ' days ' +
            pad(hh) + ':' + //' hours ' +
            pad(mm) + ':' + //' minutes ' +
            pad(ss) ; //+ ' seconds' ;

    diff -= 1000; // Every time the function runs, subtract one second from diff.

}
setInterval(updateETime, 1000 );

http://jsfiddle.net/ZWrqB/

As a commenter pointed out, this isn't totally reliable, because setInterval won't reliably fire exactly every one second, so your timer's accuracy will drift away little by little until the page is refreshed. The better way to do it is to store the time to countdown to, then every time the function fires, calculate the offset from the current time and use that offset for the timer display. This SO answer is a good way to do it: https://stackoverflow.com/a/11336046/711902

Community
  • 1
  • 1
Trevor Dixon
  • 23,216
  • 12
  • 72
  • 109
  • "then decrement it by 1000 milliseconds" **no**. actually i like your example for the ops question. an interval is never happening exactly _in or for_ 1000 s (so you must not rely on it). do calculate your diff by `'point in future' - 'now' (new Date)` every interval. – metadings Mar 14 '13 at 21:34
  • That's true. I wanted to keep it as similar to OP's original attempt so he could easily tell what went wrong. I should add more to help him approach the problem a better way. – Trevor Dixon Mar 14 '13 at 22:46
  • Thank you for pointing out the simple thing that my head was skimming over. – David Mar 15 '13 at 15:15
0

The time is static, because the time is static.

In your function updateETime(), you display the variable diff, broken down into days, hours, minutes and seconds. But since diff never changes, the display doesn't change as well.

If you want to show a countdown, you must decrement diff, every time you call updateETime().

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198