javascript count down timer flickering on calling more than once - javascript

function countdown(element, minutes, seconds) {
// set time for the particular countdown
var time = minutes*60 + seconds;
var interval = setInterval(function() {
var el = document.getElementById(element);
// if the time is 0 then end the counter
if(time == 0) {
//el.innerHTML = "countdown's over!";
// document.getElementById("timer").style.visibility="hidden";
clearInterval(interval);
return;
}
var hour=Math.floor( time / (60*60) );
if (hour < 10) hour = "0" + hour;
var minutes = 0;
if(time>=60 && hour>0)
minutes=Math.floor( (time / 60 )-60);
else{
minutes=Math.floor( (time / 60 ));
}
if (minutes < 10) minutes = "0" + minutes;
var seconds = time % 60;
if (seconds < 10) seconds = "0" + seconds;
// var text = hour+":"+minutes; //+ ':' + seconds;
var text = minutes; //+ ':' + seconds;
el.innerHTML = text;
time--;
}, 1000);
}
when i am calling the method 2wice, its creating flickering effect.
i.e. countdown(element, 50, 0);
it count downs but if i call it again i.e. countdown(element, 35, 0); it is flicks showing both the countddowns

You need to cancel the interval when the plugin initializes if you are going to call it on the same element. Otherwise you are running two intervals at once.
I'd suggest returning the interval from your function and allowing yourself to pass that interval in as a parameter. That way you can always cancel the interval before starting it (in case there is already one going). If you pass null for the interval var, you can still run clearInterval() without throwing errors.
For example:
function countdown(element, minutes, seconds, interval) {
// set time for the particular countdown
var time = minutes*60 + seconds;
clearInterval(interval);
return setInterval(function() {
...
Your first call could be:
var savedInterval = countdown('some-ele-id', 1, 1, null);
And your second call could be:
var interval = countdown('some-ele-id', 1, 1, savedInterval);
Another solution would be to save the interval as a global variable and cancel it without passing it as a parameter inside your plugin.

An alternative to avoid modify your code is:
var interval;
...
function countdown(element, minutes, seconds) {
// set time for the particular countdown
var time = minutes*60 + seconds;
interval = setInterval(function() {
...
And in your second call:
clearInterval(interval);
countdown(element, 35, 0);

Related

Countdown timer - make it persistent even after refresh or reload

I have a html page where there is counter starts on page loading. But the problem is if someone refresh or reloads the page the counter restarts. I dont know how to use local storage or cookies to make sure my counter does not reset upon reload. I am aware of the similar questions available here but my issue is i want local storage to be part of a function (countDown()).
Here is the code I tried:
<script>
var timer;
function countDown(i, callback) {
//callback = callback || function(){};
timer = setInterval(function() {
minutes = parseInt(i / 60, 10);
seconds = parseInt(i % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
document.getElementById("displayDiv ").innerHTML = "Time (h:min:sec) left for this station is " + "0:" + minutes + ":" + seconds;
i-- || (clearInterval(timer), callback());
}, 1000);
}
window.onload = function() {
countDown(60, function() {
$('#myModal').modal('show');
});
};
</script>
First, persist your current counter value to the session storage (with a specific key) at each iteration. You may only persist/update the value when the counter is greater than 0, and then clear the storage key once counter reached 0.
const COUNTER_KEY = 'my-counter';
function countDown(i, callback) {
//callback = callback || function(){};
timer = setInterval(function() {
minutes = parseInt(i / 60, 10);
seconds = parseInt(i % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
document.getElementById("displayDiv").innerHTML = "Time (h:min:sec) left for this station is " + "0:" + minutes + ":" + seconds;
if ((i--) > 0) {
window.sessionStorage.setItem(COUNTER_KEY, i);
} else {
window.sessionStorage.removeItem(COUNTER_KEY);
clearInterval(timer);
callback();
}
}, 1000);
}
Then on the window.onload function, first check if there is a value under the above key on the session storage. If a value is there, start the countdown from that value. Otherwise, start from your default value (60).
window.onload = function() {
var countDownTime = window.sessionStorage.getItem(COUNTER_KEY) || 60;
countDown(countDownTime, function() {
$('#myModal').modal('show');
});
};
You can try using localStorage as follows:
var timer;
function countDown(i, callback) {
//callback = callback || function(){};
timer = setInterval(function () {
minutes = parseInt(i / 60, 10);
seconds = parseInt(i % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
document.getElementById("displayDiv").innerHTML = "Time (h:min:sec) left for this station is " + "0:" + minutes + ":" + seconds;
// update the persisted time interval
localStorage.setItem('timeLeft', i);
i-- || (clearInterval(timer), callback());
}, 1000);
}
window.onload = function () {
let timeInterval = 100;
//check if you have the last counter value
let timeLeft = localStorage.getItem('timeLeft');
if (isNaN(timeLeft)) {
//save the current interval
localStorage.setItem('timeLeft', timeInterval);
} else if (timeLeft == 0) {
//save the current interval
localStorage.setItem('timeLeft', timeInterval);
} else {
// take the last saved value
timeInterval = timeLeft;
}
countDown(timeInterval, function () {
$('#myModal').modal('show');
});
};
I think what you want is a property called sessionStorage which stores information in the browser permanently.
here's a link explaining it
https://www.w3schools.com/jsref/prop_win_sessionstorage.asp
I have a made a promise based function for this.
It uses localStorage to store the countdown every 1 second and, once the time is over, it returns you a promise.
I use it with React and React Router on production, it's been working great.
function countdown(interval = 5000) {
return new Promise(async (resolve, reject) => {
let intervalLoop = null
function countTimer() {
if (!localStorage.endTime) {
localStorage.endTime = +new Date() + interval
}
let remaining = localStorage.endTime - new Date()
if (remaining >= 0) {
let currentTime = Math.floor(remaining / 1000)
console.log("Countdown current time:", currentTime)
} else {
clearInterval(intervalLoop)
resolve(true)
}
}
intervalLoop = setInterval(countTimer, 1000)
})
}
Make sure you are inside an async function to use it:
(async _ => {
console.log("Countdown starts now...")
await countdown(5000)
console.log("Countdown is over!");
})()

Timer is not triggering after one minute using jQuery or give some other solution to trigger function after every 1 min?

var setTimer;
var isTimeSet = false;
if (!isTimeSet) {
setTimer = $('#hdn_timerTime').val();
isTimeSet = true;
}
initialTimer();
function initialTimer() {
var CustomMinutes = 60 * parseInt(setTimer),
display = $('#time');
startTimer(CustomMinutes, display);
}
function startTimer(duration, display) {
var timer = duration, minutes, seconds;
setInterval(function () {
minutes = parseInt(timer / 60, 10)
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.text(minutes + ":" + seconds);
if (--timer < 0) {
timer = duration;
$('#outputmeters').val(JSON.stringify(listItem));
// _hardMeter.UpdateMeterData();
_hardMeter.TempUpdateMeterDataConfirmation();
}
}, 1000);
}
This code I am using but for the first time it work fine than after that it time start reducing and function fire very quickly. I don't know how it happening.
Please help me out in this and if you have some better solution for it. Could you please share it?
You can use setInterval to call the same function repeatedly at set intervals until either the page is unloaded or you call clearInterval:
var timedFunction = function() {
... // Do something
}
setInterval(timedFunction, 60 * 1000);
If your timed function takes arguments which change each time, use setTimeout and call it within the function body as well
var timedFunctionWithArguments = function(iterations) {
console.debug(iterations); // Do something
setTimeout(timedFunctionWithArguments, 60 * 1000, iterations++);
}
timedFunctionWithArguments(0);

javascript timer keeps reseting too soon (not working)

// This timer keeps reseting back to 2:00 after it reaches 1 minute. Also i do not get a notification that says times up at the right time. Can someone please correct the code. Also the stop/resume timer button also has to stay functional.
var isRunning = false;
var ticker; //this will hold our setTimeout
var seconds,
minutes;
function countdown(mins, secs) {
//i made these global, so we can restart the timer later
seconds = secs || 60; //if user put in a number of minutes, use that. Otherwise, use 60
minutes = mins;
console.log('time stuff',mins,secs,minutes,seconds)
function tick() {
var counter = document.getElementById("timer");
var current_minutes = mins - 1
seconds--;
counter.innerHTML =
current_minutes.toString() + ":" + (seconds < 10 ? "0" : "") + String(seconds);
if (seconds < 1 && minutes) {
//seconds reached 0, and still minutes left;
seconds=60;
minutes--;
}
if ((seconds > 0 || minutes > 0) && isRunning) {
ticker = setTimeout(tick, 1000);
} else if(isRunning){
console.log(seconds,minutes,isRunning)
alert('Time\'s up, brah!')
}
}
tick();
}
function timeToggle() {
isRunning = !isRunning; //if it's false, set it true. If it's true, set it false.
if (!isRunning) {
clearTimeout(ticker); //or whatever else you set the initial timeOut to.
} else {
//not running! and time is defined;
var sec = seconds||60;
console.log('def!',minutes, sec)
countdown(minutes, sec);
}
}
isRunning = true;
countdown(2);
<div id="timer">2:00</div>
<button onclick="timeToggle()">Stop time</button>
There is a small flaw in your logic.
During the countdown initialization your doing
seconds = secs || 60;
Which effectively add 60 seconds to the time you want if you don't initialize the seconds. see:
function countdownInit(mins, secs) {
seconds = secs || 60;
minutes = mins;
console.log(mins + 'min ' + seconds + 'sec');
}
countdownInit(1, 30) // ok
// 1min 30sec
countdownInit(1) // not ok
// 1min 60sec
// thats 2 minutes
The second issue here is that you use a var current_minutes that equals minutes - 1 to display the time. So you are not showing the real counter.
the fix is as follow:
function countdown(mins, secs) {
seconds = secs;
minutes = mins;
// if secs is 0 or uninitialized we set seconds to 60 and decrement the minutes
if(!secs) {
minutes--;
seconds = 60;
}
function tick() {
var counter = document.getElementById("timer");
seconds--;
// we use minutes instead of current_minutes in order to show what's really in our variables
counter.innerHTML =
minutes.toString() + ":" + (seconds < 10 ? "0" : "") + String(seconds);
// rest of code
}
// rest of code
}
I tried to keep as much as your code as possible.

how to change text when coundown zero

Hello my countdown not Stop at zero i need to change my test when countdown going to zero, This countdown start again after zero value i need to replace value after countdown is zero ..... $countdown = 50
function startTimer(duration, display) {
var start = Date.now(),
diff,
minutes,
seconds;
function timer() {
// get the number of seconds that have elapsed since
// startTimer() was called
diff = duration - (((Date.now() - start) / 1000) | 0);
// does the same job as parseInt truncates the float
minutes = (diff / 60) | 0;
seconds = (diff % 60) | 0;
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
if (diff <= 0) {
// add one second so that the count down starts at the full duration
// example 05:00 not 04:59
start = Date.now() + 1000;
}
};
// we don't want to wait a full second before the timer starts
timer();
setInterval(timer, 1000);
}
window.onload = function () {
var fiveMinutes = <?php echo $countdown?>
display = document.querySelector('#time');
startTimer(fiveMinutes, display);
};
PHP In body
if ($countdown>3){
echo "Next Submit: Wait <span id='time'></span>";
}else{
echo "Next Submit: READY....!";
}
You should save the setInterval() call to a variable.
var myTimer = setInterval();
This way you can reference it later. Then, you can have a call within your function to check for a certain condition (in your case when the countdown reaches 0) and then use clearInterval() to end the timer.
Topic covering clearInterval()

Jquery building multiple timers and .each(function() {

I am trying to build multiple timers for my web page, so far I have,
$('.timer').each(function() {
var timer = setInterval(function() {
var time = $(this).text().split(':');
var minutes = parseInt(time[0], 10);
var seconds = parseInt(time[1], 10);
// TIMER RUN OUT
if (!minutes && !seconds) {
// CLEAR TIMER
clearInterval(timer);
// MINUS SECONDS
} else {
seconds -= 1;
}
// MINUS MINUTES
if (seconds < 0 && minutes != 0) {
minutes -= 1;
seconds = 59;
// ADD ZERO IF SECONDS LESS THAN 10
} else {
if (seconds < 10) {
seconds = '0' + seconds;
}
}
// ADD ZERO IF MINUTES LESS THAN 10
if (minutes < 10) {
minutes = '0' + minutes;
}
}, 1000);
});
This doesn't work though! Where am I going wrong!
Thanks
First, inside your setInterval callback, this no longer refers to the .timer element. Try changing that to self and add var self = this; before the call to setInterval. Second, you never write your time back to your .timer element.
Are you trying to display a clock counting down? In that case, you're not updating the text after all the calculations. Try adding:
$(this).text(minutes+':'+seconds);

Categories