problem with clearInterval() in javascript - javascript

I made a simple little timer with a start, reset, plus a nonfunctional stop button. All the documentation that I have read on it makes it seem very simple so I have no idea what's going wrong.
the stop.onclick function is getting read, but it only works for a second before it gets overwritten by the setInterval function
ps- I intend to improve the accuracy so please no hints on how best to do that
const start = document.getElementById("button1")
const stop = document.getElementById("stop")
const reset = document.getElementById("reset")
var clock = start.onclick = function(){
let seconds = 1
let minutes = 0
setInterval(function() {
if (minutes == 0){
if (seconds < 10)
timer.innerHTML = '0:0' + seconds++;
else
timer.innerHTML = '0:' + seconds++;
if (seconds == 60){
minutes++
seconds = 0
}
}
else {
if (seconds < 10)
timer.innerHTML = minutes + ':0' + seconds++;
else
timer.innerHTML = minutes + ':' + seconds++;
if (seconds == 60){
minutes++
seconds = 0
}
}
}, 1000);
reset.onclick = function(){
seconds = 0
}
stop.onclick = function(){
let display = seconds
timer.innerHTML = display
clearInterval(clock)
// alert("You stopped the clock!")
}
}
```

The problem is that that is not how setInterval and clearInterval work. Specifically, you don't pass clearInterval the function that you have running at some interval to clear the interval. Instead, setInterval returns a reference to the process; you can then pass that reference to clearInterval to clear it. For instance:
const myIntervalProcess = setInterval(() => console.log('hi'), 1000);
setTimeout(() => clearInterval(myIntervalProcess), 5000);
What we see above is that we set a function that logs "hi" to the console every second. We save the reference returned from setInterval to a variable called myIntervalProcess. Then we set a timeout to pass myIntervalProcess to clearInterval after five seconds. If you run this you can see that "hi" will be logged to console exactly five times, after which point it will cease.
If we apply this fix to your code we get:
const start = document.getElementById("button1")
const stop = document.getElementById("stop")
const reset = document.getElementById("reset")
var clock = start.onclick = function(){
let seconds = 1
let minutes = 0
const clockProcess = setInterval(function() {
if (minutes == 0){
if (seconds < 10)
timer.innerHTML = '0:0' + seconds++;
else
timer.innerHTML = '0:' + seconds++;
if (seconds == 60){
minutes++
seconds = 0
}
}
else {
if (seconds < 10)
timer.innerHTML = minutes + ':0' + seconds++;
else
timer.innerHTML = minutes + ':' + seconds++;
if (seconds == 60){
minutes++
seconds = 0
}
}
}, 1000);
reset.onclick = function(){
seconds = 0
}
stop.onclick = function(){
let display = seconds
timer.innerHTML = display
clearInterval(clockProcess)
// alert("You stopped the clock!")
}
}
Also, for what it's worth, you may wish to use a linter on your code-- I see some missing semicolons and other errors/inconsistencies it would help you catch and resolve. Good luck!

Related

How do I add clearInterval to my JS timer?

I've made a timer in JavaScript, but when the start button is repeatedly clicked it keeps getting faster. I know clearInterval is used to stop this, but depending on where I put it in the code it either stops the timer from working completely or makes no difference. This is the code, I put it on the fourth line but it's not doing anything:
var minutes;
var seconds;
function PomodoroBreak(x){
clearInterval(interval)
minutes = x;
seconds = 0;
var interval = setInterval(
function(){
var el = document.getElementById("timer")
if(seconds ==0 && minutes==0){
clearInterval(interval)
el.innerHTML = "00:00"
}
else if(seconds == 0){
minutes = minutes -1;
seconds = 59
el.innerHTML = minutes + ":" + seconds
}else if(seconds > 0){
seconds = seconds -1;
el.innerHTML = minutes + ":" + seconds
document.title = minutes + ":" + seconds
}
},
1000
)
}
Where am I supposed to put it instead, or have I done something else wrong? Thank you!
I'm seeing some adjustments to be done here. I believe returning clearInterval with the startTimer declared above should do the work.
Hope this helps.
function PomodoroBreak(x){
var minutes = x;
var seconds = 0;
let startTimer = setInterval(...,1000)
return clearInterval(startTimer)
}
I think you should declare the variable “interval“ outside the function. And remove the var in the function.
var minutes;
var seconds;
var interval;
function PomodoroBreak(x){
clearInterval(interval)
minutes = x;
seconds = 0;
interval = setInterval(
function(){
var el = document.getElementById("timer")
if(seconds ==0 && minutes==0){
clearInterval(interval)
el.innerHTML = "00:00"
}
else if(seconds == 0){
minutes = minutes -1;
seconds = 59
el.innerHTML = minutes + ":" + seconds
}else if(seconds > 0){
seconds = seconds -1;
el.innerHTML = minutes + ":" + seconds
document.title = minutes + ":" + seconds
}
},
1000
)
}

Repeat timer infinite amount of times

I am trying to add a countdown timer to my Shopify checkout using Google Optimize. I got this to work using the following HMTL & JS. Taken from here
However once the timer finishes and I reload the page it starts from 17 seconds instead of 5 minutes.
Is there a way to get this to repeat the timer from 5 minutes once it hits 0?
document.getElementById('timer').innerHTML =
05 + ":" + 00;
startTimer();
function startTimer() {
var presentTime = document.getElementById('timer').innerHTML;
var timeArray = presentTime.split(/[:]+/);
var m = timeArray[0];
var s = checkSecond((timeArray[1] - 1));
if(s==59){m=m-1}
if(m<0){
return
}
document.getElementById('timer').innerHTML =
m + ":" + s;
console.log(m)
setTimeout(startTimer, 1000);
}
function checkSecond(sec) {
if (sec < 10 && sec >= 0) {sec = "0" + sec}; // add zero in front of numbers < 10
if (sec < 0) {sec = "59"};
return sec;
}
<div>Your cart is reserved for <span id="timer"></span></div>
If you could give the answer like you are talking to a complete beginner it would be greatly appreciated.
Looks like I have a lot to learn!
Welcome to StackOverflow. This should help out...
//JAVASCRIPT
startTimer(5); // SPECIFY AMOUNT OF MINUTES OR NO PARAMETER FOR DEFAULT 5
function startTimer(minutes = 5){
var timeout = minutes * 60000;
var ms = timeout;
var interval = setInterval(function(){
ms -= 1000;
if(ms >= 0) {
var d = new Date(1000*Math.round(ms/1000));
document.getElementById('timer').innerHTML = getMS(d);
} else {
startTimer(5); // MAKE TIMER RESTART AGAIN FOR 5 MINS
// clearInterval(interval); // TO MAKE TIMER STOP UPON REACHING 0:00
}
}, 1000);
}
function getMS(d){
return pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds());
}
function pad(i) {
return ('0'+i).slice(-2);
}
<!--HTML -->
<body>
<div>Your cart is reserved for <span id="timer"></span></div>
</body>
In javascript the setInterval function allow you to make anything you want every fixed ms.
interval = setInterval(() => {
console.log('Waited for 5m');
// Do whatever you want
console.log('Waiting for 5m again...');
}, 300000);
// To stop the interval
clearInterval(interval);

Adding time on button click to a count down timer

Im creating a countdown timer which starts at 3mins and 30secs.
When the timer reaches 0 the initial 3:30 timer will be repeated.
This happens until the user presses a button, which will add 1:45 to the timer and pause the timer until the user decides to resume the timer from the new value. Eg ( 3:30 + 1:45 = 5:15).
Now I have got the first 2 step to work with my current code, but I'm having a lot of issues with the 3rd part. Once the user clicks the add 1.45 button the count works, but only up until a certain point. After this point it will start to display a negative integer.
I'm sure there is an easier way to write this code. I have really overcomplicated this. Any suggestions would be appreciated.
//Define vars to hold time values
let startingMins = 3.5;
let time = startingMins * 60;
//define var to hold stopwatch status
let status = "stopped";
//define var to holds current timer
let storeTime = null;
//define Number of sets
let setNum = 1;
//Stop watch function (logic to determin when to decrement each value)
function stopwatch () {
minutes = Math.floor(time / 60);
let seconds = time % 60;
seconds = seconds < 10 ? '0' + seconds : seconds;
storeTimer = minutes + ":" + seconds; //Store time in var
storeTime = minutes + "." + seconds; //Store time in var
//Display updated time values to user
document.getElementById("display").innerHTML = storeTimer;
time--;
// When timer reachers 0 secs the inital 3:30 countdown will begin again.
if (time <= 0) {
startingMins = 3.5;
time = startingMins * 60;
minutes = Math.floor(time / 60);
seconds = time % 60;
seconds = seconds < 10 ? '0' + seconds : seconds;
setNum++;
//console.log(setNum);
}
}
function StartStop() {
if(status === "stopped") {
//start watch
interval = window.setInterval(stopwatch, 100);
var startButton = document.getElementById("start");
document.getElementById("start").innerHTML = "Pauce";
//startButton.style.display = "none"
status = "start";
//console.log(time);
}
else {
window.clearInterval(interval);
document.getElementById("start").innerHTML = "Start";
status = "stopped";
console.log(storeTime);
}
}
function pauceAdd () {
if(status === "stopped") {
//start watch
interval = window.setInterval(stopwatch, 1000);
var zukButton = document.getElementById("pauceAdd");
status = "start";
}
else {
window.clearInterval(interval);
status = "stopped";
console.log("store time " + storeTime);
let time = +storeTime + +1.45; //store time is 3.30 adding 4.75
console.log("store time2 " + time); // correct result 4.75
minutes = Math.floor(time);/// convert time from Mins (4.75) to seconds (475)
let seconds = time % 60; // 5
if (seconds < 60 ) { // if the Stored time is greater than 60 secs add 1 minute to the timer
minutes++;
seconds = seconds * 100;
console.log("secs updated = " + seconds ); // seconds updated (475)
if (seconds <= 460) {
seconds = Math.floor(seconds - 460);
console.log("seconds 2 == " + seconds)
}
else if (seconds > -60) { // Stuck here
seconds = seconds + 60;// Stuck here
}// Stuck here
else {
seconds = Math.floor(seconds - 460);
console.log("seconds 2 = " + seconds)
}
}
if (seconds < 1) {
seconds = seconds + 60;
minutes = minutes - 1;
}
seconds = seconds < 10 ? + seconds : seconds;
console.log("mins updated = " + minutes + "__________________________-");
//Display updated time values to user
document.getElementById("display").innerHTML = minutes + ":" + seconds;
}
}
function reset () {
//window.clearInterval(storeTime);
window.clearInterval(interval);
startingMins = 3.5;
time = startingMins * 60;
minutes = Math.floor(time / 60);
seconds = time % 60;
seconds = seconds < 10 ? '0' + seconds : seconds;
status = "stopped";
setNum = 1;
var startButton = document.getElementById("start");
startButton.style.display = "inline-block";
document.getElementById("display").innerHTML = "3:30";
document.getElementById("start").innerHTML = "Start";
}
I might have taken the requirements a bit too literally:
Im creating a countdown timer which starts at 3mins and 30secs.
When the timer reaches 0 the initial 3:30 timer will be repeated.
This happens until the user presses a button, which will add 1:45 to the timer and pause the timer until the user decides to resume the
timer from the new value. Eg ( 3:30 + 1:45 = 5:15).
There's a trick to countdown timers. You have to use timestamps to find out how much time ACTUALLY elapsed. You can't trust that your interval will fire exactly every second. In fact, it almost always fires a bit later (in my tests, about 2-3 milliseconds, but I was logging to the console as well, so that might have skewed the test).
let interval, timestamp;
let countdown = 210000;
document.addEventListener("DOMContentLoaded", () => {
document
.querySelector("button")
.addEventListener("click", (event) => toggleState(event.target));
});
function toggleState({ dataset }) {
timestamp = Date.now();
if (dataset.state == "running") {
clearInterval(interval);
countdown += 105000;
updateDisplay(dataset, "paused");
} else {
interval = setInterval(() => updateCountdown(dataset), 100);
updateDisplay(dataset, "running");
}
}
function updateCountdown(dataset) {
const now = Date.now();
countdown -= now - timestamp;
if (countdown <= 0) countdown = 210000;
timestamp = now;
updateDisplay(dataset, "running");
}
function updateDisplay(dataset, label) {
dataset.state = label;
dataset.time = `(${new Date(countdown).toISOString().slice(14, 19)})`;
}
button::before {
content: attr(data-state);
}
button::after {
content: attr(data-time);
padding-left: 0.5em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" rel="stylesheet" />
<button data-state="stopped" data-time="(03:30)"></button>

javascript timer keeps reseting too soon (not working)

// This timer keeps reseting back to 2:00 after it reaches 1 minute. Also i do not get a notification that says times up at the right time. Can someone please correct the code. Also the stop/resume timer button also has to stay functional.
var isRunning = false;
var ticker; //this will hold our setTimeout
var seconds,
minutes;
function countdown(mins, secs) {
//i made these global, so we can restart the timer later
seconds = secs || 60; //if user put in a number of minutes, use that. Otherwise, use 60
minutes = mins;
console.log('time stuff',mins,secs,minutes,seconds)
function tick() {
var counter = document.getElementById("timer");
var current_minutes = mins - 1
seconds--;
counter.innerHTML =
current_minutes.toString() + ":" + (seconds < 10 ? "0" : "") + String(seconds);
if (seconds < 1 && minutes) {
//seconds reached 0, and still minutes left;
seconds=60;
minutes--;
}
if ((seconds > 0 || minutes > 0) && isRunning) {
ticker = setTimeout(tick, 1000);
} else if(isRunning){
console.log(seconds,minutes,isRunning)
alert('Time\'s up, brah!')
}
}
tick();
}
function timeToggle() {
isRunning = !isRunning; //if it's false, set it true. If it's true, set it false.
if (!isRunning) {
clearTimeout(ticker); //or whatever else you set the initial timeOut to.
} else {
//not running! and time is defined;
var sec = seconds||60;
console.log('def!',minutes, sec)
countdown(minutes, sec);
}
}
isRunning = true;
countdown(2);
<div id="timer">2:00</div>
<button onclick="timeToggle()">Stop time</button>
There is a small flaw in your logic.
During the countdown initialization your doing
seconds = secs || 60;
Which effectively add 60 seconds to the time you want if you don't initialize the seconds. see:
function countdownInit(mins, secs) {
seconds = secs || 60;
minutes = mins;
console.log(mins + 'min ' + seconds + 'sec');
}
countdownInit(1, 30) // ok
// 1min 30sec
countdownInit(1) // not ok
// 1min 60sec
// thats 2 minutes
The second issue here is that you use a var current_minutes that equals minutes - 1 to display the time. So you are not showing the real counter.
the fix is as follow:
function countdown(mins, secs) {
seconds = secs;
minutes = mins;
// if secs is 0 or uninitialized we set seconds to 60 and decrement the minutes
if(!secs) {
minutes--;
seconds = 60;
}
function tick() {
var counter = document.getElementById("timer");
seconds--;
// we use minutes instead of current_minutes in order to show what's really in our variables
counter.innerHTML =
minutes.toString() + ":" + (seconds < 10 ? "0" : "") + String(seconds);
// rest of code
}
// rest of code
}
I tried to keep as much as your code as possible.

How to repeat javascript setInterval timer infinitely with two times

I am working on a timer that runs for a set amount of minutes, then starts over for a break period that counts down and then goes back to the original amount of minutes. I'm struggling with the logic. So far, I have it running down the original time, then running down the break timer but I need help making it return to the original time and loop this infinitely (or until the stop button is pressed). Here's what I have:
function timer(minutes, breakLength) {
--minutes;
timerId = setInterval(function() {
if (minutes >= 0) {
if (seconds > 0) {
--seconds;
}
if (seconds == 0 && minutes == 0) {
playSound();
isBreak = true;
minutes = breakLength;
$('.type').html('Break');
$('.timer').html(minutes + ':00');
};
if (seconds === 0) {
seconds = 59;
--minutes;
}
if (seconds < 10) {
seconds = '0' + seconds;
}
$('.timer').html(minutes + ':' + seconds);
}
}, 1000);
}
How can I make this repeat itself?
Define a new variable as a timeout id holder (let's call it resetTimeout) in your timer function scope:
var resetTimeout = null;
Add this additional code to the main function
var runFor = 60000; // 60000ms or 1 minute
Add logic in the main interval (first line):
if(runFor <= 0) {
if(!resetTimeout) {
// Create a reset timeout
resetTimeout = setTimeout(function(){ runFor = 60000; resetTimeout = null; }, breakLength);
}
return;
}
else {
runFor -= 1000; // Deduct time of this interval
}
This logic deducts 1000 ms or 1 second from runFor until it is fully consumed. Then creates a timeOut function that will reset it back to its original value and returns the current function until runFor is renewed. I used 60000 ms as an example and you can see the correct version in the full code below. Why do we assign the timeout to a variable? It is simple, we don't want to create more than one timeout. We'll set the timeout to null to allow recreation on the next interval.
Note that there are better ways of doing this but I decided to make as little modifications to your code as possible.
Here is the working code:
function timer(minutes, breakLength) {
var seconds = 0;
var originalMinutes = minutes;
var resetTimeout = null;
var totalRunFor = minutes * 60 * 1000; // Since minutes are independent
var runFor = totalRunFor;
timerId = setInterval(function() {
if(runFor <= 0) {
if(!resetTimeout) {
// Create a reset timeout
resetTimeout = setTimeout(function(){ runFor = totalRunFor; resetTimeout = null; }, breakLength);
}
return;
}
else {
runFor -= 1000; // Deduct time of this interval
}
if (minutes >= 0) {
if (seconds > 0) {
--seconds;
}
if (seconds == 0 && minutes == 0) {
//playSound();
isBreak = true;
minutes = originalMinutes;
$('.type').html('Break');
$('.timer').html(minutes + ':00');
};
if (seconds === 0) {
seconds = 59;
--minutes;
}
$('.timer').html(minutes + ':' + ((seconds < 10)?'0':'') + seconds);
}
}, 1000);
}
timer(1, 10000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Run for a minute and stop for 10 seconds indefinitely.
<div class='type'></div>
<div class='timer'></div>
It may be conceptually easier to seperate this into multiple functions within the timer function
function timer(minutes, breakLength) {
var ci = null;
function ACountdown(minutes, callback) {
var mm = minutes,
ss = 0;
ci = setInterval(function () {
--ss;
if (ss < 0)
ss += 60, --mm;
if (mm < 0) {
// done
clearInterval(ci);
setTimeout(callback, 0);
} else {
$('.timer').html(mm + ':' + seconds);
}
}, 1e3);
}
function A() {
// returned from break
$('.type').html = 'Countdown';
ACountdown(minutes, B);
}
function B() {
// just finished countdown
playSound();
// going on break
$('.type').html = 'Break';
ACountdown(breakLength, A);
}
// set up any click handlers here, e.g.
document.getElementById('cancel_button').addEventListener('click', function c() {
this.removeEventListener('click', c);
clearInterval(ci);
});
// start invocation chain
A();
}

Categories