Making a countdown timer?

im trying to make a countdown script
The tricky part is the startTime comes in 00:00:00 format which is minutes:seconds:hundredeths
how do I convert the time var (startTime) to where I can Count minutes, seconds, ans hundredths
This is what I have so far (not much)

function startCountdown () {

var minutes = startTime.subst(0, 2);
var seconds = startTime.subst(3, 2);
var hundredths = startTime.subst(6,2);

setInterval(runClock, 10)

}
function runClock {

    if(hundredths == 0) {
    seconds--;
    } else {
    hundredths --;
    }

    if(seconds== 0) {
    minutes--;
    } else {
   seconds--;
    }

}

Am I on the right track?

Why not stick a console.log call in the function and run it to see what it does.

You might want to add some code to stop the setInterval after minutes reaches zero so as to not end up in an infinite loop but closing the page without closing the console will allow you to see what the current code is doing.

ok, I have

var minutes = startTime.substr(0, 2);
var seconds = startTime.substr(3, 2);
var hundredths = startTime.substr(6,2);
		
var timeinterval = setInterval(runClock(minutes,seconds,hundredths), 10)
		
if(minutes == 0 && seconds == 0 && hundredths == 0) {
    clearInterval(timeinterval);
    document.getElementById("clockdiv").innerHTML = "<h1>Times up!</h1>";
} 

and heres the function

function runClock(minutes,seconds,hundredths) {

    console.log("M:"+minutes);
    console.log("S:"+seconds);
    console.log("H:"+hundredths);

    if(hundredths == 0) {
        seconds--;
    } else {
        hundredths --;
    }

    if(seconds== 0) {
        minutes--;
    } else {
       seconds--;
    }

}

Here’s the result


so im not getting an error & the variables are right… how do I get the function to count down?

ok, made a few changes to my code, heresa my 2 functions,

function timerStart() {
	var startTime = document.getElementById("Timer_Start").value;

//check format for user input
	if( startTime.match(/^[0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/)) {
	  document.getElementsByClassName("Error")[0].innerHTML = "";
	  document.getElementById("Timer_Form").style.display = "none";
	  document.getElementById("clockdiv").style.display = "block";
	  
	  var minutes = startTime.substr(0, 2);
	  var seconds = startTime.substr(3, 2);
	  var hundredths = startTime.substr(6,2);
	  	
      var timeinterval = setInterval(runClock(minutes,seconds,hundredths), 10)
	} else {
	  document.getElementsByClassName("Error")[0].innerHTML = "Please use correct format (00:00:00)";
	  document.getElementById("Timer_Start").focus();
	}
}
function runClock(minutes,seconds,hundredths) {

console.log("M:"+minutes);
console.log("S:"+seconds);
console.log("H:"+hundredths);

 		if (minutes < 10) {
			minutes = "0" + minutes;  
		}
 
		if (seconds < 10) {
			seconds = "0" + seconds;  
		}
		
		document.getElementById('clockdiv').innerHTML ="<h1>"+ minutes + ":" + seconds +":"+hundredths+"</h1>";
		if (hundredths == 0) {
			clearInterval(timeinterval);
			document.getElementById("clockdiv").innerHTML = "<h1>Times up!</h1>";
		} else {
			hundredths--;
		}
		if (seconds == 0) {
			hundredths--;
		} else {
			seconds--;
		}
		if (minutes == 0) {
			seconds--;
		} else {
			minutes--;
		}
}

and heres the result


so at least I dont get an error, but what confuses me is did I not set it up right to fire off the runClock method a .1 second intervals? Cause the console just shows 1 time?

Here’s the line:

var timeinterval = setInterval(runClock(minutes,seconds,hundredths), 10)

What is happening there, is that the return value from the runClock() function is being assigned to run every 10 milliseconds. The runClock function has no return value, so nothing much will happen other than the runClock function being run just the once when setting up the interval.

What you need to have happen, is to use a wrapper function, so that the minutes seconds and hundredths can then be passed to the runClock function.

function runClockWrapper(minutes, seconds, hundredths) {
  return function closureWrapper() {
    runClock(minutes, seconds, hundredths);
  }
}
...
var timeinterval = setInterval(runClockWrapper(minutes,seconds,hundredths), 10)

What happens here is that the returned function is given to setInterval, which retains knowledge of the variables (via closure), so that each time the closureWrapper function is run, the runClock function can update the variables from one run to the next.

You still have many other issues to sort out though, so good luck.

1 Like

ok, but now when the function runs the vars seem to not change, I have this code

function runClock(minutes,seconds,hundredths) {

console.log("M:"+minutes);
console.log("S:"+seconds);
console.log("H:"+hundredths);

		
		document.getElementById('clockdiv').innerHTML ="<h1>"+ twoDigits(minutes) + ":" + twoDigits(seconds) +":"+twoDigits(hundredths)+"</h1>";
		if ((hundredths == 0) && (seconds == 0) && (minutes ==0)) {
			clearInterval(timeinterval);
			document.getElementById("clockdiv").innerHTML = "<h1>Times up!</h1>";
		} else {
			if (hundredths == 0) {
			hundredths = 99;
		    } else {
			hundredths--;
		    }
		    if (seconds == 0) {
			hundredths = 99;
		    } else {
			seconds--;
		    }
		    if (minutes == 0) {
			seconds= 99;
 		    } else {
			minutes--;
		    }
		}
}

shouldn’t that count down the variables, er looking at the if statement has me thinking I didn’t set it up right.
Can you help me with the logic there?

You didn’t post your runClockWrapper function

You’re going about it the wrong way, you can’t decrement the hour, minute, seconds like that if you want the timer to be realistic. Instead you need to get the startTime in milliseconds and then do some simple math on the elapsed time to turn milliseconds into hours,minutes,seconds,hundreths.

var startTime = null;

var start = function() {
  startTime = new Date().getTime()
  tick()
}

var tick = function() {
  var time = new Date().getTime()
  var ms = time - startTime

  var hours = Math.floor((ms / (60 * 60 * 1000)));
  var minutes = Math.floor((ms / (60 * 1000)) % 60);
  var seconds = Math.floor((ms / 1000) % 60);
  var hundreths = Math.floor((ms / 10) % 60);

  console.log(hours, minutes, seconds, hundreths);
  setTimeout(tick, 100)
}

start()
1 Like

ok…

If the time comes in as minutes: seconds: hundredths (like 99:99:99)
How do I convert that to ms
I can split the string into three variables (minutes, seconds, hundredths) like

var minutes = startTime.substr(0, 2);
var seconds = startTime.substr(3, 2);
var hundredths = startTime.substr(6,2);

(((minutes * 60) + seconds) * 100) + hundredths) * 10

You’ll want to have an `end’ reference for when the timer is to end.

var start = new Date();
var end = new Date(start.getTime() +
    minutes * 60 * 1000 + seconds * 1000 + hundreths * 10);

After which you can get a current curr reference, and work out the difference from the end.

var curr = new Date();
var diff = end.getTime() - curr.getTime();

var minutes = parseInt(diff / 60000, 10);
var seconds = parseInt((diff - (minutes * 60000)) / 1000, 10);
var hundreths = (diff / 10) % 100;

if diff is less than zero, you’ll have reached the end of the timer and can zero all of the numbers.

ok, man this is frustrating for me
but heres my function

function startTimer() {
	var startTime = document.getElementById("Timer_Start").value;

//check format for user input
	if( startTime.match(/^[0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/)) {
	  document.getElementsByClassName("Error")[0].innerHTML = "";
	  document.getElementById("Timer_Form").style.display = "none";
	  document.getElementById("clockdiv").style.display = "block";
	  
	  var minutes = startTime.substr(0, 2);
	  var seconds = startTime.substr(3, 2);
	  var hundreths = startTime.substr(6,2);
	 
	  var start = new Date();
	  var end = new Date(start.getTime() + minutes * 60 * 1000 + seconds * 1000 + hundreths * 10); 	
	  tick();
          ...
	}
}

then heres the tick function

var tick = function() {
  var curr = new Date();
  var ms = end.getTime() - curr.getTime();

  var minutes = Math.floor((ms / (60 * 1000)) % 60);
  var seconds = Math.floor((ms / 1000) % 60);
  var hundreths = Math.floor((ms / 10) % 60);
	if(ms == 0) {
		clearInterval(tick);
		document.getElementById("clockdiv").innerHTML = "<h1>Times up!</h1>";
	} else {
		console.log(twoDigits(minutes) + ":" + twoDigits(seconds) +":"+twoDigits(hundreths));
		setTimeout(tick, 10)
		
	}
}

I changed the diff variable to ms but is the if statement correct to stop the ticking when ms == 0?
Thanks

You will be extremely unlikely to finish (about 50,000 to 1 odds) if you’re checking that a millisecond measurement has a precise difference of zero.

Instead, check if it’s less than or equal to zero.

1 Like

ok, here my main function which calls tick() and stops it (is that what you meant?

function startTimer() {
	var startTime = document.getElementById("Timer_Start").value;

//check format for user input
	if( startTime.match(/^[0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/)) {
	  document.getElementsByClassName("Error")[0].innerHTML = "";
	  document.getElementById("Timer_Form").style.display = "none";
	  document.getElementById("clockdiv").style.display = "block";
	  
	  var minutes = startTime.substr(0, 2);
	  var seconds = startTime.substr(3, 2);
	  var hundreths = startTime.substr(6,2);
	 
	  var start = new Date();
	  var end = new Date(start.getTime() + minutes * 60 * 1000 + seconds * 1000 + hundreths * 10); 	
	  tick();
	} else {
	  document.getElementsByClassName("Error")[0].innerHTML = "Please use correct format (00:00:00)";
	  document.getElementById("Timer_Start").focus();
	}
}
var tick = function() {
  var curr = new Date();
  var ms = end.getTime() - curr.getTime();

  var minutes = Math.floor((ms / (60 * 1000)) % 60);
  var seconds = Math.floor((ms / 1000) % 60);
  var hundreths = Math.floor((ms / 10) % 60);
	if(ms <= 0) {
		clearInterval(tick);
		document.getElementById("clockdiv").innerHTML = "<h1>Times up!</h1>";
	} else {
		console.log(twoDigits(minutes) + ":" + twoDigits(seconds) +":"+twoDigits(hundreths));
		setTimeout(tick, 100)
		
	}
}

but when it runs

end is limited to the startTimer function scope, you need to move that variable definition outside of the function to be shared.

var end = null;

function startTimer() {
  ... 
  end = blah;
}

that got rid of that error, but gave me a new one

That error will be on this line, with the end variable:

var ms = end.getTime() - curr.getTime();

Could it be that you have some other var end statement elsewhere that’s causing the problem?

I took markbrowns suggestion &

var end = null;

outside the scope so now my code is

var end = null;
function startTimer() {
	var startTime = document.getElementById("Timer_Start").value;

//check format for user input
	if( startTime.match(/^[0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/)) {
	  document.getElementsByClassName("Error")[0].innerHTML = "";
	  document.getElementById("Timer_Form").style.display = "none";
	  document.getElementById("clockdiv").style.display = "block";
	  
	  var minutes = startTime.substr(0, 2);
	  var seconds = startTime.substr(3, 2);
	  var hundreths = startTime.substr(6,2);
	 
	  var start = new Date();
	  var end = new Date(start.getTime() + minutes * 60 * 1000 + seconds * 1000 + hundreths * 10); 	
	  tick();
	} else {
	  document.getElementsByClassName("Error")[0].innerHTML = "Please use correct format (00:00:00)";
	  document.getElementById("Timer_Start").focus();
	}
}
var tick = function() {
  var curr = new Date();
  var ms = end.getTime() - curr.getTime();

  var minutes = Math.floor((ms / (60 * 1000)) % 60);
  var seconds = Math.floor((ms / 1000) % 60);
  var hundreths = Math.floor((ms / 10) % 60);
	if(ms <= 0) {
		clearInterval(tick);
		document.getElementById("clockdiv").innerHTML = "<h1>Times up!</h1>";
	} else {
		console.log(twoDigits(minutes) + ":" + twoDigits(seconds) +":"+twoDigits(hundreths));
		setTimeout(tick, 100)
		
	}
}

Look!

/me points, finger excitedly extended towards the code

There IS some other line that has var end on it.

1 Like

Am I seeing an old_time minus now_time?

I guess negative time values can work, but wouldn’t you also want to get the absolute value of the negative?