I'm having some problem with setInterval() - javascript

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>

Related

Cant Make a function run again

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>

How to Use Count Down in Javascript Using A String Length stored in an Array

var allQuestionsArray = ["question1 asffdsdsfd","question2 asdffffsd","question3 asddda","question ajsdjj 4"];
var loop = [];
$.each(allQuestionsArray, function (index, key) {
loop = key.length;
timeOut(loop);
setTimeout(function () {
$(#question-' + index + '-section').fadeOut(),
$('#question-' + index + '-section').fadeIn();
}, (loop * 1000));
});
function startTimer(duration, display) {
console.log(duration);
var start = Date.now(),
diff,
minutes,
seconds;
function timer() {
// get the number of seconds that have elapsed since
// startTimer() was called
if(duration <= 0){
display.textContent = "00:00";
}else{
diff = duration - (((Date.now() - start) / 1000) | 0);
//console.log(diff);
// 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) {
start = Date.now() + 1000;
}
}
};
timer();
setInterval(timer, 1000);
}
function timeOut(limit) {
display = document.querySelector('#time');
startTimer(limit, display);
}
1- What I am expecting from this code it should generate a countdown and needs to hideout all questions section except one it should work till the loop completed.
2- I want my code take the length of every string stored in the array and assign it to the timer == "timeOut(string.length)" that's what my mean.
3- The problem is when the code executes the timer starts according to the length of last string "question ajsdjj 4" doesn't start from the first string of the array.
I want to start the timer from first string of the array when the timer completes then it has to move to second string of the array and so on.

How to format time with AngularJS filters?

I have a timer that is counting down from a value that is being set by some user.
They enter some number which is being treated as minutes. number * 1000 * 60 to convert it into milliseconds - and from there the counter is counting down and decrements this number.
What I want to do is format this number as minutes and seconds so if the entered number is 3.5, it should be shown as 03:30.
I've tried using the date filter which is provided by Angular but it's not in sync with the value of the timer. It would decrement once and then stops.
Code:
<h4 class="timer">{{ vm.timer.ticks | date: "mm:ss"}}</h4>
The background for the timer is in a service
start(duration) {
this.ticks = duration;
this.timer = this.$interval(() => {
if (this.ticks === 0) return this.stop();
this.ticks--;
}, 1000);
}
I think it is because you are hiding "this" in your inner function. Try to rewrite it as (untested!):
start(duration) {
var ticks = duration;
this.timer = this.$interval(() => {
if (ticks === 0) return this.stop();
ticks--;
}, 1000);
}
Ok, so... I made a terrible mistake when I was calculating the time...
I set up $scope.$watch to watch over my variable from the service and according to that i was changing couple other variables.
$scope.$watch('vm.timer.ticks', value => {
if (value <= 0) {
vm.timer.count = 0;
vm.timer.latest = '';
}
if(vm.timer.ticks > 0) {
seconds = vm.timer.ticks % 60;
minutes = Math.floor(vm.timer.ticks / 60);
filledMinutes = minutes < 10 ? "0" + minutes : minutes;
filledSeconds = seconds < 10 ? "0" + seconds : seconds;
vm.displayTime = filledMinutes + ':' + filledSeconds;
} else {
vm.displayTime = '00:00';
}
});

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()

javascript countdown stutter

I have a countdown like this one:
var countdown = {
startInterval: function() {
var count = 600
var countorig = 600;
var currentId = setInterval(function() {
var min = (count - (count % 60)) / 60;
var sec = count % 60;
if (sec < 10) {
$('#timer').html(min + ':0' + sec);
} else {
$('#timer').html(min + ':' + sec);
}
$('#time').val(countorig - count);
if (count == 0) {
$('#form').submit();
}--count;
}, 1000);
countdown.intervalId = currentId;
}
};
It works. But if I load the page, the countdown starts but it stutter it is not "round" like a clock is.
JSFiddle.
setInterval isn’t exact. You should use Dates instead, to get an accurate time, and then choose an interval of less than one second to get a smoother clock. Here’s a demo!
var countdown = {
startInterval: function() {
var count = 600;
var start = new Date(); // The current date!
var currentId = setInterval(function() {
var difference = Math.max(0, count - (new Date() - start) / 1000 | 0);
var min = difference / 60 | 0;
var sec = difference % 60;
$('#timer').text(min + ':' + (sec < 10 ? '0' : '') + sec);
$('#time').val(difference);
if(count === 0) {
$('#form').submit();
}
}, 200);
countdown.intervalId = currentId;
}
};
It's never a good idea to assume your timers are exact. Instead, use delta timing.
var startTime = new Date().getTime();
setInterval(function() {
var elapsed = new Date().getTime()-startTime;
console.log("Been running for "+Math.floor(elapsed/1000)+" seconds");
},25);
That is because setInterval is not meant to be a high resolution timer. It will NOT hit every 1000 milliseconds on the dot. You might have swings as much as 20 to 30 milliseconds in either direction, resulting in a clock that is off.
Using Date.now(), this is a quick example of a countdown function ( x is milliseconds )
function countdown(x){
var o = {future: Date.now()+x, last:-1, i:null}; // object so we can pass by-ref if req.
o.i = setInterval( function() { // use o.i so we can clear interval
var remain = o.future - Date.now(),
secs = Math.floor( remain / 1000 ),
mins = 0;
if( remain < 0 ){ // finished, do whatever
return clearInterval(o.i); // then clear & exit
}
if( secs === o.last ) return; // skip this iteration if it's not been a second
o.last = secs; // else update last time
// do whatever you want for this new second
if( secs > 59 ) mins = Math.floor( secs / 60 ), secs = secs % 60;
console.log(
(mins < 10 ? '0'+mins : mins) + ':' +
(secs < 10 ? '0'+secs : secs) + ' remain.'
);
}, 100);
}
If you know it wont be used in IE, consider adding o as an argument to the callback function in the interval and also as the last argument to setInterval (so it is passed to the callback as first arg), which means closure is independent => callback can be defined anywhere.

Categories