seeking explanation for timer tutorial - javascript

Hi everyone I am new to JavaScript and was watching some tutorials on the stopwatch in javascript I manage to understand most of the code but still have some questions. I was wondering can someone help explain the purpose of the interval being null. and how did this code work? how did it prevent the function starts
// Global variables
const time_el = document.querySelector('.watch .time');
const start_btn = document.getElementById('start');
const stop_btn = document.getElementById("stop");
const reset_btn = document.getElementById("reset");
let seconds = 0;
let interval = null;
// Event listeners
start_btn.addEventListener('click', start);
stop_btn.addEventListener("click", stop);
reset_btn.addEventListener("click", reset);
// Update the timer
function timer() {
seconds++;
// Format our time
let hrs = Math.floor(seconds / 3600);
let mins = Math.floor((seconds - (hrs * 3600)) / 60);
let secs = seconds % 60;
if (secs < 10) secs = '0' + secs;
if (mins < 10) mins = "0" + mins;
if (hrs < 10) hrs = "0" + hrs;
time_el.innerText = `${hrs}:${mins}:${secs}`;
}
function start() {
if (interval) {
return
}
interval = setInterval(timer, 1000);
}
function stop() {
clearInterval(interval);
interval = null;
}
function reset() {
stop();
seconds = 0;
time_el.innerText = '00:00:00';
}
<div class="watch">
<div class="time"></div>
</div>
<button id="start">start</button>
<button id="stop">stop</button>
<button id="reset">reset</button>
from running again when I clicked more than once?
function start () {
if (interval) {
return
}
interval = setInterval(timer, 1000);
}
I pasted the whole JS code to give a better context

In javascript null evaluates to false (falsy values): js-falsy, there are also values that evaluate to true (truthy values): js-truthy, so they initialize the variable interval to null so the code knows whether to start the timer, if it doesn't evaluate to false (falsy) the timer has been started and setInterval has been called, so it returns immediately on another click of the start button.
setInterval returns an Interval ID which is a unique identifier: setInterval, this is what is stored in interval on initial start button click, so on subsequent clicks, the variable interval evaluates to true (truthy).
Added a code snippet to demonstrate what I tried to describe in points 1 and 2.
let interval = null;
//Check to see if interval evaluates to false(falsy)
if(!interval){
console.log("interval evaluated to false(falsy)");
}
//set interval to the ID of call to setInterval()
interval = setInterval(() => {
console.log("setInterval() called and interval set to my ID");
}, 1000000);
//Check to see if interval evaluates to true(truthy)
if(interval){
console.log("setInterval ID: " + interval);
console.log("interval evaluated to true(truthy)");
}

Related

how to check if the event is running

I want to create a simple eggtimer app. I created a timer and two buttons start and pause. However, since I'm a beginnner, I cannot work them right. When I hit the start button, the clock is running but if I hit the start button again, the setInterval is triggered again (which I don't want). Therefore, I used {once : true} with the event listener. But consequently when I use the pause button, I cannot resume the clock. I know I should store the event in a boolean, but I don't know how to do it correctly. Can you help me? I know the key things is setting the variable clockIsRunning in the right way. But how?
const startingMinutes = 25;
let time = startingMinutes * 60;
const startBtn = document.querySelector("#start-btn");
const pauseBtn = document.querySelector("#pause-btn");
const resetBtn = document.querySelector("reset-btn");
let interval;
let clockIsRunning = false;
// start button
startBtn.addEventListener("click", startCountdown, false);
const countdownEl = document.querySelector("#countdown");
function updateCountdown() {
const minutes = Math.floor(time / 60);
let seconds = time % 60;
seconds = seconds < 10 ? "0" + seconds : seconds;
countdownEl.innerHTML = `${minutes}:${seconds}`;
time--;
clockIsRunning = true;
}
function startCountdown() {
if ((clockIsRunning = false)) {
interval = setInterval(updateCountdown, 1000);
}
}
// pause button
pauseBtn.addEventListener("click", function() {
clearInterval(interval);
});
<div id="display-container">
<div id="display-timer">
<p id="countdown">25:00</p>
</div>
<p id="display-logo">Focus</p>
</div>
<div id="buttons-container">
<button id="reset-btn">
<i class="fas fa-undo-alt"></i></ion-icon>Reset
</button>
<button id="start-btn"><i class="fas fa-play"></i></ion-icon>Start</button>
<button id="pause-btn"><i class="fas fa-pause"></i></ion-icon>Pause</button>
</div>
if...else take a condition, the code is executed if the boolean is true, not if false.
Knowing setInterval returns and integer (true) and clearInterval returns undefined (false), you can easily have a clock status by assign it to interval directly, thanks to #danh.
/* If clock is not running, start */
if(!interval) {
interval = setInterval(updateCountdown, 1000);
}
/* If clock is running, stop */
if(interval) {
interval = clearInterval(interval); // undefined
}
const startingMinutes = 25;
let time = startingMinutes * 60;
let interval;
const startBtn = document.querySelector("#start-btn");
const pauseBtn = document.querySelector("#pause-btn");
startBtn.addEventListener("click", startCountdown, false);
const countdownEl = document.querySelector("#countdown");
function updateCountdown() {
const minutes = Math.floor(time / 60);
let seconds = time % 60;
seconds = seconds < 10 ? "0" + seconds : seconds;
countdownEl.innerHTML = `${minutes}:${seconds}`;
time--;
}
function startCountdown() {
if(!interval) {
updateCountdown();
interval = setInterval(updateCountdown, 1000);
}
}
// pause button
pauseBtn.addEventListener("click", function() {
if(interval) {
interval = clearInterval(interval);
}
});
<body>
<div id="display-container">
<div id="display-timer">
<p id="countdown">25:00</p>
</div>
</div>
<div id="buttons-container">
<button id="start-btn"><i class="fas fa-play"></i>Start/resume</button>
<button id="pause-btn"><i class="fas fa-pause"></i>Pause</button>
</div>
</body>
You have a few problems here. Your if statement in your startCountdown function assigns false to clockIsRunning, and so will always return false. What you should do is check for equality, i.e. use ==.
Then, if the clock isn't running, have the startCountdown function set the variable to true; this should not be done in the updateCountdown function, since this is run during the interval (i.e. after a second) and so could allow multiple intervals to be set if the Start button is clicked multiple times before the first interval elapses.
Also, in your event listener for the pause button, set clockIsRunning to false. Your code would look something like this:
// interval handler
function updateCountdown() {
const minutes = Math.floor(time / 60);
let seconds = time % 60;
seconds = seconds < 10 ? "0" + seconds : seconds;
countdownEl.innerHTML = `${minutes}:${seconds}`;
time--;
}
// start button
function startCountdown() {
if ((clockIsRunning == false)) {
clockIsRunning = true;
interval = setInterval(updateCountdown, 1000);
}
}
// pause button
pauseBtn.addEventListener("click", function () {
clockIsRunning = false;
clearInterval(interval);
});

Set Interval() and ClearInterval() logic support

having difficulty stopping timer outside of loop. I don't really know why the setTimeout() has been helping the function work... and i know its not the most syntactically correct.. but wondering if someone can help point me as to how to be able to call it outside the function to stop the countdown, say if an action occurs before the timer, and want to call a stopCountdown() function?
function countdown(start){
setTimeout(setCountdown, 1000);
let startingMinutes = timerEl.innerHTML;
startingMinutes = start;
let time = startingMinutes * 60;
function setCountdown(){
const minutes = Math.floor(time/60);
let seconds = time % 60;
if(seconds < 10){
seconds = '0' + seconds
} else {
seconds
}
if(minutes <=0 && seconds <=0){
clearInterval(start);
console.log('timerOver')
} else{
setTimeout(setCountdown, 1000);
timerEl.innerHTML = (minutes + ':'+seconds)
time--;
}
}}
function stopCountdown(){
document.querySelector("#countdown").innerText = '0'
setTimeout(setCountdown(start));
}
Welcome to coding, I am trying my best to explain it. First, let me point out some of my opinion on your code
function countdown(start){
setTimeout(setCountdown, 1000);
let startingMinutes = timerEl.innerHTML;
startingMinutes = start;
// I am not sure why you firstly initializing startMinutes
// to the value of timerEl.innerHTML
//and then reassign the value of startMinutes to variable start next line
let time = startingMinutes * 60;
function setCountdown(){
const minutes = Math.floor(time/60);
let seconds = time % 60;
if(seconds < 10){
seconds = '0' + seconds
} else {
seconds
}
if(minutes <=0 && seconds <=0){
clearInterval(start); // you are using setTimeout, not setInterval
console.log('timerOver')
} else{
setTimeout(setCountdown, 1000);
timerEl.innerHTML = (minutes + ':'+seconds)
time--;
}
}}
function stopCountdown(){
document.querySelector("#countdown").innerText = '0'
setTimeout(setCountdown(start));
// when calling stopCountdown(), what is the value of start?
// you can't access function setCountdown inside function stopCountdown
}
If my guess is correct, you want to make a timer and then you can make it stop when calling a stopCountdown function, right?
For a timer, it is simply asking javascript to - 1 seconds for every 1000 ms passed. So we can write a function which -1 seconds and ask JS to run it every 1000ms, right?
In this case, you should use setInterval but not setTimeout (setTimeout can also make a timer, I will also show you). The difference is that setTimeout calls a function ONCE after X milliseconds and setInterval will run a function EVERY X milliseconds.
Here is the code
let countdownIntervalId // get the countdownIntervalId outside by first declearing a variable to catch the id
function countdown(start) { // assume the unit of start is minute
console.log("countdown called, minutes =" + start)
// add code here to change the innerHTML of the timer if you want
let secondsToCount = start * 60; //Converting minutes to seconds
countdownIntervalId = setInterval(() => {
timer()
}, 1000); // starting to count down
function timer() { // run every seconds
const minutes = Math.floor(secondsToCount / 60);
let seconds = secondsToCount - minutes*60;
console.log("counter= " + minutes + ':' + `${seconds}`.padStart(2, '0'))
secondsToCount = secondsToCount-1;
if (minutes <= 0 && seconds <= 0) {
clearInterval(countdownIntervalId); // clearInterval
console.log('timerOver')
}
}
}
function stopCountdownOutside(){
if(countdownIntervalId){
clearInterval(countdownIntervalId)
}
}
countdown(2) //countdown 2 mins
You can stop the counter by calling stopCountdownOutside(), you can test on Chrome console. This is because we are passing the intervalId to the countdownIntervalId which is declare outside the function. so we can simply call clearInterval(countdownIntervalId) to stop it
For using the setTimeout
let countdownTimeoutId// get the countdownIntervalId outside by first declearing a variable to catch the id
function countdown(start) { // assume the unit of start is minute
console.log("countdown called, minutes =" + start)
// add code here to change the innerHTML of the timer if you want
let secondsToCount = start * 60; //Converting minutes to seconds
countdownTimeoutId = setTimeout(() => {
timer()
}, 1000); // starting to count down
function timer() { // run every seconds
const minutes = Math.floor(secondsToCount / 60);
let seconds = secondsToCount - minutes*60;
console.log("counter= " + minutes + ':' + `${seconds}`.padStart(2, '0'))
secondsToCount = secondsToCount-1;
if (minutes <= 0 && seconds <= 0) {
clearTimeout(countdownTimeoutId); // clearTimeout
console.log('timerOver')
}else{
countdownTimeoutId = setTimeout(timer,1000)
}
}
}
function stopCountdownOutside(){
if(countdownTimeoutId){
clearTimeout(countdownTimeoutId)
}
}
countdown(1) //countdown 2 mins
you can try to refactor my code to a more clean version, happy coding

reset timer back to 0 by using the timer setInterval/clearInterval for stopwatch

Im working on code for a simple stopwatch. Last obstacle for me is reset the time to zero. The function resetTimer is where i am trying to implement the code. So the webpage will display a page with a timer and three buttons; stop, start and reset. When a user clicks the reset button, the timer is supposed to reset back to zero. I have been having trouble trying to make it work. Any help/ideas would be clutch.
I hope i made myself clear. Again i am trying to make the timer reset to 00:00:00
window.onload = function () {
//grab possible elements needed
const timerEl = document.getElementById("timer-text")
const startBtn = document.getElementById("start")
const restartBtn = document.getElementById("restart");
const stopBtn = document.getElementById('stop');
//hold variables of time and set to 0
let hours = parseInt('0');
let minutes = parseInt('0');
let seconds = parseInt('0');
let time;
function makeTwoNumbers(num) {
if (num < 10) {
return "0" + num
}
return num
}
//timer
let timer = () => {
seconds++
//console.log(seconds)
if (seconds == 60) {
minutes++
seconds = 0;
hours = 0
}
if (minutes == 60) {
hours++
minutes = 0;
hours = 0;
}
timerEl.textContent = makeTwoNumbers(hours)+ ": " + makeTwoNumbers(minutes) + ": " + makeTwoNumbers(seconds);
}
let runTheClock;
//timer is running
function runTimer() {
runTheClock = setInterval(timer, 20);;
}
function stopTimer() {
clearInterval(runTheClock)
}
//function will reset timer
function resetTimer() {
time--;
timerEl.textContent;
if (time === 0) {
stopTimer();
time = 0
}
}
restartBtn.addEventListener("click", function () {
resetTimer();
})
//button will pause the timer
stopBtn.addEventListener("click", function () {
stopTimer();
})
//button will start the timer
startBtn.addEventListener("click", function () {
runTimer();
})
}
Here's a fixed and slightly refactored version.
<html>
<body>
<div id="timer-text"></div>
<button id="start">start</button>
<button id="restart">restart</button>
<button id="stop">stop</button>
</body>
<script>
const timerEl = document.getElementById("timer-text")
const startBtn = document.getElementById("start")
const restartBtn = document.getElementById("restart");
const stopBtn = document.getElementById('stop');
let runTheClock;
let seconds = 0;
render(seconds);
function makeTwoNumbers(num) {
return ((num < 10) ? "0" : "") + num;
}
function tick() {
seconds++;
render(seconds);
}
function render(secs) {
const hours = Math.floor(secs / 3600);
const minutes = Math.floor(secs / 60) - (hours * 60);
const seconds = secs % 60;
const val = [hours, minutes, seconds].map(makeTwoNumbers).join(":");
console.log(val);
timerEl.textContent = val;
}
function runTimer() {
runTheClock = setInterval(tick, 1000);
}
function stopTimer() {
clearInterval(runTheClock)
}
function resetTimer() {
seconds = 0;
render(seconds);
}
restartBtn.addEventListener("click", resetTimer);
stopBtn.addEventListener("click", stopTimer);
startBtn.addEventListener("click", runTimer);
</script>
</html>
In the reset function it just sets seconds back to 0 and sets the textContent value so it appears on the page. I separated out the calculating and drawing of the time into a render fucntion, so it can be reused whenever it needs to be re-rendered.
To explain the render function.
We only need to store the number of seconds as a persistent variable between the periodic function calls. We can derive hours and minutes from it. This makes it much less error prone than trying to increment hours and minutes as well.
To calculate hours we just divide seconds by 3600 (or 60 x 60 the number of seconds in an hour) and round down.
To calculate minutes we can calculate the number of total minutes (seconds / 60 and round down) then subtract the number of minutes in the hours value we calculated (hours * 60).
For seconds we use modulus or % which is just a fancy word for remainder. So seconds % 60 gives us the remainder value of seconds / 60. For example 61 % 60 = 1. This isn't the only way these values could be calculated.
To build the display string. I just put all of the hours, minutes and seconds in an array. Then used the map method, which applies the function makeTwoNumbers to all of the values. I then used the join method to join all the strings using the delimiter :. It just saves some typing and means you only reference makeTwoNumbers once, making it less work to use a different function later if you want to.
Hope that helps.
I realized that you could simply reset seconds, hours, and minutes to 0 and use a variable true. This would reset it entirely to 0. I couldnt believe how simple it was

How do I stop and reset a setInterval timer

How do I stop and reset this setInterval timer back to 00:00?
Setting clearInterval(timer); works for stopping the time but I can't figure out how to reset the time value back to 00:00.
Here's where I'm at:
HTML
<span class="timer">
<label id="minutes">00</label>:<label id="seconds">00</label>
</span>
JS
const minutesLabel = document.getElementById("minutes");
const secondsLabel = document.getElementById("seconds");
let timer = setInterval(setTime, 1000);
function setTime() {
++totalSeconds;
secondsLabel.innerHTML = pad(totalSeconds % 60);
minutesLabel.innerHTML = pad(parseInt(totalSeconds / 60));
}
function pad(val) {
let valString = val + "";
if (valString.length < 2) {
return "0" + valString;
} else {
return valString;
}
}
stopTimer = () => {
clearInterval(timer);
timer = setInterval(setTime, 1000);
};
I'm using this timer in a game so based on the users state I need to be able start, stop, and restart the time back to 0.
What's happening now is that your variable keeps going up, even when you "reset" the timer.
Simply add
totalSeconds = 0;
to your stopTimer function. This will reset the variable to zero.
The variable totalSeconds keeps track of your time.
The name of your function stopTimer() - maybe it should be restartTimer - seems a bit misleading since you're restarting the timer there but basically just set totalSeconds to 0 like:
stopTimer = () => {
totalSeconds = 0;
clearInterval(timer);
timer = setInterval(setTime, 1000);
};

Countdown Timer not Stopping with clearInterval()

I'm having a problem get this countdown timer to stop at zero so the time won't show as a negative value. The console.log is getting called and works fine but for some reason the clearInterval() is not. This is driving me crazy and I'm close to quitting.
const timerContainer = document.getElementById('timerContainer');
const THREEMINUTES = 60 * 0.1;//5 seconds for testing
startTimer(THREEMINUTES, timerContainer);
function startTimer(duration, display) {
let start = Date.now();
let diff, min, sec;
let timer = () => {
diff = duration - (((Date.now() - start) / 1000) | 0);
//use bitwise to truncate the float
min = (diff / 60) | 0;
sec = (diff % 60) | 0;
min = min < 10 ? '0' + min : min;
sec = sec < 10 ? '0' + sec : sec;
display.textContent = min + ':' + sec;
if (diff <= 0) {
stopTimer();
submit.disabled = 'true';
};
};
//call timer immediately otherwise we wait a full second
timer();
setInterval(timer, 1000);
function stopTimer() {
clearInterval(timer);
console.log("time's up", diff);
};
}
<div id="timerContainer"></div>
You are not saving the result of setInterval(timer, 1000);
you should use this:
let timerId;
timer();
timerId = setInterval(timer, 1000);
function stopTimer() {
clearInterval(timerId);
console.log("time's up", diff)
};
As you might see, the result of setInterval is a number (object in node), and all you then need to do is pass that value to clearInterval thus we save the value in the variable timerId for reference.
Don't pass the function that you want stopped to clearInterval().
Pass a reference to the timer that you started, so you need to make sure that when you start a timer, you capture a reference to the ID that will be returned from it.
// Function that the timer will invoke
function callback(){
. . .
}
// Set up and initiate a timer and capture a reference to its unique ID
var timerID = setInterval(callback, 1000);
// When needed, cancel the timer by passing the reference to it
clearInterval(timerID);
The code is fixed make sure you fix your submit button code.
You should first assign the value of setInterval to a variable. That variable is used while calling clearInterval which infact clears the interval.
const timerContainer = document.getElementById('timerContainer');
const THREEMINUTES = 60 * 0.1;//5 seconds for testing
startTimer(THREEMINUTES, timerContainer);
var timer = null;
function startTimer(duration, display) {
let start = Date.now();
let diff, min, sec;
let timer = () => {
diff = duration - (((Date.now() - start) / 1000) | 0);
//use bitwise to truncate the float
min = (diff / 60) | 0;
sec = (diff % 60) | 0;
min = min < 10 ? '0' + min : min;
sec = sec < 10 ? '0' + sec : sec;
display.textContent = min + ':' + sec;
if (diff <= 0) {
stopTimer();
submit.disabled = 'true';
};
};
//call timer immediately otherwise we wait a full second
timer();
timer = setInterval(timer, 1000);
function stopTimer() {
clearInterval(timer);
console.log("time's up", diff);
};
}

Categories

Resources