pausing and playing setInterval() on button click - javascript

I am making a timer in javascript and am having some trouble starting and stoppimg the timer without the timer jumping ahead when it starts again. I've put in a boolean (isPaused) to pause and play setInterval, but when I play the timer jumps whatever length of time it has been paused. I tried recalling the setInterval function on play and I've tried resetting the variable that determines how long to count down (timeLeft). the timeLeft variable is the same when i pause it and play it so I'm not sure why it is jumping around like that.
my HTML :
<div class="container">
<div class="row">
<div class="col-xs-6">
<button id="start-button">Start Timer</button>
<button id="pause-button">Pause Timer</button>
<button id="play-button">Play Timer</button>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<span id="display-minutes"></span>
<span id="display-seconds"></span>
<span id="display-milli"></span>
</div>
</div>
</div>
and my JavaScript:
var minutes = 25;
var seconds = 0;
var milliseconds = 0;
var endTime = 0;
var timeLeft = 0;
var dateAtPause = 0;
var isPaused = false;
$('#display-minutes').html(minutes);
$('#display-seconds').html(seconds);
$('#display-milli').html(milliseconds);
//calculate time remaining between now and endTime
function timeRemaining() {
timeLeft = Date.parse(endTime) - Date.parse(newDate());
var milliseconds = Math.floor(timeLeft % 1000);
var seconds = Math.floor((timeLeft/1000) % 60);
var minutes = Math.floor(timeLeft/1000/60);
var total = timeLeft;
return {
'milliseconds': milliseconds,
'seconds': seconds,
'minutes': minutes,
'total': total,
};
}
function updateClock() {
if (!isPaused) {
var time = timeRemaining();
$('#display-minutes').html(time.minutes);
$('#display-seconds').html(time.seconds);
$('#display-milli').html(time.milliseconds);
if (time.total <= 0) {
clearInterval(timeInterval);
};
};
};
$('#start-button').click(function() {
//set time (var minutes) minutes from now
var startTime = new Date();
endTime = new Date(startTime.setMinutes(startTime.getMinutes() + minutes));
updateClock();
var timeInterval = setInterval(updateClock, 1000);
});
$('#pause-button').click(function() {
isPaused = true;
dateAtPause = new Date();
console.log(timeLeft);
});
$('#play-button').click(function() {
isPaused = false;
var timeInterval = setInterval(updateClock, 1000);
console.log(timeLeft);
});

When you pause / play the previous timer is not cleared and the end time is not changed. That's why the remaining time continues to go down even during the pause.
After hitting play, you have one more timer, so you keep increasing the number of running timers.
Also, the clearInterval in updateClock does nothing to the timeInterval variables that are created locally in the other functions.

This is happening because you chose to use a point in time for the endtime and lose track of the original duration needed.
Conceptually you will want to track the number of milliseconds left to run rather than an actual end time.
Functionality I would recommend:
timer = {};
timer.duration = 10000; //one field to track the expected duration (milliseconds is easiest to deal with)
timer.elapsedTime = 0; //another field to track what time has elapsed
And just keep track of the elapsed time vs the duration you expect it to run for.
I created a jsfiddle for you to see the functionality: JSFiddle

Related

I can't get this countdown timer button working

I have a countdown timer I am working on but cant get it to work. I don't really understand how I got this far with it as I am not a developer. The function is: You input a timer like 1 minute, and the countdown timer counts down and reaches zero. It then pays a sound and starts the countdown again.
After you press the Start Timer button, the countdowns being. And the button changes to STOP. So you can stop the timer at any point, then when you stop the timer the button changes to START/RESUME so you can start the timer again.
The problem is that the timer STOP button only works the first time counting down. After that it doesn't work. Any ideas from the pros, how I can fix this?
const timerDisplay = document.getElementById("timerDisplay");
const startButton = document.getElementById("startButton");
const timeInput = document.getElementById("timeInput");
const audio = new Audio('alarm.mp3');
let interval;
let start;
let duration;
let elapsed;
let isRunning = false;
startButton.addEventListener("click", function() {
if (!isRunning) {
duration = timeInput.value * 60 * 1000;
startTimer(duration);
startButton.innerHTML = "Stop";
isRunning = true;
} else {
clearInterval(interval);
startButton.innerHTML = "Resume";
isRunning = false;
}
});
function startTimer(duration) {
start = Date.now();
let timer = duration,
minutes, seconds;
interval = setInterval(function() {
elapsed = Date.now() - start;
timer = duration - elapsed;
minutes = parseInt(timer / 60000, 10);
seconds = parseInt((timer % 60000) / 1000, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
timerDisplay.innerHTML = minutes + ":" + seconds;
if (timer < 0) {
clearInterval(interval);
timerDisplay.innerHTML = "Change Exercises!";
audio.play();
start = Date.now();
timer = duration;
}
}, 1000);
audio.addEventListener("ended", function() {
startTimer(duration);
startButton.innerHTML = "Stop";
isRunning = false;
});
}
<p>
<label for="timeInput">Set Time:</label>
<input type="number" id="timeInput" value="1">
</p>
<p>
<button id="startButton">Start Timer</button>
</p>
<p id="timerDisplay"></p>
This actualy doesnt restart when the countdown reaches zero. But it still restarts on my server? Not sure whats thats about.

javascript countdown timer

I want to create a countdown timer with javascript that will count down every six minutes. When it gets to 00 I will start from 6 minutes. It will continue like this forever. If the browser is refreshed, this countdown will continue. Even if the browser is refreshed, the countdown will not start again from 6 minutes until 00. How can I do this? Someone help with the code.
Welwome to SO. Please, before asking for help try to provide some code before.
For this time, we will help.
let countdown = 6 * 60;
setInterval(function() {
countdown--;
if (countdown === 0) {
countdown = 6 * 60;
}
document.getElementById("countdown").innerHTML = countdown;
}, 1000);
Note that if the browser is refreshed, everything will reinitialize.
To keep track, you'll need a database or store in client browser.
Make a button with the onclick function starting the timer using the setInterval function that has a callback that decreases a second each second from the 6 minutes.In the callback, store the time into localstorage, and make the startingTime value restore from the localstorage time value if the localstorage time value is not 0.
const start = document.querySelector("#start")
const timeP = document.querySelector("#time")
let interval;
const startingTime = 360
let time = startingTime || window.localStorage['time']
console.log(window.localStorage['time'])
const setLocalStorage = () => {
console.log(time);
window.localStorage['time'] = time}
if (time <= 0) {
time = startingTime
setLocalStorage()
}
function calc(s) {
minutes = (s - s % 60) / 60;
seconds = s % 60;
return minutes + ":" + seconds
}
function callback() {
console.log(time);
time--;
timeP.innerHTML = calc(time);
if (time <= 0) {
time = startingTime;
clearInterval(interval);
start.classList.remove("invis")
timeP.classList.add("invis")
}
setLocalStorage();
}
function startTimer() {
interval = setInterval(callback, 1000);
start.classList.toggle("invis");
timeP.classList.remove("invis")
}
start.onclick = startTimer
.invis {
display: none
}
#start {
color: black;
background-color: red;
}
#time {
color: black;
}
<button id="start">START</button>
<p1 id="time" class="invis"></p1>
If you want the timer "not to pause" to run even after you exit the browser then:
you could store the value of Date.now() in localstorage or wherever you want
and get the value on load and subtract that value from the current Date.now() and you have the difference between the times now you can use that difference to do what you want.

javaScript countdown starts multiple times when links are clicked more than once

I'm pretty new into JavaScript and would like to implement the following feature:
By clicking a link on the site, a timer with a 15min countdown shall start. That works fine if the link is clicked only once. But if the link (or another one) is clicked again, two (ore more) countdowns are displayed parallelly.
I've tried two different approaches: first, a code that focuses on a Date() object and second a version that handles a variable which is successively reduced by one second. Both codes (of course) are based on the setInterval() function.
In the first case a log of stopZeit shows that each time a link is clicked a new value of stopZeit is created. In the second case console.log(timerLaenge) shows 30 no matter how often a link is clicked, but there are multiple timers started though.
Here are my two tries:
Version one:
function timer(stopZeit); //stopZeit = time now plus 15min - must be fixed, otherwise it will be actualized everytime the function is called
{
console.log(stopZeit);
var countdown = setInterval(function()
{
var jetzt = new Date().getTime(); //now
var differenz = stopZeit - jetzt; //time difference
var minuten = Math.floor((differenz % (1000 * 60 * 60)) / (1000 * 60)); //calculate remaining minutes
var sekunden = Math.floor((differenz % (1000 * 60)) / 1000); //calculate remaining seconds
document.getElementById("countdown").innerHTML = minuten + 'm ' + sekunden + 's '; //write down the current time difference
if(differenz < 0) //check if timer is expired
{
clearInterval(countdown);
document.getElementById("countdown").innerHTML = 'Timer abgelaufen!';
}
},1000);
}
<p id="countdown"></p>
Link01 <!--declare stopZeit as constant and hand it over to the timer function. -->
<br>
<br>
Link02 <!--another link-->
Version two:
function timer()
{
timerLaenge = 30; //length of timer
console.log(timerLaenge);
var countdown = setInterval(function()
{
timerLaenge = timerLaenge-1;
document.getElementById("countdown").innerHTML = timerLaenge + 's';
if(timerLaenge < 0)
{
clearInterval(countdown);
document.getElementById("countdown").innerHTML = 'Timer abgelaufen!';
}
},1000);
}
<p id="countdown"></p>
Link01
<br>
<br>
Link02
How can I achieve that the timer is reseted every time a link is clicked again?
To reset the timer everytime user clicks on the link, you can clear the existing timer first before starting the new timer, using clearInterval.
var countdown; // Bring this variable up one scope
function timer() {
timerLaenge = 30; //length of timer
if(countdown) clearInterval(countdown); // Clear the interval here
countdown = setInterval(function() {
timerLaenge = timerLaenge - 1;
document.getElementById("countdown").innerHTML = timerLaenge + 's';
if (timerLaenge < 0) {
clearInterval(countdown);
document.getElementById("countdown").innerHTML = 'Timer abgelaufen!';
}
}, 1000);
}
<p id="countdown"></p>
Link01
<br>
<br>
Link02
Welcome, AlexR_112!
The problem is that var countdown happens in a scope of timer() and countdown gets overwritten on every click. the solution is to store it outside.
I also added a cancelTimer() that will stop countdown hope it might helps you in future )
var countdown;
function timer()
{
if (countdown) {
return;
}
timerLaenge = 30; //length of timer
console.log(timerLaenge);
countdown = setInterval(function()
{
timerLaenge = timerLaenge-1;
document.getElementById("countdown").innerHTML = timerLaenge + 's';
if(timerLaenge < 0)
{
clearInterval(countdown);
document.getElementById("countdown").innerHTML = 'Timer abgelaufen!';
}
},1000);
}
function cancelTimer()
{
if (countdown) {
clearInterval(countdown);
countdown = null;
}
}
<p id="countdown"></p>
Link01
<br>
<br>
Link02
<br>
<br>
Cancel

Javascript .getTime() inconsistent results between between windows

I need to show a countdown timer. I get time from my server and should count down to zero, based on the following:
var now = new Date().getTime();
var timeRemaining = endTime - now;
.... I start the contdown timer with timeRemining
What happens is when I start the timer in two different tabs, the timer is off by about 2 seconds.
If I do this in one tab and another private window/tab, the timer can be different much much more.
Is there something I can do about this?
var end = new Date('2015-10-27T13:00:00');
var endTime = end.getTime();
var div = document.getElementById('time');
setInterval(function() {
var now = new Date().getTime();
var timeRemaining = endTime - now;
var seconds = timeRemaining / 1000;
div.innerText = Math.floor(seconds);
}, 1000);
<div id="time"></div>

jQuery backword Countdown from Initial HTML Value

I have a initial timer value. How can i make it so that it start counting down to 0?
I want the output to get displayed in another element
<span id="time">03:30:00</span>
<span id="output"></span>
<script type="text/javascript">
jQuery(function($){
var val = $("#time").html();
var output = "";
// count down
$("#output").html(output)
});
</script>
<script type="text/javascript">
$(function(){
var val = $("#time").html().trim();
console.log(val);
val = val.split(":");
var hr = parseInt(val[0].trim());
var mn = parseInt(val[1].trim());
var sc = parseInt(val[2].trim());
console.log(val);
var timer = setInterval(function(){
if(hr==0 && mn==0 && sc==0){
clearInterval(timer);
return;
}
if(sc==0){
sc=60;
mn--;
}
if(mn==0 && sc==0){
mn=60;
hr--;
}
sc--;
$("#output").html(hr+":"+mn+":"+sc);
},10);
});
</script>
This is not the correct answer but rather a best practise
You should use the new time element instead
<time datetime="2014-08-29T20:00:00.000Z">3 minutes left</time>
where datetime is the ISO date format for when the correct moment occured in the future
then inside of the element you would present the text how every you want to display it
By doing so you eliminate the slow bandwidth/DOM parsing & javascript compilation to when its start to count down.
When it has begun you should calculate how many hours/minutes/second there is left until that point in the feuter in every digest.
Then you are safe from the incorrect setTimeout/setInterval that doesn't always wait the exact same time, especially when the tab is idle (in the background)
where setTimeout(fn, 1000) could take 4 seconds if it where in the background.
Here is a example.
How you get the date and display it in the DOM is up to you
var finishDate = new Date(Date.now()+10000); // get point in future somehow
var tick = function() {
var now = new Date()
var difference = finishDate - now;
var hours = Math.floor(difference / 36e5),
minutes = Math.floor(difference % 36e5 / 60000),
seconds = Math.floor(difference % 60000 / 1000);
console.log(hours, minutes, seconds);
setTimeout(tick, now.getUTCMilliseconds())
}
tick() // Start the digest

Categories