I made a timer that will reach zero.
and when it reaches zero make the timer run again.
the timer goes back to the starting number but doesnt run again.
also when i call it again the numbers just start to jump.
the code:
var timerPlace = document.getElementById('timer');
var timerP = document.getElementById('timerHard');
var stopTimer;
var toStop;
function timeMed() {
console.log('im in!')
var counter = 0;
var timeLeft = 5;
timerPlace.innerHTML = '00:45';
function timeIt() {
console.log('here')
counter++
timerPlace.innerHTML = convertSeconds(timeLeft - counter);
if (timerPlace.innerHTML == '00:00') {
clearInterval(stopTimer);
resetExercise();
timeMed();
}
}
function convertSeconds(s) {
var sec = s % 60;
var min = Math.floor((s % 3600) / 60);
return ('0' + min).slice(-2) + ':' + ('0' + sec).slice(-2);
}
if (!stopTimer) {
stopTimer = setInterval(timeIt, 1000);
}
}
You only call setInterval() when stopTimer is not set. But after the countdown completes, stopTimer is still set to the ID of the old interval timer, so you don't restart it. You should clear the variable when you call clearInterval().
if (timerPlace.innerHTML == '00:00') {
clearInterval(stopTimer);
stopTimer = null;
resetExercise();
timeMed();
}
Modern ES6 Approach and best practices.
I've decided to take the chance and refactor your code a little with Javascripts best practices in mind.
I've added comments which explain the code, and the engineering considerations.
The baseline for the timer is taken from the excellent answer here: https://stackoverflow.com/a/20618517/1194694
// Using destructuring on the paramters, so that the keys of our configuration object,
// will be available as separate parameters (avoiding something like options.duraitons and so on.
function startTimer({duration, onUpdate , infinite}) {
let timer = duration, minutes, seconds;
let interval = setInterval(function () {
minutes = parseInt(timer / 60);
seconds = parseInt(timer % 60);
// you can also add hours, days, weeks ewtc with similar logic
seconds = seconds < 10 ? `0${seconds}` : seconds;
minutes = minutes < 10 ? `0${minutes}` : minutes;
// calling your onUpdate function, passed from configuraiton with out data
onUpdate({minutes, seconds});
if (--timer < 0) {
// if infinite is true - reset the timer
if(infinite) {
timer = duration;
} else {
// Clearing the interval + additonal logic if you want
// I would also advocate implementing an onEnd function,
// So that you'll be able to decide what to do from configuraiton.
clearInterval(interval);
}
}
}, 1000);
}
const duration = 5;
const displayElement = document.querySelector("#timer");
startTimer({
duration,
onUpdate: ({minutes, seconds}) => {
// now you're not constraint to rendering it in an element,
// but can also Pass on the data, to let's say your analytics platform, or whatnot
displayElement.textContent = `${minutes}:${seconds}`;
},
infinite: true
});
<div id="timer">
</div>
Related
I have interval that needs to do some http requests after one minute
setInterval(() => {
this.takeTableDataCallInterval();
}, 60000);
How can i get counter minus from my Interval Number ?
For example every one second i want to show something like
60 seconds Left until new call is maked
59 seconds Left until new call is maked
When it comes to 0 it should start over
Here is an example:
it works every one second in order to do the countdown but once it reach to the 60 it resets the countdown and does the request.
const timer = document.querySelector('#timer');
let counter = 60;
setInterval(() => {
if (counter === 0) {
//this.takeTableDataCallInterval();
counter = 60;
}
else {
timer.innerHTML = `${counter} seconds left`;
counter--;
}
}, 1000);
<p id="timer"></p>
Counting shorter setInterval periods is one way of doing this, although timings here are rarely accurate enough to decently measure the passage of time, and you'll see drift (i.e. 60 one second intervals won't sum to exactly 60s)
Instead, record a "due time" with a high accuracy using performance.now()
let dueTimeMs = performance.now() + 60000;
then set an interval with relatively short time
setInterval(() => {
const nowMs = performance.now();
const timeUntilDueMs = dueTimeMs - nowMs;
// report remaining time
if(timeUntilDueMs <= 0){
// do something
dueTimeMs += 60000;
}
},100);
Try this:
let timeout;
function resetTimeout(limit) {
timeout = limit;
}
function serviceCall() {
console.log('Service call made')
}
setInterval(() => {
if(timeout == 0 || timeout == null) {
(timeout == 0) ? serviceCall() : ''
resetTimeout(60);
}
console.log(`${timeout}s left until new call is made`)
timeout --;
}, 1000);
I have a web page where I entered a countdown code and it works well. However, I can only call it 1 time with the id in html.
Second or third time, it no longer works. How can I always use it? I would need it 3 or 4 times on the page. Thank you.
This is the code:
var counter = null;
window.onload = function() {
initCounter();
};
function initCounter() {
// get count from localStorage, or set to initial value of 1000
count = getLocalStorage('count') || 1000;
counter = setInterval(timer, 1000); //1000 will run it every 1 second
}
function setLocalStorage(key, val) {
if (window.localStorage) {
window.localStorage.setItem(key, val);
}
return val;
}
function getLocalStorage(key) {
return window.localStorage ? window.localStorage.getItem(key) : '';
}
function timer() {
count = setLocalStorage('count', count - 1);
if (count == -1) {
clearInterval(counter);
return;
}
var seconds = count % 60;
var minutes = Math.floor(count / 60);
var hours = Math.floor(minutes / 60);
minutes %= 60;
hours %= 60;
document.getElementById("timer").innerHTML = hours + " ore " + minutes + " min " + seconds + " sec"; // watch for spelling
}
You need to encapsulate the functionality in a way that can be called many times. It usually helps to think about the question "As a programmer, how I'd like to use this?"
Usually, it's a single function that takes some parameters and does something and/or returns something.
As an example... wouldn't it be nice if we had a function startMyTimer(...) that takes a timerId, and an element and sets up a timer that will update that element? We already have the signature:
function startMyTimer(timerId, element) { ... }
And now you can build everything inside this function. JS allows declaring functions within functions, which helps with encapsulation, so copying from your code it would look like:
function startMyTimer(timerId, element) {
var count = getLocalStorage(timerId) || 1000;
var counter = setInterval(timer, 1000); //1000 will run it every 1 second
function timer() {
count = setLocalStorage(timerId, count - 1);
if (count == -1) {
clearInterval(counter);
return;
}
var seconds = count % 60;
var minutes = Math.floor(count / 60);
var hours = Math.floor(minutes / 60);
minutes %= 60;
hours %= 60;
element.innerHTML = hours + " ore " + minutes + " min " + seconds + " sec"; // watch for spelling
}
}
Note that now count and counter are both private to the scope of startMyTimer, so only within this function (and any function inside this one, such as function timer()) will see these variables.
So if you want to do exactly what you did, you'd use this function as
window.onload = function() {
startMyTimer('count', document.getElementById("timer"));
};
Again, this is just an example of a posible solution - Maybe you could pass in the element id instead of the element, or a timer duration, etc., and the best solution is the one that fits best your needs.
I want my stopwatch as if 60 seconds complete . There should be an increment in minute and seconds to start from 0 again . I tried so many ways to do so but it always stop working when time is one minute .. is it built in problem in setInterval()
async timer() {
var timeout = setInterval(() => {
count++
this.timerSecond.innerText = count;
if (count > 59) {
count = 0;
this.timerSecond.innerText = count;
count1++
this.timerMinute.innerText = count1
}
}, 100);
console.log(timeout);
return timeout;
}
Does this method work for you?
timer () {
let seconds = 0;
const tick = () => {
this.timerText.textContent = seconds;
this.timerSecond.textContent = `${seconds % 60}`.padStart(2, '0');
this.timerMinute.textContent = Math.floor(seconds / 60);
seconds++;
};
tick();
return setInterval(tick, 1000);
}
It's hard to tell why you had two separate setInterval() calls, but I removed the one called every 100 milliseconds and combined the logic into a single one.
The timerSecond uses modulo 60 of seconds, and timerMinute uses result of integer division by 60, while the timerText just receives the seconds directly, as in your initial code.
The async keyword didn't add any value to your code, since none of it uses promises, so I removed it.
Here's a slightly elaborated example to demonstrate functionality:
class Stopwatch {
timerText = document.querySelector('.text');
timerSecond = document.querySelector('.second');
timerMinute = document.querySelector('.minute');
timer () {
let seconds = 0;
const tick = () => {
this.timerText.textContent = seconds;
this.timerSecond.textContent = `${seconds % 60}`.padStart(2, '0');
this.timerMinute.textContent = Math.floor(seconds / 60);
seconds++;
};
tick();
return setInterval(tick, 1000);
}
}
new Stopwatch().timer();
<div class="text"></div>
<div>
<span class="minute"></span>:<span class="second"></span>
</div>
This is nice and simple:
var seconds = 0;
setInterval(function(){
tick(document.getElementById("timer"), ++seconds);
}, 1000);
function tick(ele, secs){
ele.innerHTML = Math.floor(secs / 60) + ":" + (secs % 60 < 10 ? "0" : "") + secs % 60;
}
<span id="timer">0:00</span>
Math.floor(secs / 60) gives us the minutes and excludes any remainder of seconds, secs % 60 gives us the remainder of seconds after we've divided by 60 (so it essentially removes the minutes), and (secs % 60 < 10 ? "0" : "") gives us a leading "0" if the seconds (excluding whole minutes) is less than 10.
Here is a basic example of how to make a counter that counts down from 60 (or any other number) and display it on the page.
// Reference to html element that holds the count
const counterDiv = document.getElementById('counter');
// Variable that will keep track of the seconds to count down from
const secondsToCount = 60;
// Set the initial value of the counter to the secondsToCount variable.
// The counter will be updated each 1000ms | 1s and will be changed
// to the value of the remaining seconds to count down from
// which is why this variable is let opposed to const
let counter = secondsToCount;
// Set the initial text of the counter html element
counterDiv.innerHTML = secondsToCount;
// Function that is going to do counting for us.
const interval = setInterval( () => {
// Decrement the current counter value by 1
counter--;
// Update the text to show the new value of our counter
counterDiv.innerHTML = counter;
// If the counter is === 0, the counter is finished. She some text.
if (counter === 0) {
// Clear the interval (otherwise, you'll continue to count
// into the negative numbers
clearInterval(interval);
// Show the completed text
counterDiv.innerHTML = `Done counting down from ${secondsToCount} seconds`;
}
}, 1000); // 1000 ms | 1s
<!-- Element used to show the count -->
<div id="counter"></div>
I'm creating pomodoro timer- interval should repeat with different duration after first one completes. simplified non working exampe:
var firstDuration=5;
var secondDuration=10;
var timer=setInterval(()=>{
firstDuration--
if (firstDuration<0){
clearInterval(timer) ..
//secondDuration-- dont know how to continue..
What is the best way to implement such functionality? Also i plan to use Date.now() rather than -- .
If i've understood the requirements correctly, this will do what you want. It will have a timer go off every second until 20 minutes have elapsed, then every second until 5 minutes have elapsed. At that point it starts over with the 20 minute countdown.
const workDurationSeconds = 20 * 60;
const breakDurationSeconds = 5 * 60;
function startCountdown(session) {
let duration;
if (session === 'work') {
duration = workDurationSeconds;
} else {
duration = breakDurationSeconds;
}
let id = setInterval(() => {
duration--;
if (duration <= 0) {
clearInterval(id);
startCountdown(session === 'work' ? 'break' : 'work');
}
}, 1000);
}
EDIT & UPDATE: for reference I rewrote the whole thing with only 1 timer and a second to time converter. Very clean and less complex. Here is the full code: http://pastebin.com/Hb6cBryL
I got this timer that I built out of javascript: http://powerpoint.azurewebsites.net/
It is quite simple code, but for the final implementation I would need to be able to pause the timer and restart it. I use 2 setIntervalls, 1 for the minutes that triggers every 60s and one for the seconds that triggers every second.
When I pause it I clear the intervals. However when I restart them the minutes restart at the 60 interval and aren't synced with the seconds anymore.
I probably implemented this in a horribly wrong way so I'd like to ask for your advice. 1 idea I had was to continue the inverval but avoid updating the variable and text on the page so that the minutes/seconds stay in sync< However this doesn't sound like an ideal solution to me. All tips are welcome :)
Js code:
var minutes = null, seconds = null, cnt, secs;
function settimer(frm) { if (minutes == null) { cnt = frm.timeinput.value - '1'; secs = '59';} };
function stop() {
clearInterval(minutes);
clearInterval(seconds);
minutes = null;
seconds = null;
document.getElementById("minutes").innerHTML = '00';
document.getElementById("seconds").innerHTML = '00';
}
function pause() {
clearInterval(minutes);
clearInterval(seconds);
}
function runtimer() {
event.preventDefault();
if (minutes == null) {
document.getElementById("minutes").innerHTML = cnt;};
minutes = setInterval(function () {
if (cnt == '0') { stop() } else { cnt -= 1; document.getElementById("minutes").innerHTML = cnt; };
}, 6000);
if (seconds == null) { document.getElementById("seconds").innerHTML = secs; };
seconds = setInterval(function () {
if (secs == '0') { secs = '59' } else { secs -= 1; document.getElementById("seconds").innerHTML = secs; };
}, 100);
}
You'll need to wrap them somehow, and recognise that you can't immediately get the timer's id.
function setIntervalWithOffset(fn, delay, offset) {
var o = {id: null, o_id: null};
o.o_id = window.setTimeout(function () {
o.id = window.setInterval(fn, delay);
}, offset);
return o;
}
function setTimeoutWithOffset(fn, delay, offset) {
var o = {id: null, o_id: null};
o.o_id = window.setTimeout(function () {
o.id = window.setTimeout(fn, delay);
}, offset);
return o;
}
To clear, use window.clearTimeout on obj.o_id and whichever type you set for obj.id.
You should also consider whether you'd be better off implementing a setTimeout loop rather than using setInterval so you don't have a chance of a cascade error
Sorry, I think that you are in a bad way. Why do you want to use two intervals to do the same thing? Intervals are asynchronous, you can not synchronize two intervals that runs independently.
You can achieve that with just one interval. To show seconds, you can just increment another variable each time that your counter reachs a threshold:
var counter = 0;
var seconds = 0;
var $interval = setInterval(function(){
counter++;
if (counter >= 6000) {
counter = counter - 6000;
seconds++;
}
, 10);
So, it will be more easy to stop/restart your interval.
You need to get the handle to the timer, in order to be able to reset it later, you can do like below:
timeoutHandle = setTimeout(function(){/*code*/}, 1000);
clearTimeout(timeoutHandle);
Take a look at this jsfiddle
Taken from : How do I stop a window.setInterval in javascript?