I'm trying to create a pomodoro clock, and I can't figure out why the resetClock function is going everything except clearing the interval for the clock. It is resetting the number, but the clock keeps counting down. I'd imagine I'll have this issue when trying to implement the stop clock function also. Can someone help?
var minutes = 25;
var seconds = 0;
var startSound = new Audio('./sounds/startsound.mp3')
var resetSound = new Audio('./sounds/resetclocksound.mp3')
var stopSound = new Audio('./sounds/pausesound.mp3')
var alarmSound = new Audio('/sounds//haoduken.mp3')
var minutes_interval;
var seconds_interval;
function startClock() {
startSound.play();
minutes = 24;
seconds = 59;
document.getElementById('minutes').innerHTML = minutes;
document.getElementById('seconds').innerHTML = seconds;
document.getElementById('start-button').removeEventListener('click', startClock)
var minutes_interval = setInterval(minutesTimer, 60000);
var seconds_interval = setInterval(secondsTimer, 1000);
function minutesTimer() {
minutes = minutes - 1;
document.getElementById('minutes').innerHTML = minutes;
}
function secondsTimer() {
seconds = seconds - 1;
document.getElementById('seconds').innerHTML = seconds;
if (seconds <= 0) {
seconds = 60;
}
if (seconds <= 0 && minutes <= 0) {
alarmSound.play()
clearInterval(minutes_interval);
clearInterval(seconds_interval);
}
}
}
function resetClock() {
clearInterval(seconds_interval);
clearInterval(minutes_interval)
resetSound.play();
var minutes = 25;
var seconds = 0;
document.getElementById('minutes').innerHTML = minutes;
document.getElementById('seconds').innerHTML = seconds;
document.getElementById('start-button').addEventListener('click', startClock)
}
The problem is on the lines where you start the interval:
var minutes_interval = setInterval(minutesTimer, 60000);
var seconds_interval = setInterval(secondsTimer, 1000);
the problem is simply your use of the var keyword, which creates a new local variable inside the startClock function. It does nothing to the outer (global?) variables of the same name, because those are "shadowed" by the new local variables.
As a consequence, the clearInterval calls inside resetClock are referencing the outer variables, which do not hold a timer ID.
The solution is probably very simple: just remove the var from the above two lines. You now only have one "global" minutes_interval and seconds_interval, which will be referenced by the clearInterval calls. From a quick glance, it appears that this should work OK for you, and that you only ever set these intervals up once before cancelling them. But if you wanted to use this code to set up multiple intervals simultaneously you'd have to rethink your approach.
Related
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
I'm trying to create a function that can return a value (the user's current time in seconds) to another variable that can be used elsewhere in my code. The function returns the correct value, but I can't figure out how to make it repeat using setInterval or setTimeout.
var currenttime = clock();
function clock() {
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
var time = (hour * 3600) + (minute * 60) + second;
return time;
}
console.log(currenttime)
I want the variable currenttime to be updated every second, but changing the line to
var currenttime = setInterval(clock, 1000);
returns an incorrect value. Alternatively I've also tried to make the clock function repeat,
but I'm not sure how to do this as I'm using a return statement so the function ends before it can be repeated.
Does anyone know what I'm doing wrong?
Assign to currentTime every time clock runs, but don't return the time - since this'll be in an interval, the return value is ignored:
let currentTime;
function clock() {
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
currentTime = (hour * 3600) + (minute * 60) + second;
}
setInterval(clock, 1000);
setTimeout(() => console.log(currentTime), 2000);
setTimeout(() => console.log(currentTime), 6000);
This is a bit weird, though - variable assignment alone doesn't have side effects (in almost all cases). It would make more sense for whatever uses the currentTime variable to call clock to get the current number of seconds, eg:
function clock() {
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
return (hour * 3600) + (minute * 60) + second;
}
document.querySelector('button').addEventListener('click', () => {
document.querySelector('div').textContent = clock();
});
<button>Get seconds</button>
<div id="time"></div>
The function called by setInterval should call clock and display the time.
setInterval(function(){ console.log(clock()); }, 1000);
setInterval return only an ID value that can be used in clearInterval(ID) to stop setInterval loop.
So, you can do that:
function clock()
{
let [h,m,s] = (new Date().toTimeString()).match(/\d{2}/g)
return (h*3600) + (m*60) + +s
}
var currenttime = clock();
setInterval(() => { currenttime = clock() }, 1000);
Why timer clock.start(); does not want to stop by using function clock.stop();.
I'm using typical function clearInterval in prototype stop to stop function start. Bur after calling clock.stop(); the timer in function clock.start(); does not stop.
I can not understand why...
function Clock(options) {
this._template = options.template;
}
Clock.prototype._render = function() {
var date = new Date();
var hours = date.getHours();
if (hours < 10) hours = '0' + hours;
var min = date.getMinutes();
if (min < 10) min = '0' + min;
var sec = date.getSeconds();
if (sec < 10) sec = '0' + sec;
var output = this._template.replace('h', hours).replace('m', min).replace('s', sec);
console.log(output);
};
Clock.prototype.start = function() {
this._render();
var self = this;
this._timer = setInterval(function() {
self._render();
}, 1000);
};
Clock.prototype.stop = function() {
setTimeout(function() {
clearInterval(this._timer);
console.log('Stop!'); // message is displayed, but timer in **this._timer** does not stop...
}, 5000);
};
var clock = new Clock({
template: 'h:m:s'
});
clock.start();
clock.stop();
To solve a problem in a function clock.stop();, it is necessary to apply a closure similarly applied to the function clock.start();
So we need to put the this._timer in the local variable and accessing directly to they by using the clouser method.
in the Clock.prototype.start we did clouser
this._render();
var self = this;
So we need to make the same in Clock.prototype.stop such
var sef = this._timer;
and use local variable sef in the timer function.
So simple, but I understand it only now.
Thanks to #elclanrs for a aiming :)
I am making a countdown timer that should be reseting and starting anew every 10 seconds.
This is the code I came up with by now:
function count(){
var end_date = new Date().getTime()+10*1000;
setInterval(function(){
var current_date = new Date().getTime();
var seconds_left = parseInt((end_date - current_date) / 1000);
document.getElementById("countdown").innerHTML = seconds_left + " seconds ";
}, 1000);
}
setInterval(function(){count()}, 10*1000);
It is supposed to function as follows:
+ I set interval that will restart count() every 10 seconds.
+ count() defines end_date - a date 10 seconds from now.
+ then count() sets interval that will restart every 1 second.
+ every 1 second seconds_left variable is changed according to how current_date changed with respect to end_date.
+ as soon as seconds_left becomes 0, setInterval from step 1 fires and starts count() anew.
Which step am I implementing the wrong way? Do I misunderstand the functioning of setInterval()?
Here is my JsFiddle: http://jsfiddle.net/sy5stjun/ .
My guess is that each call is in its own new object and you get multiple instances of itself fighting ever 10 seconds.
Using your approach using date objects here is a possible re-write:
var tmr = null;
var time;
function bigInterval() {
clearInterval(tmr);
time = (new Date()).valueOf() + (10 * 1000);
smallInterval();
tmr = setInterval(smallInterval, 500);
}
function smallInterval() {
var cur = (new Date()).valueOf();
var seconds_left = parseInt((time - cur) / 1000);
document.getElementById("countdown").innerHTML = seconds_left + " seconds";
}
bigInterval();
setInterval(bigInterval, 10*1000);
In the above code I've updated the small timer to be 500ms instead of 1000ms as it won't exactly line up with the system clock at 1000 and you get visual jumps in the numbers.
If exact timing isn't 100% important then here is a possible shorter method:
var t = 10;
setInterval(function() {
document.getElementById("countdown").innerHTML = t + " seconds";
t--;
if (t <= 0) {
t = 10;
}
}, 1000);
There are a few things going on, here. You're not specific why you have to set another interval inside your loop, but there are a lot easier ways to accomplish what you're going for. Another approach follows:
HTML:
<!-- string concatenation is expensive in any language.
Only update what has to change to optimize -->
<h1 id='countdown'><span id="ct"></span> seconds </h1>
JS:
// For one thing, grabbing a new reference to the
// dom object each interval is wasteful, and could interfere with
// timing, so get it outside your timer, and store it in a var scoped
// appropriately.
var ct = document.getElementById("ct");
// set your start
var ctStart = 10;
// set your counter to the start
var ctDown = ctStart;
var count = function() {
// decrement your counter
ctDown = ctDown - 1;
// update the DOM
ct.innerHTML = ctDown;
// if you get to 0, reset your counter
if(ctDown == 0) { ctDown = ctStart; }
};
// save a reference to the interval, in case you need to cancel it
// Also, you only need to include a reference to the function you're
// trying to call, here. You don't need to wrap it in an anonymous function
var timer = window.setInterval(count, 1000);
My jsFiddle available for tinkering, here: http://jsfiddle.net/21d7rf6s/
I'm fairly new to DOM and the whole HTML and PHP Stuff so I'm seeking some information on how to do this. What I have until now is a Javascript. Now I want/have to use DOM to show this script. (FYI: I'm implementing something for Moodle and this has be done like this)
What I have found out about DOM is that I can change values of different Nodes. The problem I've found myself in is that all the examples I found were like. Click on a button and something happens. That's ok but now I want my script to run every second so I can the person who needs it can see that the time is running down.
I hope I gave you enough information and I hope you can help me. Thank you for trying to help me.
var running = false
var endTime = null
var timerID = null
// totalMinutes the amount of minutes is put into
var totalMinutes = 3;
function startTimer() {
// running is being started and the current time is put into the variable
running = true
now = new Date()
now = now.getTime()
// Variable endTime gets the time plus the maximum time
endTime = now + (1000 * 60 * totalMinutes);
showCountDown()
}
function showCountDown() {
// same as startTimer, time is saved in variable now
var now = new Date()
now = now.getTime()
if (endTime - now <= 0) {
// Variable timerID gets clearTimeout -->http://de.selfhtml.org/javascript/objekte/window.htm#clear_timeout
clearTimeout(timerID)
// boolean running set to false
running = false
alert("Ihr Resultat wird nun ausgewertet!")
} else {
// delta is being calculated
var delta = new Date(endTime - now)
var theMin = delta.getMinutes()
var theSec = delta.getSeconds()
var theTime = theMin
// show seconds and minutes
theTime += ((theSec < 10) ? ":0" : ":") + theSec
document.getElementById('CheckResults').innerHTML = " (Übung in " + theTime + " Minuten abgelaufen)"
if (running) {
timerID = setTimeout("showCountDown()",900)
}
}
}
</script>
You might want to use window.setInterval for a start. Here is a short example. Create a blank html page, put the script into the head section, and the markup into the body section. I wasn't able to post it with proper html and body tags
<script>
function countDownTimer(msecGranularity, output) {
var secRunningTime, startTime, endTime, onFinish, interval;
function heartBeat() {
var diff = endTime - new Date();
output.innerHTML = diff / 1000;
if (diff < 0) {
window.clearInterval(interval);
onFinish();
};
};
this.start = function (secRunningTime, finishHandler) {
onFinish = finishHandler;
startTime = new Date();
endTime = startTime.setSeconds(startTime.getSeconds() + secRunningTime);
interval = window.setInterval(heartBeat, msecGranularity);
}
};
function startTimer(duration, granularity) {
var output = document.createElement("div");
document.getElementById("timerOutputs").appendChild(output);
var t = new countDownTimer(granularity, output);
t.start(duration, function () { output.innerHTML = 'TIMER FINISHED' });
};
</script>
In the HTML place these to start the timer class.
<button onclick="startTimer(60,100)">Start a new 60 seconds timer with 100 msec granularity</button><br />
<button onclick="startTimer(600,1000)">Start a new 600 seconds timer with 1000 msec granularity</button>
<div id="timerOutputs">
</div>