Countdown won't stop at 0, keeps decrementing - javascript

I have a timer that keeps decrementing after 0 so I get negative numbers. Time starts when a button is clicked and the pauses when the same button is clicked again.
button.addEventListener("click", function(event){
console.log('timer started')
// Timer paused, click to start
// Pause/Play Timer
if(timeleft == 90){
timeleft = setInterval(function() {
time--;
timerDisplay.innerHTML = time;
}, 1000);
} else if (timeleft === 0) {
clearInterval(timeleft);
} else{
// Timer running, click to pause
console.log('timer paused')
clearInterval(timeleft);
timeleft = 90;
}
});
The stop and start functionality works fine but why won't it stop counting down once it reaches 0?

Sample code for reference to build a timer.
const actionBtn = document.getElementById("start-timer");
let isTimerRunning = false;
let interval = null;
let maxTime = 20;
// Click handler to start and stop timer button in DOM
actionBtn.addEventListener("click", function() {
if(isTimerRunning) {
// stop timer
stopTimer();
} else {
// start timer
startTimer();
}
});
// Function to start timer
function startTimer() {
isTimerRunning = true; // toggle state, so on click again we can stop timer
// 1sec interval function to reduce max time
interval = setInterval(function() {
maxTime = maxTime - 1;
if(maxTime > -1) { // if the more time left (more than 0) update UI
renderUi(`Reset (${maxTime}sec)`);
} else { // if there is no time left stop timer
stopTimer();
}
}, 1000);
}
// stop timer
function stopTimer() {
isTimerRunning = false; // toggle state, so on click again we can start timer
clearInterval(interval); // clear the interval
maxTime = 20; // reset max time to initial value
renderUi(`Start Timer (${maxTime}sec)`); // update UI to initial value
}
// A generic function to update UI
// if we have complet UI structure we can update this function
function renderUi(str) {
actionBtn.innerText = str;
}
<button id="start-timer">Start Timer (20sec)</button>

Related

Pure JavaScript: How to refresh page after countdown if the browser tab is active

I want to achieve the following scenario:
Set a timer of 60 seconds and start the countdown displaying the
timer. After the countdown is finished, refresh (not reload) the page
and restart the countdown timer and continue the process.
If the browser's tab is changed, after finishing the timer, refresh the
page and pause the timer, and only when the tab is active again refresh
the page and start the countdown timer again.
I have managed to achieve the first requirement like:
Result will Refresh in <span id="countdown"></span>
<script>
if (!document.hidden) {
function timedRefresh(e) {
var n = setInterval((function () {
e > 0 ? (e -= 1, document.getElementById("countdown").innerHTML = e) : (clearInterval(n), window.location.reload())
}), 1e3)
}
timedRefresh(59)
}
</script>
And is unable to achieve the second requirement. I have tried to implement the solution mentioned here: Is there a way to detect if a browser window is not currently active?
But it didn't work.
How do I achieve the requirements in pure JavaScript code?
The following code has solved this scenario. It's a little messy, but I think is understandable. We use both window.document.hasFocus() and the focus event to create this solution. I have changed the window.location.reload() methods to just consoles simulating a function that refresh the data inside the application, since is asked to us refresh (not reload).
function timedRefresh(intervalTime) {
let interval = null;
let currentTime = intervalTime;
const updateTimer = () => {
const countdownSpan = document.getElementById("countdown");
if (currentTime <= 0) {
console.log(`print refresh at ${new Date()}`); // refresh page
if (window.document.hasFocus()) {
currentTime = intervalTime;
} else {
clearInterval(interval);
interval = null;
currentTime = intervalTime;
}
}
if (!interval) {
countdownSpan.innerHTML = "#";
} else {
countdownSpan.innerHTML = currentTime;
currentTime -= 1;
}
};
interval = setInterval(updateTimer, 1000);
window.addEventListener("focus", () => {
if (!interval) {
interval = setInterval(updateTimer, 1000);
}
});
}
const TIMER_SECONDS = 5;
timedRefresh(TIMER_SECONDS);
Edit:
The answer above does not work with reloads using window.location.realod(). A code solving the issue may look like this:
const TIMER_SECONDS = 60;
/*
* Update span with current time
* `currentTime` is an integer bigger than zero or a string '#' meaning 'timer stopped'
*/
function updateDisplayTimer(currentTime){
const countdownSpan = document.getElementById("countdown");
countdownSpan.innerHTML = currentTime;
}
/*
* A timer with `loopDuration` seconds. After finished, the timer is cleared.
* `loopDuration` is an integer bigger than zero, representing the time duration in seconds.
*/
function timedRefresh(loopDuration) {
let currentTime = loopDuration;
let interval = setInterval(() => {
if (currentTime > 0) {
updateDisplayTimer(currentTime);
currentTime -= 1;
} else {
window.location.reload(); // refresh page
}
}, 1000);
window.addEventListener('load', () => {
if(window.document.hasFocus()){
timedRefresh(TIMER_SECONDS);
} else {
updateDisplayTimer("#");
clearInterval(interval);
interval = null;
}
});
window.addEventListener('focus', () => {
if(interval == null){
window.location.reload(); // refresh page
}
});
}
// exeute main fucntion
timedRefresh(TIMER_SECONDS);
Use window.document.hasFocus() to determine if the user is focused on your webpage or not.

timer starts automatically instead of on a button press in javascript

I'm quite new to javascript so the answer is probably quite easy but anyways
I'm trying to make a simple click speed test but i cant get the timer to start when the user presses the click me button, so i resorted to just starting it automatically. if anyone can help me to start it on the button press it will be much appreciated
HTML code:
<button id="click2" onclick="click2()">Click Me!</button><br>
<span id="clicksamount">0 Clicks</span><br><br>
<span id="10stimer">10s</span>
JS code:
var click = document.getElementById("click2");
var amount = 0;
var seconds = 10;
var endOfTimer = setInterval(click2, 1000);
function click2() {
seconds--;
document.getElementById("10stimer").innerHTML = seconds + "s";
if (seconds <= 0) {
var cps = Number(amount) / 10;
document.getElementById("clicksamount").innerHTML = "You got " + cps + " CPS!";
document.getElementById("click2").disabled = true;
document.getElementById("10stimer").innerHTML = "Ended";
clearInterval(seconds);
}
}
document.getElementById("click2").onclick = function() {
amount++;
document.getElementById("clicksamount").innerHTML = amount + " Clicks";
}
It looks like you're overwriting your onclick function on the button with id click2 with the lowest 4 lines.
Also, you call clearInterval() with the seconds variable instead of the actual interval, which is referenced by endOfTimer.
I'd suggest to have a separated timer management in a function which you call only on the first click of your button.
See JSFiddle
<button id="clickbutton" onclick="buttonClick()">Click Me!</button><br>
<span id="clicksamount">0 Clicks</span><br><br>
<span id="secondcount">10s</span>
// We will have timerStarted to see if the timer was started once,
// regardless if it's still running or has already ended. Otherwise
// we would directly restart the timer with another click after the
// previous timer has ended.
// timerRunning only indicates wether the timer is currently running or not.
var timerStarted = false;
var timerRunning = false;
var seconds = 10;
var clickAmount = 0;
var timer;
function buttonClick() {
if (!timerStarted) {
startTimer();
}
// Only count up while the timer is running.
// The button is being disabled at the end, therefore this logic is only nice-to-have.
if (timerRunning) {
clickAmount++;
document.getElementById("clicksamount").innerHTML = clickAmount + " Clicks";
}
}
function startTimer() {
timerStarted = true;
timerRunning = true;
timer = setInterval(timerTick,1000);
}
function timerTick() {
seconds--;
document.getElementById("secondcount").innerHTML = seconds + "s";
if (seconds <= 0) {
timerRunning = false;
clearInterval(timer);
var cps = Number(clickAmount) / 10;
document.getElementById("clickbutton").disabled = true;
document.getElementById("clicksamount").innerHTML = "You got " + cps + " CPS (" + clickAmount + "clicks in total)!";
}
}
I made some changes to your code. Effectively, when the user clicks the first time, you start the timer then. The timer variables is null until the first the user clicks.
var click = document.getElementById("click2");
var noOfClicks = 0;
var seconds = 10;
var timer = null;
function doTick(){
seconds--;
if(seconds<=0){
seconds = 10;
clearInterval(timer);
document.getElementById("10stimer").innerHTML= "Ended"
timer=null;
document.getElementById("click2").disabled = true;
}
updateDisplay()
}
function updateClicks(){
if(!timer){
timer=setInterval(doTick, 1000);
clicks= 0;
seconds = 10;
}
noOfClicks++;
updateDisplay();
}
function updateDisplay(){
var cps = Number(noOfClicks) / 10;
document.getElementById("clicksamount").innerHTML = "You got " + cps + " CPS!";
document.getElementById("10stimer").innerHTML =seconds;
}
click.addEventListener('click', updateClicks)
https://jsbin.com/bibuzadasu/1/edit?html,js,console,output
function timer(startEvent, stopEvent) {
let time = 0;
startEvent.target.addEventListener(startEvent.type, () => {
this.interval = setInterval(()=>{
time++;
}, 10); // every 10 ms... aka 0.01s
removeEventListener(startEvent.type, startEvent.target); // remove the listener once we're done with it.
stopEvent.target.addEventListener(startEvent.type, () => {
clearInterval(this.interval); // stop the timer
// your output function here, example:
alert(time);
removeEventListener(stopEvent.type, stopEvent.target); // remove the listener once we're done with it.
});
});
}
Use event listeners rather than onclicks
usage example:
HTML
<button id="mybutton">Click me!</button>
JS
/* ABOVE CODE ... */
let mybutton = document.getElementById("mybutton");
timer(
{target: mybutton, type: "click"},
{target: mybutton, type: "click"}
);
function timer(startEvent, stopEvent) {
let time = 0;
startEvent.target.addEventListener(startEvent.type, () => {
this.interval = setInterval(()=>{
time++;
}, 10); // every 10 ms... aka 0.01s
removeEventListener(startEvent.type, startEvent.target); // remove the listener once we're done with it.
stopEvent.target.addEventListener(startEvent.type, () => {
clearInterval(this.interval); // stop the timer
// your output function here, example:
alert(time);
removeEventListener(stopEvent.type, stopEvent.target); // remove the listener once we're done with it.
});
});
}
let mybutton = document.getElementById("mybutton");
timer(
{target: mybutton, type: "click"},
{target: mybutton, type: "click"}
);
<button id="mybutton">Click me!</button>
//state initialization
var amount = 0;
var seconds = 10;
var timedOut=false;
var timerId=-1;
//counters display
var clicksDisplay= document.getElementById("clicksamount");
var timerDisplay= document.getElementById("10stimer");
function click2(e){
//first click
if(timerId===-1){
//start timer
timed();
}
//still in time to count clicks
if(!timedOut){
amount++;
clicksDisplay.innerText=amount +" Clicks";
}
}
function timed(){
//refresh timer dispaly
timerDisplay.innerText=seconds+"s";
seconds--;
if(seconds<0){
//stop click count
timedOut=true;
}else{
//new timerId
timerId=setTimeout(timed,1000);
}
}

How to stop countdown after a few rounds?

var secondsP = document.getElementById('seconds');
var btn1 = document.getElementById("btnSurrender");
var clock = null;
btn1.addEventListener("click", surrender);
function timer () {
clearInterval(clock);
var start = new Date().getTime();
clock = setInterval(function() {
var seconds = Math.round(15 - (new Date().getTime() - start) / 1000);
if (seconds >= 0) {
secondsP.textContent = seconds;
} else {
clearInterval(clock);
}
if (seconds === 0) {
}
}, 1000);
}
function surrender(){
clearInterval(clock);
secondsP.textContent = 0;
setTimeout(timer,2000);
}
timer();
setInterval(timer, 17000);
<html>
<head>
<style>
</style>
<script src="/scripts/snippet-javascript-console.min.js?v=1"></script>
</head>
<body>
<p id="seconds">15</p>
<button id= "btnSurrender">end now</button>
</body>
</html>
I need help with my little problem. I made a stopwatch which counts down 15 seconds. After this 15 seconds, it waits two seconds and starts again. You have option to stop counting when you want to, using "end now" button (then it'll start again after 2 sec). Now, my question is: how can I make a function which is going to stop whole counting after 3/4 rounds?
You restart the clock in surrender() using the call setTimeout(timer, 2000). All you need to do is add an if statement inside that function testing a variable that controls how many times you have run the timer, and then call/not call timer() accordingly. Here is a working example of it: https://jsfiddle.net/L38q6k5d/, but just to give you an idea of how it would work:
At the top of the js file:
var timesRun = 0
var timerInterval = null;
Inside the surrender function:
timesRun += 1 // Increment it each time the timer ends
if (timesRun > 4) { // If the timer has run less than 4 times
return; // this will stop the function here, so we dont start the timer again
}
setTimeout(timer, 2000); // Reset the timer
Inside the timer function,
if (timesRun > 1) {
clearInterval(timerInterval);
return; // end the function here
}
When starting the initial timer:
timer();
timerInterval = setInterval(timer, 17000);
Complete JS:
var secondsP = document.getElementById('seconds');
var btn1 = document.getElementById("btnSurrender");
var clock = null;
var timerInterval = null;
// New Code
var numberOfTimesRun = 0; // this is where we keep track of how many times the timer has run
btn1.addEventListener("click", surrender);
function timer () {
clearInterval(clock);
// New Code
if (numberOfTimesRun > 1) {
clearInterval(timerInterval);
return; // end the function here
}
// End New Code
var start = new Date().getTime();
clock = setInterval(function() {
var seconds = Math.round(15 - (new Date().getTime() - start) / 1000);
if (seconds >= 0) {
secondsP.textContent = seconds;
} else {
clearInterval(clock);
numberOfTimesRun += 1; // so we know that 1 iteration of the timer has been completed
}
if (seconds === 0) {
}
}, 1000);
}
function surrender(){
clearInterval(clock);
secondsP.textContent = 0;
//New Code
numberOfTimesRun += 1;
if (numberOfTimesRun > 4) {
return; // end the function there
}
setTimeout(timer, 2000)
//End New Code
}
timer();
timerInterval = setInterval(timer, 17000);

Javascript Countdown Timer Repeat and Count total that repeat

I have javascript countdown timer from 25 -> 0.
var count=25;
var counter=setInterval(timer, 1000); //1000 will run it every 1 second
function timer()
{
count=count-1;
if (count <= 0)
{
clearInterval(counter);
return;
}
document.getElementById("timer").innerHTML=count; // watch for spelling
}
div HTML
<span id="timer">25</span>
Now I want the countdown is repeat automatically after wait 5 seconds then it start again from 25 -> 0. And I want to count how many times that countdown repeat. Is it possible for that?
Please help.
You can try wrapping the entire code into a function (countTimers() in the example below) that runs every 30 seconds (5 seconds after each timer). Then, set a counter (timersCount in the example below) to count how many times that will run.
See the example below:
var timersCount = 0, stopped = false, count, counter; // make count, counter global variables so buttons can access them
var timerCounter = setInterval(countTimers, 30000);
countTimers(); // run countTimers once to start
function timer() {
count = count-1;
document.getElementById("timer").innerHTML=count;
if(count <= 0) {
clearInterval(counter);
return;
}
}
function countTimers() {
timersCount++;
// as per request in the comments, you can set a timer counter as well:
document.getElementById("totalcounter").innerHTML = timersCount;
count = 25;
counter = setInterval(timer, 1000);
}
// button code:
document.getElementById("reset").addEventListener("click", function() {
clearInterval(timerCounter);
clearInterval(counter);
count = 25;
document.getElementById("timer").innerHTML=count;
timersCount = 0;
document.getElementById("totalcounter").innerHTML = timersCount;
stopped = true;
});
document.getElementById("stop").addEventListener("click", function() {
if(stopped)
return;
clearInterval(counter);
stopped = true;
});
document.getElementById("start").addEventListener("click", function() {
if(!stopped)
return;
stopped = false;
counter = setInterval(timer, 1000);
setTimeout(function() {
clearInterval(counter);
timerCounter = setInterval(countTimers, 30000);
countTimers();
}, count*1000);
});
Timer: <span id="timer">25</span><br>
Number of times run: <span id="totalcounter">1</span>
<br><br>
<button id="reset">Reset</button>
<button id="stop">Stop</button>
<button id="start">Start (if stopped)</button>
var count=25;
var counter = null;
// reset count and timer
function reset_timer()
{
count = 25;
counter=setInterval(timer, 1000); //1000 will run it every 1 second
}
// init timer for first time
reset_timer();
function timer()
{
count--;
if (count <= 0)
{
clearInterval(counter);
setTimeout(reset_timer, 5000);
return;
}
document.getElementById("timer").innerHTML=count; // watch for spelling
}
setTimeout is a timer that runs one time and stop.
This approach uses Promises to the countdown work and generate an infinite loop,
if for some reason you need to stop/resume your counter you can reject the Promise chain and have a boolean to control the state:
let secondsCounter =
document.querySelector('#secondsCounter'),
totalCount =
document.querySelector('#totalCount'),
ttc = 1,
actualSecond = 25,
isPaused = false,
interval;
let countDown = time => new Promise( (rs, rj) => interval = setInterval( ()=>{
if (isPaused) {
return rj('Paused');
}
secondsCounter.textContent = --actualSecond;
if (actualSecond == 0){
actualSecond = time + 1;
clearInterval(interval);
rs();
}
}, 1000));
let loop = time => countDown(time).then( ()=>{
totalCount.textContent = ++ttc;
return Promise.resolve(null);
});
let infinite = () => loop(25)
.then(infinite)
.catch(console.log.bind(console));
let stop = () => {
clearInterval(interval);
isPaused = true;
}
let resume = () => {
console.log('Resumed');
isPaused = false;
loop(actualSecond).then(infinite);
}
let start_stop = () => isPaused ?
resume() : stop();
infinite();
Seconds : <div id="secondsCounter">25</div>
Times : <div id="totalCount">1</div>
<button onclick="start_stop()">Start/Stop</button>

jquery fire event after timeout

I've implemented auto page scrolling using the jQuery plugin datatables.
I'm attempting to add two buttons, one that stops the auto scrolling and one that starts it again. I've gotten this working, but I want it to begin scrolling again if the page has been stopped for a period of time. Here is what I have tried:
var refreshRate = 5;
var totalPages = 0;
var currentPage = 0;
var upTime = 0;
$('document').ready(function(){
var interval = window.setInterval('$("#start").click()',refreshRate);
$("#start").click(function(){
function start(){
clearInterval(timeout);
$("#stop").show();
$("#start").hide();
currentPage = table.api().page.info().page + 1;
totalPages = table.api().page.info().pages;
table.api().ajax.reload(function(json){
if (currentPage != totalPages){
table.api().page('next').draw(false);
}
else{
table.api().page('first').draw(false);
}
});
upTime = upTime + (refreshRate / 1000);
clearInterval(interval);
interval = setInterval('$("#start").click()', refreshRate);
}
start();
});
$("#stop").click(function(){
$("#stop").hide();
$("#start").show();
timeout();
clearInterval(interval);
});
//call start on doc ready to auto start scrolling
start();
function timeout(){
var timeout = window.setInterval(function(){
start();
}, 10000);
}
});
As you can see I am attempting to call the start() function embedded within the button click after a 10 second timeout. I am also getting a TypeError when I call start() at DOM ready to begin page scrolling.
Uncaught TypeError: object is not a function
But besides the error it scrolls as it should.
Any assistance?
You are having issues with function scope. Your code that called start towards the bottom did not have start in its scope since you defined it inside the click handler. Also, timeout was outside of the scope too, which would cause the interval to go on forever:
$('document').ready(function(){
var timeout,
interval = window.setInterval('$("#start").click()',refreshRate);
function start(){
clearInterval(timeout);
$("#stop").show();
$("#start").hide();
currentPage = table.api().page.info().page + 1;
totalPages = table.api().page.info().pages;
table.api().ajax.reload(function(json){
if (currentPage != totalPages){
table.api().page('next').draw(false);
}
else{
table.api().page('first').draw(false);
}
});
upTime = upTime + (refreshRate / 1000);
clearInterval(interval);
interval = setInterval('$("#start").click()', refreshRate);
}
function timeout(){
timeout = setInterval(function(){
start();
}, 10000);
}
$("#start").click(function(){
start();
});
$("#stop").click(function(){
$("#stop").hide();
$("#start").show();
timeout();
clearInterval(interval);
});
//call start on doc ready to auto start scrolling
start();
});

Categories