Javascript easy timer does not work - javascript

I am trying to make an easy countdown but it does not work the way I think it should work. This is the first time I use setInterval in Javascript and would be very happy if someone could find my mistake.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
function timer () {
window.clearTimeout(clock)
var seconds = 10;
var clock = setInterval(function() {
if (seconds == 0) {
} else {
seconds = seconds-1;
document.getElementById('seconds').innerHTML = seconds;
};
},1000);
}
</script>
<button onclick="timer();">timer</button>
<p id="seconds">10</p>
</body>
</html>
I hoped the timer would start-over when you clicked the button, but there are 2 timers running at the same time.

There are several problems with your code you need to address:
You need to make the clock variable global. In your example, an empty new variable clock is created each time the timer() function is called.
You are using the clearTimeout() function instead of the clearInterval() function.
The setInterval() function may miss some ticks and your seconds counter will then be off. If you wish to avoid that, you should check the current time each time the interval function is called.
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
var clock;
function timer () {
clearInterval(clock);
var start = new Date().getTime();
clock = setInterval(function() {
var seconds = Math.round(10 - (new Date().getTime() - start) / 1000);
if (seconds > 0)
document.getElementById('seconds').innerHTML = seconds;
else
clearInterval(clock);
}, 1000);
}
</script>
<button onclick="timer();">timer</button>
<p id="seconds">10</p>
</body>
</html>
A breakdown of Math.round(10 - (new Date().getTime() - start) / 1000):
new Date().getTime() returns the current time in milliseconds since the epoch.
(... - start) / 1000 returns the number of seconds since the start of the timer.
10 - ... returns the number of remaining seconds.
Math.round(...) rounds the result to an integer.

Just using setTimeout simplifies things (you used setInterval, but clearTimeout to clear it), declare the necessary variables outside the timer function and add a reset argument to be able to reset the timer.
(function () {
var report = document.querySelector('#seconds');
var seconds = 10;
var timed = null;
document.querySelector('button')
.addEventListener('click', function(e) { timer(true) });
timer(true);
function timer (reset) {
seconds -= 1;
if(reset) {
clearTimeout(timed);
seconds = 10;
}
report.textContent = seconds;
if (seconds > 0 ) {
timed = setTimeout(timer, 1000);
}
}
}())
#seconds {
font: 48px/70px bold verdana, arial;
color: white;
width: 70px;
height: 70px;
background: green;
text-align: center;
border-radius: 50%;
}
<button>start/reset timer</button>
<p id="seconds"></p>

Related

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 form submit not working

So I was trying to write some javascript to countdown and then submit the form when the countdown is finished. This is the JS I found online and tried to implement:
var seconds = 300;
function secondPassed() {
var minutes = Math.round((seconds - 30) / 60),
remainingSeconds = seconds % 60;
if (remainingSeconds < 10) {
remainingSeconds = "0" + remainingSeconds;
}
document.getElementById('countdown').innerHTML = minutes + ":" + remainingSeconds;
if (seconds == 0) {
clearInterval(countdownTimer);
document.qForm.submit();
} else {
seconds--;
}
}
var countdownTimer = setInterval('secondPassed()', 1000);
Here it is implemented:
https://jsfiddle.net/spadez/9p9o4k6s/1/
The error says: secondPassed is not defined but I'm not sure why that is. Could anyone please explain where I have gone wrong?
For me both ways of calling setInterval work well with SO snippet. I think bug can be jsfiddle specific as it seems it accepts only the first form of setInterval, which takes function and interval, not code string to execute and delay (https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval). If you want to keep using fiddle you will have to change last line to:
var countdownTimer = setInterval(secondPassed, 1000);
var seconds = 300;
function secondPassed() {
var minutes = Math.round((seconds - 30) / 60),
remainingSeconds = seconds % 60;
if (remainingSeconds < 10) {
remainingSeconds = "0" + remainingSeconds;
}
document.getElementById('countdown').innerHTML = minutes + ":" + remainingSeconds;
if (seconds == 0) {
clearInterval(countdownTimer);
document.qForm.submit();
} else {
seconds--;
}
}
var countdownTimer = setInterval('secondPassed()', 1000);
body {
background-color: #eee;
}
canvas {}
time {color: red; float: right;}
.active {color: green; font-size: 12px; font-weight: bold;}
<h3>Question 1 of 20<time id="countdown">5:00</time></h3>
<form name="qForm">
<input type="radio"> 219
<input type="submit" value="Submit">
</form>
There is an error in last line of your code. Change that line to this'
var countdownTimer = setInterval(secondPassed, 1000);
Here is the updated fiddle. https://jsfiddle.net/9p9o4k6s/3/
When you pass a function call as a string to setInterval like that, the function you're calling must be in the global scope. Your function secondPassed is wrapped by the jsFiddle onload wrapper and so it is not in the global scope.
To demonstrate this, if you did window.secondPassed = secondPassed; to put it in the global scope, your existing code would work.
The proper solution is to pass the function object as the argument instead of a string:
var countdownTimer = setInterval(secondPassed, 1000);
Note there are no parenthesis () when used in this way.

pausing and playing setInterval() on button click

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

How to stop timer after the the countdown is over

<html>
<head>
<title>Countdown</title>
<script type="text/javascript">
// set minutes
var mins = 1;
// calculate the seconds (don't change this! unless time progresses at a different speed for you...)
var secs = mins * 60;
function countdown() {
setTimeout('Decrement()',1000);
}
function Decrement() {
if (document.getElementById) {
minutes = document.getElementById("minutes");
seconds = document.getElementById("seconds");
// if less than a minute remaining
if (seconds < 59) {
seconds.value = secs;
} else {
minutes.value = getminutes();
seconds.value = getseconds();
}
secs--;
setTimeout('Decrement()',1000);
}
}
function getminutes() {
// minutes is seconds divided by 60, rounded down
mins = Math.floor(secs / 60);
return mins;
}
function getseconds() {
// take mins remaining (as seconds) away from total seconds remaining
return secs-Math.round(mins *60);
}
</script>
</head>
<body>
<div id="timer">
Time Left: 00:<input id="minutes" type="text" style="width: 20px; border: none; background-color:none; font-size: 16px; font-weight: bold;">:<input id="seconds" type="text" style="width: 26px; border: none; background-color:none; font-size: 16px; font-weight: bold;">
</div>
<script>
countdown();
</script>
In this java script code the timer get executing after the time is over and time goes in minus example (00-1:30).
So I want to stop the timer when it reaches the 00:00. And it should give alert when the time is completed or submit the page.
There are a couple of issues, the biggest being that you are testing the seconds and not seconds.value, so you are always entering the else block. However, you also don't have a condition for when it reaches zero. Here is a jsfiddle that should fix those things, http://jsfiddle.net/psQb5/.
there are two possibilities. One is to use the function setInterval instead of setTimeout. Like this.
<script type="text/javascript">
// set minutes
var mins = 1;
// calculate the seconds (don't change this! unless time progresses at a different speed for you...)
var secs = mins * 60;
var intervalVar;
function countdown() {
intervalVar = setInterval('Decrement()',1000);
}
function Decrement() {
if (document.getElementById) {
minutes = document.getElementById("minutes");
seconds = document.getElementById("seconds");
// if less than a minute remaining
if (seconds < 59) {
seconds.value = secs;
} else {
minutes.value = getminutes();
seconds.value = getseconds();
}
secs--;
if (secs == 0) {
window.clearTimeout(intervalVar);
alert('timeout');
}
}
}
function getminutes() {
// minutes is seconds divided by 60, rounded down
mins = Math.floor(secs / 60);
return mins;
}
function getseconds() {
// take mins remaining (as seconds) away from total seconds remaining
return secs-Math.round(mins *60);
}
</script>
use setInterval() function instead of setTimeout().
when you want to stop timer using clearInterval() function.
for basic understanding of above function click below
w3schools.

How can I make this JavaScript Timer function properly?

I am trying to make a timer using JavaScript. The problem is, I can't get the timer to stop when it reaches 0. I have tried using return and if statements, but nothing seems to be working. Am I on the right track, or is there a better way to do this?
<input type="text" id="minutes" style="width:30px;text-align:center" maxlength="2" placeholder="00">
<span>:</span>
<input type="text" id="seconds" style="width:30px;text-align:center" maxlength="2" placeholder="00">
<button onclick="timer()">Set</button>
<script>
//This prototype correctly uses the modulus function when dealing with negative numbers.
Number.prototype.mod = function (m) {
return ((this % m) + m) % m
}
function timer() {
var minutes = document.getElementById('minutes').value //Value of minutes box.
var seconds = document.getElementById('seconds').value //Value of seconds box.
var initial = seconds * 1000 //Amount of seconds (converted to milliseconds) initially set.
var milliseconds = (minutes * 60000) + (seconds * 1000) //Total amount of milliseconds set.
setTimeout(function () {
alert("Time's up!")
}, milliseconds) //Display a message when the set time is up.
/*\Decreases the minute by one after the initially set amount of seconds have passed.
|*|Then, clears the interval and sets a new one to decrease the minute every 60 seconds.
\*/
test = setInterval(function () {
minutes--;
document.getElementById('minutes').value = minutes;
clearInterval(test)
setInterval(function () {
minutes--;
document.getElementById('minutes').value = minutes
}, 60000)
}, initial)
//Seconds are set to decrease by one every 1000 milliseconds, then be displayed in the seconds box.
setInterval(function () {
seconds--;
document.getElementById('seconds').value = seconds.mod(60)
}, 1000)
}
You have four different timer functions (setTimer and two setIntervals) when you only need one. JSFiddle
function timer() {
var minutes = document.getElementById('minutes').value //Value of minutes box.
var seconds = document.getElementById('seconds').value //Value of seconds box.
var intervalTimer = setInterval(function () {
seconds--;
if (seconds < 0) {
seconds = 59;
minutes--;
}
document.getElementById('minutes').value = minutes;
document.getElementById('seconds').value = seconds;
if (minutes == 0 && seconds == 0) {
alert("Time's up!");
clearInterval(intervalTimer);
}
}, 1000);
}
In general, you need to make sure every setInterval is given a name (var x = setInterval...) and cleared later on (clearInterval(x)). You could have separate timers (one for the minutes which starts after the given number of seconds then repeats every 60 seconds, one for seconds, and one to display the message) if you really want to for some reason, as long as you clear all of the interval timers once the countdown reaches zero.
Using two timers might make sense, however. This would make sure that the Time's up message really appears when it's supposed to, even if there is any imprecision in the interval timer.
function timer() {
var minutes = document.getElementById('minutes').value,
seconds = document.getElementById('seconds').value,
intervalTimer = setInterval(function () {
seconds--;
if (seconds < 0) {
seconds = 59;
minutes--;
}
document.getElementById('minutes').value = minutes;
document.getElementById('seconds').value = seconds;
}, 1000);
setTimer(function () {
alert("Time's up!");
clearInterval(intervalTimer);
}, minutes * 60000 + seconds * 1000);
}
I made improvements to Stuart's answer: fiddle
Basically the same thing, except it works properly:
function clearTimer() {
clearInterval(intervalTimer);
}
var intervalTimer;
function timer() {
var minutes = document.getElementById('minutes').value //Value of minutes box.
var seconds = document.getElementById('seconds').value //Value of seconds box.
intervalTimer = setInterval(function () {
seconds--;
if (seconds < 0) {
seconds += 60;
minutes--;
}
if (minutes < 0) {
alert("Time's up!");
clearTimer();
} else {
document.getElementById('minutes').value = minutes;
document.getElementById('seconds').value = seconds;
}
}, 1000);
}
Im not a great javascript guy, but maybe this will help. i made this in typescript http://www.typescriptlang.org/Playground/
but i would do timing different and use the javascript date object and calculate differences. This is a simple example of how i would start to create a time (without the date object)
javascript
var Timer = (function () {
function Timer(time) {
this.accuracy = 1000;
this.time = time;
}
Timer.prototype.run = function (button) {
var _this = this;
this.time -= 1; //this is inaccurate, for accurate time use the date objects and calculate the difference.
//http://www.w3schools.com/js/js_obj_date.asp
button.textContent = this.time.toString();
if (this.time > 0) {
setTimeout(function () {
return _this.run(button);
}, 1000);
}
};
return Timer;
})();
var time = new Timer(10);
var button = document.createElement('button');
time.run(button);
document.body.appendChild(button);
typescript(in case you wonder)
class Timer {
accuracy = 1000;//update every second
time: number;
constructor(time: number) {
this.time = time;
}
run(button: HTMLButtonElement) {
this.time -=1;//this is inaccurate, for accurate time use the date objects and calculate the difference.
//http://www.w3schools.com/js/js_obj_date.asp
button.textContent = this.time.toString();
if(this.time > 0)
{
setTimeout(()=> this.run(button),1000);
}
}
}
var time = new Timer(10)
var button = document.createElement('button');
time.run(button);
document.body.appendChild(button);

Categories