Well I’m trying to recreate the countdown for each of these challenges seen here:
http://www.bungie.net/stats/reach/globalchallenges.aspx
The problem is if you compare my countdown with the original countdown there is about a 10-14 second difference, I just don’t understand why? Thanks!
I’m using the source from their mobile page(view source) to get the expiration times.
<span id="wExpSeconds" title="1304330400000"></span>
<span id="dExpMilliseconds" title="1303984800000"></span>
Here is the source code of my countdown page:
<html>
<head>
<title></title>
<style type="text/css">
.stat{ font: 14px/18px Arial, Helvetica, sans-serif; color:#bbb; }
.seconds{ color:#ff5f3c; }
</style>
</head>
<body>
<div id="countDownDiv"></div>
<script type="text/javascript">
function countDown(id, end, cur){
this.container = document.getElementById(id);
this.endDate = new Date(end);
this.curDate = new Date(cur);
var context = this;
var formatResults = function(day, hour, minute, second){
var displayString = [
'<span class="stat">',day,'d </span>',
'<span class="stat">',hour,'h </span>',
'<span class="stat">',minute,'m </span>',
'<span class="stat seconds">',second,'s</span>'
];
return displayString.join("");
}
var update = function(){
context.curDate.setSeconds(context.curDate.getSeconds()+1);
var timediff = (context.endDate-context.curDate)/1000;
// Check if timer expired:
if (timediff<0){
return context.container.innerHTML = formatResults(0,0,0,0);
}
var oneMinute=60; //minute unit in seconds
var oneHour=60*60; //hour unit in seconds
var oneDay=60*60*24; //day unit in seconds
var dayfield=Math.floor(timediff/oneDay);
var hourfield=Math.floor((timediff-dayfield*oneDay)/oneHour);
var minutefield=Math.floor((timediff-dayfield*oneDay-hourfield*oneHour)/oneMinute);
var secondfield=Math.floor((timediff-dayfield*oneDay-hourfield*oneHour-minutefield*oneMinute));
context.container.innerHTML = formatResults(dayfield, hourfield, minutefield, secondfield);
// Call recursively
setTimeout(update, 1000);
};
// Call the recursive loop
update();
}
countDown("countDownDiv",1304330400000, new Date().getTime());
</script>
</body>
</html>
Since the function is not called as a method of any object, nor with
call()orapply(), its this keyword will reference the global object. So the above effectively creates global variables for container, endDate and curDate.Please write out 1,000 times: the this keyword is not context (nor does it have anything to do with scope).
As already discussed, the variable “context” is a reference to the global object, it is set by how you call the function. So you are accessing global variables here.
Here is your problem. That will call update in about 1 second. The longer your counter runs, the more inaccurate it will become (it will always drift later).
You should get a new date object each time, look at the ms, then call the next timeout just after the next full second (give it about 30 to 50ms to make sure it’s just after and not before). That way your counter will never be out by much and even if it is, it will correct itself each time it is called.
And make sure you calculate the full count down each time, so if there is a lag of a few seconds you catch up again.