I’m working through some pomodoro tutorials and thought it best I understood the simple timer first so I found an entry on stack overflow on the simplest timer and built up from there… http://stackoverflow.com/questions/20618355/the-simplest-possible-javascript-countdown-timer
function startTimer(duration, display) {
var start = Date.now(),
diff,
minutes,
seconds;
function timer() {
// get the number of seconds that have elapsed since
// startTimer() was called
diff = duration - (((Date.now() - start) / 1000) | 0);
// does the same job as parseInt truncates the float
minutes = (diff / 60) | 0;
seconds = (diff % 60) | 0;
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
if (diff <= 0) {
// add one second so that the count down starts at the full duration
// example 05:00 not 04:59
start = Date.now() + 1000;
}
}
// we don't want to wait a full second before the timer starts
timer();
setInterval(timer, 1000);
}
$('#twentyfive').on('click', function(){
var fiveMinutes = 60 * 25,
display = document.querySelector('#time');
startTimer(fiveMinutes, display);
});
The first time I click on the start button… it gives me a 25 minute timer as expected… the second time it stutters a shadow timer behind it… third click a third… etc. It appears to be keeping each date.now time and trying to show the difference to each of them… I was curious to the best practice to resetting this… It feels like a memory leak in the making to be building hidden timer functions just running in the background…
No, it’s not a memory leak, it’s just that every time you click Start, you initiate a new setInterval and the last setInterval also keeps calling the timer() function, you want to clear the last interval and start a new one.
The setInterval() function returns the current interval Id, and you can clear the particular interval id using clearInterval(). Here’s the syntax:
var intervalId = setInterval(timer, 10000);
clearInterval(intervalId);
Here’s a simple solution to your timer problem:
var existingIntervalId = 0;
function startTimer(duration, display) {
var start = Date.now(),
diff,
minutes,
seconds;
function timer() {
// get the number of seconds that have elapsed since
// startTimer() was called
diff = duration - (((Date.now() - start) / 1000) | 0);
// does the same job as parseInt truncates the float
minutes = (diff / 60) | 0;
seconds = (diff % 60) | 0;
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
if (diff <= 0) {
// add one second so that the count down starts at the full duration
// example 05:00 not 04:59
start = Date.now() + 1000;
}
}
// we don't want to wait a full second before the timer starts
timer();
existingIntervalId = setInterval(timer, 1000);
}
$('#twentyfive').on('click', function(){
var fiveMinutes = 60 * 25,
display = document.querySelector('#time');
// Clear existing interval
clearInterval(existingIntervalId);
// Start the timer
startTimer(fiveMinutes, display);
});
ok, new problem… it keeps going into the negative numbers. I’ve looked at several tutorials that suggest I should be calling clearInterval(existingIntervalId);
again once the countdown reaches zero… but I can’t see where it’s actually doing the counting to stop it when it reaches zero…
line 21 is the closest I’m seeing, but I still must be scripting it wrong…
if (difference <= 0) {
// add one second so that the count down starts at the full duration
// example 05:00 not 04:59
start = Date.now() + 1000;
if (difference <= 0) {
clearInterval(existingIntervalId);
// add one second so that the count down starts at the full duration
// example 05:00 not 04:59
start = Date.now() + 1000;
The logic is correct, just that you should use diff instead of difference (which is not defined).
if (diff <= 0) {
// add one second so that the count down starts at the full duration
clearInterval(existingInterval);
// example 05:00 not 04:59
start = Date.now() + 1000;
}