I have taken this simple timer method from here.
What I want is pretty simple, yet I can’t figure it out.
When the timer reaches zero (0:00), I want a popup alert. At the same time, the timer should continue in negative time.
So everything is working, except the popup. Any idea why?
window.onload = function() {
var minute = 0;
var sec = 3;
setInterval(function() {
document.getElementById("timer").innerHTML = minute + " : " + sec;
sec--;
if (sec == 00) {
minute --;
sec = 59;
if (minute == 0 && sec == 00) {
alert("You failed!");
}
}
}, 1000);
}
<div class="countdown" class="failed" id="coutdown">
Time remaining to find solution: <span id="timer">10 : 00</span>
</div>
window.onload = function() {
var minute = 0;
var sec = 3;
var timer = document.getElementById("timer");
setInterval(function() {
if (sec === 0) {
timer.innerHTML = minute + " : " + sec;
if (minute === 0 && sec === 0) {
alert("You failed!");
}
minute--;
sec = 60;
} else {
timer.innerHTML = minute + " : " + sec;
}
sec--;
}, 1000);
}
<div class="countdown" class="failed" id="coutdown">
Time remaining to find solution: <span id="timer">10 : 00</span>
</div>
You are checking minute and second conditions after minute-- in your code, which means -1 is not equal to zero. Write an if condition before making minus 1 in your code.
Please use console.log("You failed!") instead of alert("You failed!") to ensure an accurate result.
Your conditional is checking whether sec == 0 immediately after you set sec = 59, so the conditional will never occur. Do you mean to have the order of this setter and the conditional swapped?
This is what I mean by restructuring the code entirely into reusable functions. comment what you don't understand and I will explain. I try not to hard code anything timer fetches its starter value from HTML.
const display = document.getElementById("timer");
function toArray(domEl){
return domEl.innerHTML.split(':').map(el => +el);
}
function getSec(timeArr){
if(timeArr.length > 3 || timeArr.length === 0) return;
return timeArr.reverse().map((el, i) => el * 60 ** i).reduce((cur,accu)=> cur + accu);
}
let totalSec = getSec(toArray(display))
setInterval(()=>{
totalSec--;
display.textContent = formatTime(totalSec);
},1000)
function formatTime(sec){
const time = {hr:0, min:0, sec:0};
time.hr = ~~(sec/3600) || 0;
time.min = ~~(~~(sec%3600)/60);
time.sec = ~~(sec%3600)%60;
if(time.hr===0 && time.min===0 && time.sec ===0) alert("You Faild!")
return `${time.hr ? time.hr + ':':''}${padTime(time.min)}:${padTime(time.sec)}`
}
function padTime(time){
return time? String(time).padStart(2,0):0;
}
<div class="countdown" class="failed" id="coutdown">
Time remaining to find solution: <span id="timer">0:01:05</span>
</div>
Related
I am making a timer and for some reason the timer is not properly decrementing using the countDown function in the code below. I am using setTimeout to call it countDown repeatedly but when I checked the debugger JavaScript does not even go to that line, after the second-to-last line timeEl.textContent = tempMinutes + ":" + tempSeconds; it just stops. I tried setInterval but its the same.
I want to know how to have the timer go down and setTimeout to do its thing, but how? Any advice or help is greatly appreciated!
const workBtnEl = document.querySelector("#work-btn");
const shortBreakBtnEl = document.querySelector("#short-break-btn");
const longBreakBtnEl = document.querySelector("#long-break-btn");
let timeEl = document.querySelector("#time");
const work = 25;
const shortBreak = 5;
const longBreak = 15;
let currentMinutes, currentSeconds = 0;
workBtnEl.addEventListener("click", function() {
timeEl.textContent = "25:00";
currentMinutes = work;
countDown(currentMinutes, 0);
});
function countDown(minutes, seconds) {
if (seconds == 0) {
if (minutes == 0) {
return;
}
minutes -= 1;
seconds = 59;
}
let tempSeconds = seconds;
let tempMinutes = minutes;
if (seconds < 10) {
tempSeconds = "0" + seconds;
}
if (minutes < 10) {
tempMinutes = "0" + minutes
}
timeEl.textContent = tempMinutes + ":" + tempSeconds;
let time = setTimeout(countDown, 1000, minutes, seconds);
}
<button id="work-btn">
Work
</button>
<button id="short-break-btn">
Short break
</button>
<button id="long-break-btn">
Long break
</button>
<span id="time">Time</span>
You never decrease seconds when it is non-zero.
So add that after the if block:
if (seconds == 0) {
// your code...
} else seconds--; // <---
You need to reduce the seconds variable in the countDown function otherwise the same text will be printed to your text area each time.
Right now you just have a condition if the seconds are 0 then set seconds to 59.
See what you have done in this line :
let currentMinutes, currentSeconds = 0;
currentMinutes will be undefined mostly, I used Node REPL to check
If you have something like :
let a, b = 0
The value of a was undefined & b got set to zero
An appropriate assignment would be
let currentMinutes = 0;
let currentSeconds = 0;
I'm trying to build a timer that when it reaches zero it stops. I've tried to make it with a clearInterval but it is not working. As it does nothing.
function startGame() {
var minute = 00;
var sec = 10;
const timeInterval = setInterval(function() {
document.getElementById("gameTimer").innerHTML =
minute + " : " + sec;
sec--;
if (sec == 00) {
minute--;
sec = 59;
if (minute == 00) {
minute = 0;
clearInterval(timeInterval)
}
} else if (minute == 0 && sec == 1) {
document.getElementById("finishGame").innerHTML = "hello"
}
}, 1000);
};
<span id="gameTimer"></span>
<button onClick="startGame()">Start Counter</button>
<span id="finishGame"></span>
You need to use minute <= 0 condition, since you subtract one from minute first, and then check for minute == 0, which will be false, since minute will be -1.
Also, its better to put all if conditions first, then subtract one from second.
function startGame() {
var minute = 0;
var sec = 10;
const timeInterval = setInterval(function() {
document.getElementById("gameTimer").innerHTML = minute + " : " + sec;
if (sec <= 0) {
minute--;
sec = 59;
if (minute <= 0) {
minute = 0;
clearInterval(timeInterval)
}
} else if (minute == 0 && sec == 1) {
document.getElementById("finishGame").innerHTML = "hello";
}
sec--;
}, 1000);
};
<body>
<span id="gameTimer"></span>
<button onClick="startGame()">Start Counter</button>
<span id="finishGame"></span>
</body>
I'm kinda new to programming, but recently I was trying to do little first project of mine called timer count, it's just simple local website which I open when I'm deciding to start programming during the day and it counts the time. I created 2 buttons with 2 different functions (start,stop), but the problem I'm stuck on is I don't know how to implement stop function. The idea is that timer should stop after button click, and when I click start button it should start from saved time.
Here's HTML/CSS code:
<div class="timer-display-id">
<h1>Timer </h1>
<p id="timer">00:00:00 </p>
<button id="start-timer" onclick="start()">Start </button>
<button id="stop-timer" onclick="stop()">Stop </button>
</div>
<script src="timer.js"></script>
and here's JS code:
function stop() {
// not exactly sure if this function should be here, anyway no idea what to add to get this to work
clearInterval(interval);
start.disabled = false;
}
function convertSec(cnt) {
let sec = cnt % 60;
let min = Math.floor(cnt / 60);
if (sec < 10) {
if (min < 10) {return "0" + min + ":0" + sec;}
else {return min + ":0" + sec;}
}
else if ((min < 10) && (sec >= 10)) {return "0" + min + ":" + sec;}
else {return min + ":" + sec;}
}
function start() {
let ret = document.getElementById("timer");
let counter = 0;
let start = document.querySelector("#start-timer");
let stop = document.querySelector("#stop-timer");
start.disabled = true;
let interval = setInterval(function() {
ret.innerHTML = convertSec(counter++); // timer start counting here...
},1000);
}
I understand it might be very messy, kinda lack of logic, but it's best I can do for now. If you'd like to give some tips about code organizing, I'd appreciate it.
You nee to have interval accessible by both functions whileit holds the setInterval function, just move it outside the start function :
const ret = document.getElementById("timer");
const startBtn = document.querySelector("#start-timer");
let counter = 0;
let interval;
function stop() {
clearInterval(interval);
startBtn.disabled = false;
}
function convertSec(cnt) {
let sec = cnt % 60;
let min = Math.floor(cnt / 60);
if (sec < 10) {
if (min < 10) {
return "0" + min + ":0" + sec;
} else {
return min + ":0" + sec;
}
} else if ((min < 10) && (sec >= 10)) {
return "0" + min + ":" + sec;
} else {
return min + ":" + sec;
}
}
function start() {
startBtn.disabled = true;
interval = setInterval(function() {
ret.innerHTML = convertSec(counter++); // timer start counting here...
}, 1000);
}
<div class="timer-display-id">
<h1>Timer </h1>
<p id="timer">00:00:00 </p>
<button id="start-timer" onclick="start()">Start </button>
<button id="stop-timer" onclick="stop()">Stop </button>
</div>
If you want the count to be saved after you hit "stop", and to re-start from the same point, you will need to define your count variable somewhere outside the start() function, so that it can tell what count to restart from. At the moment, count is local to the start() function, which will reset it to zero every time.
By using the 1s interval timer to update the count, your counter will round each period to whole seconds. It would be slightly more complicated, but if you want to be able to add up the partial seconds from multiple counts, it would be more accurate to use something like Date.getTime() to record the time the start button is pressed, then check the elapsed time when stop() is triggered, and add that to your count. You might still want to use an interval timer to regularly update the current value though. Again, you would need to check that the variables you want to use have the correct scope, so that they are visible to the functions that use them, and not lost between function calls.
I'm creating a countdown timer in minutes and seconds that that displays on the page - all seems to work fine with the bit of code I have. The only issue is when the alert box pops up I want the clock to stop counting down also.
I thought that including the return keyword under the alert pop up would resolve the issue but the clock keep ticking down.
Below is the code. Any help would be great.
window.onload = function() {
var hour = 1;
var sec = 59;
setInterval(function() {
document.getElementById("timer").innerHTML = hour + " : " + sec;
sec--;
if (sec == 0) {
hour--;
sec = 59;
}
if (hour == 1 && sec == 51)
{
alert("Stop, you have not completed the task in the alotted time");
return;
}
}, 1000);
}
To do that you need to save that Interval in a variable and then deactivate the interval with clearInterval. So your code would be like this:
window.onload = function() {
var hour = 1;
var sec = 59;
let counting_interval = setInterval(function() {
document.getElementById("timer").innerHTML = hour + " : " + sec;
sec--;
if (sec == 0) {
hour--;
sec = 59;
}
if (hour == 1 && sec == 51)
{
alert("Stop, you have not completed the task in the alotted time");
clearInterval(counting_interval); // pass the interval as the argument and it will stop to call the interval anymore
return;
}
}, 1000);
}
You need to set a timeout, not an interval. Intervals trigger until they're stopped. Timeouts happen once.
const interval = setInterval( function() {
document.getElementById("timer").innerHTML = hour + " : " + sec;
sec--;
if (sec == 0) {
hour--;
sec = 59;
}
});
const timeoutPeriod = 2 * 60 * 60 * 1000;
setTimeout(
function(){
clearInterval(interval);
alert("Stop, you have not completed the task in the alotted time");
}, timeoutPeriod
);
this is my code, it doesn't work I think the problem is what I'm returning in the function.
Please, help.
var minutes = 25;
var seconds = 60;
function myFunction() {
var start = setInterval(function() {
if (seconds > 0) {
seconds--;
}
if (seconds == 0) {
seconds = 60;
minutes--;
}
if (seconds == 0 && minutes == 0) {
alert("done");
}
var time = minutes + ":" + seconds;
return time;
}, 1000);
return start;
}
console.log(myFunction());
Description
Minor changes to show your code is working
Bugs?
- Requires a minutes and seconds variable be declared before myFunction is called, the rewrite takes these are parameters.
- Doesn't check if the variables are negative and thereby expects "valid" data from the user.
- Only allows for console.log(time), the rewrite allows a function to be passed in for each tick and onTimerComplete
var minutes = 25;
var seconds = 60;
function myFunction() {
var start = setInterval(function() {
if (seconds > 0) {
seconds--;
}
if (seconds == 0 && minutes == 0) {
alert("done");
// added this to clear the timer on 0 minutes 0 seconds
clearInterval(start);
return;
}
if (seconds == 0) {
seconds = 59;
minutes--;
}
var time = minutes + ":" + seconds;
// adding this as this is the function being repeated
console.log(time);
}, 1000);
}
myFunction();
How I would rewrite this
function timer(minutes, seconds, onTimerChanged, onTimerComplete) {
var timerPointer = undefined;
// if minutes is below 0 reset to 0
if (minutes < 0) {
minutes = 0;
}
// if seconds is set below 0 reset to 0
if (seconds < 0) {
seconds = 0;
} else if (seconds > 59) {
// this will add to minutes if too many seconds are passed
minutes += Math.floor(seconds / 60);
seconds = seconds % 60;
}
// this is the function to be called on each tick call
// default: console.log
if (onTimerChanged === undefined) {
onTimerChanged = console.log;
}
if (onTimerComplete === undefined) {
onTimerComplete = function() {
console.log("done")
};
}
// starts the timer
this.start = function() {
timerPointer = setInterval(tick, 1000);
}
// stops the timer
this.stop = clearInterval(timerPointer);
this.time = undefined;
// function for each tick
function tick() {
if (seconds > 0) {
seconds--;
}
if (seconds == 0 && minutes == 0) {
// added this to clear the timer on 0 minutes 0 seconds
clearInterval(timerPointer);
if (onTimerComplete) {
onTimerComplete();
}
return;
}
if (seconds == 0) {
seconds = 59;
minutes--;
}
// pads the numbers so they are always two digits
this.time = padToTwo(minutes) + ":" + padToTwo(seconds);
// if onTimeChanged exists call it
if (onTimerChanged) {
onTimerChanged(this.time);
}
}
// padding the string to be two digits always
function padToTwo(number) {
if (number <= 99) {
number = ("0" + number).slice(-2);
}
return number;
}
}
// create the timer object
var test = new timer(-1, 500);
// start the timer
test.start();
// this would also work
// new timer(minutes, seconds).start();
Both of the returns you have are pointless. console.log() will only output one time. You have to have console.log() inside of the setInterval() function to run multiple times. You should also clear the interval to avoid any memory leaks.
Last, I also added in minutes > 0 because otherwise seconds would be 60 and minutes would be -1 when time has run out.
var minutes = 25;
var seconds = 60;
function myFunction() {
var start = setInterval(function() {
if (seconds > 0) {
seconds--;
}
if (seconds == 0 && minutes > 0) {
seconds = 60;
minutes--;
} else
if (seconds == 0 && minutes == 0) {
clearInterval(start);
alert("done");
}
var time = minutes + ":" + seconds;
console.log(time);
}, 1000);
}
myFunction();
Your code (almost) works. You just will have to wait 26 minutes to see the alert.
if (seconds == 0 && minutes == 0) {
clearInterval(start);
alert("done");
}