I want to make a stopwatch in JavaScript that could count milliseconds, seconds and minutes. This is what I have: (you can stop the timer by pressing space)
var counter = document.getElementsByTagName('h1')[0];
var miliseconds = 0;
var seconds = 0;
var minutes = 0;
function Add() {
miliseconds++;
if (miliseconds >= 99) {
miliseconds = 0;
seconds++;
if (seconds >= 59) {
seconds = 0;
minutes++;
}
}
counter.textContent = (minutes ? (minutes > 9 ? minutes : "0" + minutes) : "00") + ":" +
(seconds ? (seconds > 9 ? seconds : "0" + seconds) : "00") + ":" +
(miliseconds ? (miliseconds > 9 ? miliseconds : "0" + miliseconds) : "00");
Timer();
}
function Timer() {
t = setTimeout(Add, 10);
}
Timer();
document.addEventListener("keypress", function(e) {
if (e.keyCode === 32) {
clearTimeout(t);
}
});
<h1 id="counter">00:00:00</h1>
The problem is that it seems to not go at the proper speed, meaning that when I compare it to other timers, it gradually becomes slower than them (i.e the speed at which the timer is counting slows down over time). So suddenly, there are 5-second differences, then it becomes 7-second differences and so on.
Any help would be appreciated.
You should create a startTime variable, then calculate the elapsedTime, and use that to calculate additional variable to show.
var startTime = Date.now();
setTimeout(function(){
var elapsedTime = Date.now() - startTime;
// Additional code to calculate hour, minute, second, milisecond here
}, 10);
Related
I am a JS newbie. I have a 24hrs Countdown timer which resets on page reload, however i want to save the start progress using LocalStorage so that it ends exactly after 24hrs. Which means that it does not stop or restart as soon as it has started even when the page is closed. It would always continue the countdown when the page is visited. My code is below
<div class="ml-2">Time Remainingā<span id="remainingTime"></span></div>
<script>
// this code set time to 24 hrs
var timer2 = "36:00:00";
var session_timer = localStorage.getItem('timer2');
if(session_timer){
console.log('timer2',session_timer);
timer2 = session_timer;
}
var interval = setInterval(function() {
var timer = timer2.split(':');
//by parsing integer, I avoid all extra string processing
var hours = parseInt(timer[0], 10);
var minutes = parseInt(timer[1], 10);
var seconds = parseInt(timer[2], 10);
--seconds;
minutes = (seconds < 0) ? --minutes : minutes;
hours = (minutes < 0) ? --hours : hours;
if (hours < 0) clearInterval(interval);
minutes = (minutes < 0) ? 59 : minutes;
minutes = (minutes < 10) ? '0' + minutes : minutes;
hours = (hours < 10) ? '0' + hours : hours;
if (minutes < 0) clearInterval(interval);
seconds = (seconds < 0) ? 59 : seconds;
seconds = (seconds < 10) ? '0' + seconds : seconds;
minutes = (minutes < 10) ? minutes : minutes;
timer2 = hours+ ':' +minutes + ':' + seconds;
if(hours <= 0 && minutes == 0 && seconds == 0){
// if you want to delete it on local storage
// localStorage.removeItem('timer');
console.log('Transaction Cancelled')
}
else{
$('#remainingTime').html(timer2);
// if you want to save it on local storage
// localStorage.setItem('timer', timer2);
}
}, 1000);
</script>
To save something in Local Storage you can use localStorage.setItem(key, value)
To get something from Local Storage you can use localStorage.getItem(key, value)
if(hours <= 0 && minutes == 0 && seconds == 0){
// if you want to delete it on local storage
localStorage.removeItem('timer');
console.log('Transaction Cancelled')
}
else{
$('#remainingTime').html(timer2);
// if you want to save it on local storage
localStorage.setItem('timer', timer2.toString());
}
Using luxon js and calculating as Millis versus handling hours, minutes and seconds
// this code set time to 24 hrs
let duration = luxon.Duration.fromObject({
days: 1
});
var interval;
function tick() {
let remaining = localStorage.getItem("interval") || duration.toMillis();
remaining -= 1000;
let d = luxon.Duration.fromMillis(remaining);
console.log(d.toHuman());
localStorage.setItem("interval", remaining);
}
function onLoad() {
var interval = setInterval(tick, 1000);
console.log("Timer Started");
}
function onUnLoad() {
cancelInterval(interval);
console.log("Timer Stopped");
}
onLoad();
onUnLoad();
<script src="https://moment.github.io/luxon/global/luxon.min.js"></script>
I've a script like this:
<span class="countdown">5:00</span>
<script type="text/javascript">
$(document).ready(function() {
var timer2 = "5:01";
var interval = setInterval(function() {
var timer = timer2.split(':');
//by parsing integer, I avoid all extra string processing
var minutes = parseInt(timer[0], 10);
var seconds = parseInt(timer[1], 10);
--seconds;
minutes = (seconds < 0) ? --minutes : minutes;
if (minutes < 0) clearInterval(interval);
seconds = (seconds < 0) ? 59 : seconds;
seconds = (seconds < 10) ? '0' + seconds : seconds;
//minutes = (minutes < 10) ? minutes : minutes;
$('.countdown').html(minutes + ':' + seconds);
timer2 = minutes + ':' + seconds;
}, 1000);
});
</script>
On the same page, I have a button which is supposed to reset the timer as part of it's functionality.
$('#liveorderfeedwidget').on('click', function() {
$(".countdown").empty();
$('.countdown').off();
var timer2 = "5:01";
var interval = setInterval(function() {
var timer = timer2.split(':');
//by parsing integer, I avoid all extra string processing
var minutes = parseInt(timer[0], 10);
var seconds = parseInt(timer[1], 10);
--seconds;
minutes = (seconds < 0) ? --minutes : minutes;
if (minutes < 0) clearInterval(interval);
seconds = (seconds < 0) ? 59 : seconds;
seconds = (seconds < 10) ? '0' + seconds : seconds;
//minutes = (minutes < 10) ? minutes : minutes;
$('.countdown').html(minutes + ':' + seconds);
timer2 = minutes + ':' + seconds;
}, 1000);
. . . . . . . .
But whenever I click the button to reset the timer, it does not fully clear the first binded event.
Let's say I click the button when it is at 2:39.
The timer/countdown class span flashes, says 5:00, and then goes in continuous cycle like this
2:39 5:00 2:38 4:59 2:37 4:58 etc etc
Apparently $(".countdown").empty(); and $('.countdown').off(); in my reset button timer is not working as intended.
What is needed to fully clear the previous event and refresh the .countdown to its fully reset state?
edit:
Here's a full jsfiddle with the issue observed:
https://jsfiddle.net/fw6Lzm0o/
You have 2 variables named interval. One is global and one is local to button onclick. Then you are missing the clearInterval() method that actually stops the timer. Then the empty or off is not required, you want to put 5:00 there.
Here is the code that needs to be changed:
$('#liveorderfeedwidget').on('click', function() {
$(".countdown").html('5:00');
//$(".countdown").empty();
//$('.countdown').off();
var timer2 = "5:01";
clearInterval(interval); //clear the timer
interval = setInterval(function() {
var timer = timer2.split(':');
//by parsing integer, I avoid all extra string processing
var minutes = parseInt(timer[0], 10);
var seconds = parseInt(timer[1], 10);
--seconds;
minutes = (seconds < 0) ? --minutes : minutes;
if (minutes < 0) clearInterval(interval);
seconds = (seconds < 0) ? 59 : seconds;
seconds = (seconds < 10) ? '0' + seconds : seconds;
//minutes = (minutes < 10) ? minutes : minutes;
$('.countdown').html(minutes + ':' + seconds);
timer2 = minutes + ':' + seconds;
}, 1000);
});
Here is the working fiddle.
Even better would be to make a function and call it on page load and on click... rather than having 2 set of exact duplicate codes.
like this:
var timer2, interval;
startTimer();
$('#liveorderfeedwidget').on('click', function() {
clearInterval(interval);
startTimer();
});
function startTimer() {
timer2 = "5:01";
$(".countdown").html('5:00');
interval = setInterval(function() {
var timer = timer2.split(':');
//by parsing integer, I avoid all extra string processing
var minutes = parseInt(timer[0], 10);
var seconds = parseInt(timer[1], 10);
--seconds;
minutes = (seconds < 0) ? --minutes : minutes;
if (minutes < 0) clearInterval(interval);
seconds = (seconds < 0) ? 59 : seconds;
seconds = (seconds < 10) ? '0' + seconds : seconds;
// minutes = (minutes < 10) ? minutes : minutes;
$('.countdown').html(minutes + ':' + seconds);
timer2 = minutes + ':' + seconds;
}, 1000);
}
Here is the working fiddle for this.
Halo, i have function timer, but the timer is already run before i click start. how to solve it, i want when i click start, the timer will be running. if i deleted seconds++ in first function, the time not running even i click start button the time is still 0. Thank you for help.
this is my code
var h1 = document.getElementsByTagName('h1')[0],
start = document.getElementById('start'),
stop = document.getElementById('stop'),
seconds = 0, minutes = 0, hours = 0,
t;
function add() {
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
if (minutes >= 60) {
minutes = 0;
hours++;
}
}
h1.textContent = (hours ? (hours > 9 ? hours : "0" + hours) : "00") + ":" + (minutes ? (minutes > 9 ? minutes : "0" + minutes) : "00") + ":" + (seconds > 9 ? seconds : "0" + seconds);
timer();
}
function timer() {
t = setTimeout(add, 1000);
}
timer();
/* Start button */
start.onclick = timer;
/* Stop button */
stop.onclick = function() {
clearTimeout(t);
}
<h1><time>00:00:00</time></h1>
<button id="start">start</button>
<button id="stop">stop</button>
Remove timer(); from your code
function timer() {
t = setTimeout(add, 1000);
}
//timer();
/* Start button */
start.onclick = timer;
Remove the stray timer(); on the line after declaring the function.
I am working with call connect and disconnect module in php using twilio api,Whenever i disconnect then timer not stop, Here is my code
//timer start when click on answer button
$('#answer').on('click', function() {
var countdown = document.getElementsByTagName('countdown')[0],
start = document.getElementById('start'),
stop = document.getElementById('stop'),
clear = document.getElementById('clear'),
seconds = 0, minutes = 0, hours = 0,
t;
function add() {
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
if (minutes >= 60) {
minutes = 0;
hours++;
}
}
countdown.textContent = (hours ? (hours > 9 ? hours : "0" + hours) : "00") + ":" + (minutes ? (minutes > 9 ? minutes : "0" + minutes) : "00") + ":" + (seconds > 9 ? seconds : "0" + seconds);
document.getElementById('checkyear').value = countdown.textContent;
timer();
}
function timer() {
t = setTimeout(add, 1000);
}
timer();
});
//Timer should stop when disconnect the call
Twilio.Device.disconnect(function (conn) {
clearTimeout(t);
});
Twilio developer evangelist here.
I think the issue here is one of scope. Your variable t, which is set to the ID of the timeouts you are using to count time up, is only available within the event handling function that is called when you click on the answer button.
When it's inside the Twilio.Device.disconnect handler, t is undefined.
I would rearrange your code so that the timing variables and functions are outside of the click event handler, so they are in scope for the disconnect handler. Something like this:
var t, seconds, minutes, hours;
Twilio.Device.disconnect(function(conn) {
clearTimeout(t);
});
function add() {
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
if (minutes >= 60) {
minutes = 0;
hours++;
}
}
countdown.textContent =
(hours ? (hours > 9 ? hours : '0' + hours) : '00') +
':' +
(minutes ? (minutes > 9 ? minutes : '0' + minutes) : '00') +
':' +
(seconds > 9 ? seconds : '0' + seconds);
document.getElementById('checkyear').value = countdown.textContent;
timer();
}
function timer() {
t = setTimeout(add, 1000);
}
$('#answer').on('click', function() {
var countdown = document.getElementsByTagName('countdown')[0],
start = document.getElementById('start'),
stop = document.getElementById('stop'),
clear = document.getElementById('clear');
seconds = 0;
minutes = 0;
hours = 0;
timer();
});
Suppose you wanted to set a timer to whatever time you want will be displayed in the form 00:00:00 minutes, seconds, and hundredths. How would you go about doing so? Please any help is greatly appreciated.
Here is the link in JSFiddle:
https://jsfiddle.net/mxpuejvz/2/
function decrement(){
var time = 600;
var mins = parseInt((time / 100) / 60);
var secs = parseInt((time / 100) % 60);
var hundredths = parseInt(time % 100);
if(mins < 10) {
mins = "0" + mins;
}
if(secs < 10) {
secs = "0" + secs;
}
if(hundredths < 10) {
hundredths = "0" + hundredths;
}
document.getElementById("output").innerHTML = mins + ":" + secs + ":" + hundredths;
if (hundredths === 0){
if(time ===0){
clearInterval(countdownTimer);
document.getElementById("output").innerHTML = "Time's Up.";
}else{
time--;
}
var countdownTimer = setInterval('decrement()', 10)
}
}
}
Three issues appear to need attention.
"time to go" needs to be stored outside the screen update function and decremented or calculated each time the screen is updated.
using parseInt to convert numbers to integer numbers is regarded as a hack by some. Math.floor() or integer calculation can be alternatives.
Timer call backs are not guaranteed to made exactly on time: counting the number of call backs for a 10msec time does not give the number of 1/100ths of elapsed time.
The following code is an example of how it could work, minus any pause button action.
var countdownTimer;
var endTime;
var counter = 0; // ** see reply item 3. **
function startCountDown( csecs) // hundredths of a second
{ endTime = Date.now() + 10*csecs; // endTime in millisecs
decrement();
countdownTimer = setInterval(decrement, 10);
counter = 0; // testing
}
function decrement()
{ var now, time, mins, secs, csecs, timeStr;
++ counter; // testing
now = Date.now();
if( now >= endTime)
{ time = 0;
timeStr = "Times up! counter = " + counter;
clearInterval( countdownTimer);
}
else
{ time = Math.floor( (endTime - now)/10); // unit = 1/100 sec
csecs = time%100;
time = (time-csecs)/100; // unit = 1 sec
secs = time % 60;
mins = (time-secs)/60; // unit = 60 secs
timeStr =
( (mins < 10) ? "0" + mins : mins) + ":" +
( (secs < 10) ? "0" + secs : secs) + ":" +
( (csecs < 10) ? "0" + csecs : csecs);
}
document.getElementById("output").innerHTML=timeStr;
}
The argument to startCountDown gives the number of 1/100ths of second for the count down. If the counter result is the same as the argument,try swapping browser tabs and back again during the countdown.
HTML to test:
<button type="button" onclick="startCountDown(600)">start</button>
<div id="output">
</div>