I'm trying to make a reaction test website just for fun, but I don't know how to calculate the time taken between button presses.
I found this
var startTime;
function startButton() {
startTime = Date.now();
}
function stopButton() {
if (startTime) {
var endTime = Date.now();
var difference = endTime - startTime;
alert('Reaction time: ' + difference + ' ms');
startTime = null;
} else {
alert('Click the Start button first');
}
}
but it only works for 2 buttons (I only want one). So I tried making a function, something like
function calculateTime(){
startButton();
stopButton();
}
but of course, it doesn't work since it will stop the timer immediately. Any way to get around it?
Use a single function that checks whether startTime has been set or not. If it hasn't been set, it sets it; otherwise, it reports the time difference.
let startTime = null;
const button = document.querySelector("#timer");
button.addEventListener("click", startStop);
const output = document.querySelector("#output");
function startStop() {
if (startTime) {
var endTime = Date.now();
var difference = endTime - startTime;
output.innerText = 'Reaction time: ' + difference + ' ms';
startTime = null;
button.innerText = "Start Timer";
} else {
startTime = Date.now();
button.innerText = "Stop Timer";
output.innerText = "";
}
}
<button id="timer">Start Timer</button><br>
<div id="output"></div>
You were close. You need to declare the start time outside of the function so that it persists between function calls and then use the else section of the if statement to set it.
let startTime;
document.querySelector("button").addEventListener("click", startStop);
function startStop() {
if (startTime) {
console.log("Clock stopped");
var endTime = Date.now();
var difference = endTime - startTime;
alert('Reaction time: ' + difference + ' ms');
startTime = null;
} else {
startTime = Date.now();
console.log("Clock started");
}
}
<button>Start/Stop</button>
You can use performace.now() or console.time to calucalte time after press button.
var performance = window.performance;
var t0 = performance.now();
------your function--------
var t1 = performance.now();
console.log("This function took " + (t1 - t0) + " milliseconds.")
function a() {
console.time("buttontimer");
... your function ...
var dur = console.timeEnd("buttontimer"); // NOTE: dur only works in FF
}
Related
I want to create a 3 hours countdown that runs in the background and repeats when it reaches 00:00:00. How can I do it using HTML and javascript? Thank you!
You can use Web Worker:
Run in background
No throttled ( settimeout-setinterval-on-inactive-tab )
// index.html
<div id="box">60</div>
<script>
let box = document.getElementById('box');
let worker = new Worker('countdown.js');
worker.postMessage(60);
worker.onmessage = function (event) {
box.innerHTML = event.data;
}
</script>
// countdown.js
onmessage = function (e) {
let num = e.data;
let count = setInterval(function () {
postMessage(--num);
if (num <= 0) {
clearInterval(count);
close();
}
}, 1000);
}
For background countdown. I think the big issue that you need to face is when you are leave the page or open a new tabs. right?
Do you want to make the countdown work even the tab is not active?
maybe requestAnimationFrame is helpful for you.
function showTime() {
remainingTime = getRemainingTime(endTime);
var seconds = pad((remainingTime / 1000));
console.log('remain time is: ', seconds + " sec")
if (remainingTime >= 1000) {
window.requestAnimationFrame(showTime);
} else {
console.log('Time up!!!')
}
}
function getRemainingTime(deadline) {
var currentTime = new Date().getTime();
return deadline - currentTime;
}
function pad(value) {
var sl = (""+Math.floor(value)).length;
if(sl > 2){
return ('0' + Math.floor(value)).slice(-sl);
}
return ('0' + Math.floor(value)).slice(-2);
}
endTime = new Date().getTime() + 1000*60;
window.requestAnimationFrame(showTime);
Demo here: https://codepen.io/quanhv/pen/oNZWxvB
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I want to make multiples stopwatches in jquery, but the problem is i want the stopwatch the respective stopwatch to sun when we hit the corresponding button, and should stop when we hit button for another stopwatch and that respective stopwatch should start simultaneously, please see the image for reference, i know the question is not so clear, sorry for inconvenience.
thanks in advance.
try this one:
$(document).ready(function() {
(function($){
$.extend({
APP : {
formatTimer : function(a) {
if (a < 10) {
a = '0' + a;
}
return a;
},
startTimer : function(dir) {
var a;
// save type
$.APP.dir = dir;
// get current date
$.APP.d1 = new Date();
switch($.APP.state) {
case 'pause' :
// resume timer
// get current timestamp (for calculations) and
// substract time difference between pause and now
$.APP.t1 = $.APP.d1.getTime() - $.APP.td;
break;
default :
// get current timestamp (for calculations)
$.APP.t1 = $.APP.d1.getTime();
// if countdown add ms based on seconds in textfield
if ($.APP.dir === 'cd') {
$.APP.t1 += parseInt($('#cd_seconds').val())*1000;
}
break;
}
// reset state
$.APP.state = 'alive';
$('#' + $.APP.dir + '_status').html('Running');
// start loop
$.APP.loopTimer();
},
pauseTimer : function() {
// save timestamp of pause
$.APP.dp = new Date();
$.APP.tp = $.APP.dp.getTime();
// save elapsed time (until pause)
$.APP.td = $.APP.tp - $.APP.t1;
// change button value
$('#' + $.APP.dir + '_start').val('Resume');
// set state
$.APP.state = 'pause';
$('#' + $.APP.dir + '_status').html('Paused');
},
stopTimer : function() {
// change button value
$('#' + $.APP.dir + '_start').val('Restart');
// set state
$.APP.state = 'stop';
$('#' + $.APP.dir + '_status').html('Stopped');
},
resetTimer : function() {
// reset display
$('#' + $.APP.dir + '_ms,#' + $.APP.dir + '_s,#' + $.APP.dir + '_m,#' + $.APP.dir + '_h').html('00');
// change button value
$('#' + $.APP.dir + '_start').val('Start');
// set state
$.APP.state = 'reset';
$('#' + $.APP.dir + '_status').html('Reset & Idle again');
},
endTimer : function(callback) {
// change button value
$('#' + $.APP.dir + '_start').val('Restart');
// set state
$.APP.state = 'end';
// invoke callback
if (typeof callback === 'function') {
callback();
}
},
loopTimer : function() {
var td;
var d2,t2;
var ms = 0;
var s = 0;
var m = 0;
var h = 0;
if ($.APP.state === 'alive') {
// get current date and convert it into
// timestamp for calculations
d2 = new Date();
t2 = d2.getTime();
// calculate time difference between
// initial and current timestamp
if ($.APP.dir === 'sw') {
td = t2 - $.APP.t1;
// reversed if countdown
} else {
td = $.APP.t1 - t2;
if (td <= 0) {
// if time difference is 0 end countdown
$.APP.endTimer(function(){
$.APP.resetTimer();
$('#' + $.APP.dir + '_status').html('Ended & Reset');
});
}
}
// calculate milliseconds
ms = td%1000;
if (ms < 1) {
ms = 0;
} else {
// calculate seconds
s = (td-ms)/1000;
if (s < 1) {
s = 0;
} else {
// calculate minutes
var m = (s-(s%60))/60;
if (m < 1) {
m = 0;
} else {
// calculate hours
var h = (m-(m%60))/60;
if (h < 1) {
h = 0;
}
}
}
}
// substract elapsed minutes & hours
ms = Math.round(ms/100);
s = s-(m*60);
m = m-(h*60);
// update display
$('#' + $.APP.dir + '_ms').html($.APP.formatTimer(ms));
$('#' + $.APP.dir + '_s').html($.APP.formatTimer(s));
$('#' + $.APP.dir + '_m').html($.APP.formatTimer(m));
$('#' + $.APP.dir + '_h').html($.APP.formatTimer(h));
// loop
$.APP.t = setTimeout($.APP.loopTimer,1);
} else {
// kill loop
clearTimeout($.APP.t);
return true;
}
}
}
});
$('#sw_start').live('click', function() {
$.APP.startTimer('sw');
});
$('#cd_start').live('click', function() {
$.APP.startTimer('cd');
});
$('#sw_stop,#cd_stop').live('click', function() {
$.APP.stopTimer();
});
$('#sw_reset,#cd_reset').live('click', function() {
$.APP.resetTimer();
});
$('#sw_pause,#cd_pause').live('click', function() {
$.APP.pauseTimer();
});
})(jQuery);
});
DEMO HERE
OR
$(function () {
// Never assume one widget is just used once in the page. You might
// think of adding a second one. So, we adjust accordingly.
$('.stopwatch').each(function () {
// Cache very important elements, especially the ones used always
var element = $(this);
var running = element.data('autostart');
var hoursElement = element.find('.hours');
var minutesElement = element.find('.minutes');
var secondsElement = element.find('.seconds');
var millisecondsElement = element.find('.milliseconds');
var toggleElement = element.find('.toggle');
var resetElement = element.find('.reset');
var pauseText = toggleElement.data('pausetext');
var resumeText = toggleElement.data('resumetext');
var startText = toggleElement.text();
// And it's better to keep the state of time in variables
// than parsing them from the html.
var hours, minutes, seconds, milliseconds, timer;
function prependZero(time, length) {
// Quick way to turn number to string is to prepend it with a string
// Also, a quick way to turn floats to integers is to complement with 0
time = '' + (time | 0);
// And strings have length too. Prepend 0 until right.
while (time.length < length) time = '0' + time;
return time;
}
function setStopwatch(hours, minutes, seconds, milliseconds) {
// Using text(). html() will construct HTML when it finds one, overhead.
hoursElement.text(prependZero(hours, 2));
minutesElement.text(prependZero(minutes, 2));
secondsElement.text(prependZero(seconds, 2));
millisecondsElement.text(prependZero(milliseconds, 3));
}
// Update time in stopwatch periodically - every 25ms
function runTimer() {
// Using ES5 Date.now() to get current timestamp
var startTime = Date.now();
var prevHours = hours;
var prevMinutes = minutes;
var prevSeconds = seconds;
var prevMilliseconds = milliseconds;
timer = setInterval(function () {
var timeElapsed = Date.now() - startTime;
hours = (timeElapsed / 3600000) + prevHours;
minutes = ((timeElapsed / 60000) + prevMinutes) % 60;
seconds = ((timeElapsed / 1000) + prevSeconds) % 60;
milliseconds = (timeElapsed + prevMilliseconds) % 1000;
setStopwatch(hours, minutes, seconds, milliseconds);
}, 25);
}
// Split out timer functions into functions.
// Easier to read and write down responsibilities
function run() {
running = true;
runTimer();
toggleElement.text(pauseText);
}
function pause() {
running = false;
clearTimeout(timer);
toggleElement.text(resumeText);
}
function reset() {
running = false;
pause();
hours = minutes = seconds = milliseconds = 0;
setStopwatch(hours, minutes, seconds, milliseconds);
toggleElement.text(startText);
}
// And button handlers merely call out the responsibilities
toggleElement.on('click', function () {
(running) ? pause() : run();
});
resetElement.on('click', function () {
reset();
});
// Another advantageous thing about factoring out functions is that
// They are reusable, callable elsewhere.
reset();
if(running) run();
});
});
DEMO HERE
Why doesn't this fire the first time? I'm not sure I understand this, please help! When I run pause() the second time, then it fires. Not sure what i'm doing wrong here.
this.pause = function (stopwatch){
this.stopwatch = stopwatch;
socket.emit('pauseTime'); //server does fire "paustime"
// this doesn't fire
socket.on('pauseTimeClock', function(data){
stopWatchClock.setPausedTime(data.time);
$('.pauseTime').html(data.time.replace(/(\d)/g, '<span>$1</span>'))
console.log(stopWatchClock.pausedTime);
});
this.stopwatch.changeState(this.stopwatch.getPauseState());
}
server code
socket.on('pauseTime', function () {
//stop broadcasting countDown time
clearInterval(timeinterval);
var pausedTime = moment();
function pauseTimeClock() {
var timeDiffHour = moment().hour() - pausedTime.hour();
var timeDiffMinute = moment().minute() - pausedTime.minute();
var timeDiffSec = moment().second();
var displayTime = timeDiffHour + ":" + timeDiffMinute + ":" + timeDiffSec;
socket.broadcast.emit("pauseTimeClock", { time: moment(displayTime, 'hhmm').format('HH:mm') });
console.log(timeDiffHour);
console.log(timeDiffMinute);
}
setInterval(pauseTimeClock, 1000);
})
var myVar = setInterval(function() {
myTimer()
}, 1000);
var d = 1;
function myTimer() {
document.getElementById("demo").innerHTML = d++;
}
Can any one help me how to set the dynamic timer in JavaScript?
I'm trying to create a quiz application and I need to run a timer for the questions which is already available in the database.
I have to retrieve a time from the database and I have to run a count-down timer.
What about something like this. It doesn't reply on the timer being perfect.
var running = false;
var timeToRun = 10000; // 10 seconds
var startTime;
var timer;
var output = document.getElementById("output");
function start(){
running = true;
startTime = new Date();
timer = setInterval(check, 100);
output.innerHTML = "Started<br>" + output.innerHTML;
}
function stop(){
running = false;
clearInterval(timer);
}
function check(){
var now = new Date();
var left = (startTime - now) + timeToRun;
output.innerHTML = left + "<br>" + output.innerHTML;
if (left < 0){
stop();
output.innerHTML = "times up <br>" + output.innerHTML;
}
}
start();
<div id="output">o</div>
function myTimer(d) {
d++;
document.getElementById("demo").innerHTML = d;
return d;
}
var d = 1;
var myVar = setInterval(function() {
d = myTimer(d);
}, 1000);
like this?
[Edit after reading comments:]
var endpoint = [php_timestamp_here];
var countdown = setInterval(function() {
var d = new Date();
var ts = d.getTime();
if( ts >= endpoint ){
// stuff after reach the point...
clearInterval(countdown);
}
// stuff every second
}, 1000);
Il try to explain this as simple as I can.
I'm trying to make a timer app for practice. User should be abble to add a new Object, wich will be a timer + stop/start buttons.
At this point, its working with one object, but when I create another object, the old one stops working(i belive it loses the pointer to it, or somthing like that), and the new one works.
Dont worry, about the buttons functionality,thats not important, all I want to understand how do I save the object, after a new one is created.
here is JS:
var startTime = 0;
var itemNum = 0;
var obName;
var arrayForTimers = [];
function timerObject(obName) {
this.nameField = "start";
this.classField = "timer";
this.block = " ";
this.obName = obName;
this.startButton = " ";
this.stopButton = " ";
this.placeholder = document.getElementsByClassName("timer-placeholder")[0];
this.addBlock = function () {
this.block = document.createElement("DIV");
this.block.className = this.classField;
this.block.className += " " + this.obName;
this.placeholder.appendChild(this.block);
}
this.renderTime = function () {
this.startTime = startTime;
this.endTime = new Date();
// time difference in ms
this.timeDiff = this.endTime - this.startTime;
// strip the miliseconds
this.timeDiff /= 1000;
// get seconds
this.seconds = Math.round(this.timeDiff % 60);
// remove seconds from the date
this.timeDiff = Math.floor(this.timeDiff / 60);
// get minutes
this.minutes = Math.round(this.timeDiff % 60);
// remove minutes from the date
this.timeDiff = Math.floor(this.timeDiff / 60);
// get hours
this.hours = Math.round(this.timeDiff % 24);
this.block.innerHTML = this.hours + " h " + this.minutes + " min " + this.seconds + " sec";
// window.setInterval('this.obName.renderTime()',1000);// Uncomment if you want to test your PCs limit
}
this.renderButtons = function () {
var timePassed;
//this.parentTimer = document.getElementsByClassName("timer "+this.obName)[0];
this.startButton = document.createElement("INPUT");
this.startButton.setAttribute("type", "button");
this.startButton.setAttribute("value", "start");
this.startButton.className = "start " + this.obName;
this.stopButton = document.createElement("INPUT");
this.stopButton.setAttribute("type", "button");
this.stopButton.setAttribute("value", "stop");
this.stopButton.className = "stop " + this.obName;
this.placeholder.insertBefore(this.startButton, this.block);
this.placeholder.insertBefore(this.stopButton, this.block);
this.startButton.addEventListener("click", function () {
//if (this.hours === 0 && this.minutes === 0 && this.seconds === 0){
this.startTime = new Date();
// }
tm = window.setInterval('obName.renderTime()', 1000);
})
this.stopButton.addEventListener("click", function () {
window.clearInterval(tm);
//timePassed = this.endTime - this.startTime;
//endTime = new Date();
// timePassed = endTime - startTime;
})
//give listener to clear and start interval
}
};
function createNewTimer() {
obName = document.getElementById("ObName").value;
if (obName !== "") {
obName = new timerObject(obName);
obName.addBlock();
obName.renderButtons();
startTime = new Date();
obName.renderTime();
//arrayForTimers.push(obName);
//window.setInterval('obName.renderTime()',1000);
} else {
document.getElementById("ObName").value = "Fill me";
}
};
Here is a Js Fiddle http://jsfiddle.net/3qxoea52/4/
P.S. sorry for my grammar, not my native languege.
Thanks.
The problem is here
tm = window.setInterval('obName.renderTime()', 1000);
This means that when you click any of the start buttons it will always start the object currently associated with obName.
Also, you only have a single global variable tm to store the timer, so when you do
window.clearInterval(tm);
It is clearing whichever timer was last set.
And you also have a single global startTime, which is causing all of the timers to reset whenever you create a new timer.
Another problem is that you have nothing to store the time when you stop each timer, so if you stop then restart it, it will not continue at the same point.
You can fix these problems by:
using self = this to create a stable reference to the object
use function.bind to make sure an event handler will be bound to the right timer object
add a property this.startDiff so that the time is saved when you stop then restart the clock
make tm a local variable within the TimerObject
set this.startTime within the object instead of outside it.
-- as in the code below (jsfiddle)
function TimerObject(obName) {
var self = this,
tm;
this.startTime = new Date();
this.startDiff = 0;
this.nameField = "start";
this.classField = "timer";
this.block = " ";
this.obName = obName;
this.startButton = " ";
this.stopButton = " ";
this.placeholder = document.getElementsByClassName("timer-placeholder")[0];
this.addBlock = function () {
this.block = document.createElement("DIV");
this.block.className = this.classField;
this.block.className += " " + this.obName;
this.placeholder.appendChild(this.block);
};
this.renderTime = function () {
var timeDiff = new Date() - this.startTime + this.startDiff;
this.timeDiff = timeDiff;
timeDiff /= 1000;
// get seconds
this.seconds = Math.round(timeDiff % 60);
// remove seconds from the date
timeDiff = Math.floor(timeDiff / 60);
// get minutes
this.minutes = Math.round(timeDiff % 60);
// remove minutes from the date
timeDiff = Math.floor(timeDiff / 60);
// get hours
this.hours = Math.round(timeDiff % 24);
this.block.innerHTML = this.hours + " h " + this.minutes + " min " + this.seconds + " sec";
// window.setInterval('this.obName.renderTime()',1000);// Uncomment if you want to test your PCs limit
};
this.renderButtons = function () {
var timePassed;
//this.parentTimer = document.getElementsByClassName("timer "+this.obName)[0];
this.startButton = document.createElement("INPUT");
this.startButton.setAttribute("type", "button");
this.startButton.setAttribute("value", "start");
this.startButton.className = "start " + this.obName;
this.stopButton = document.createElement("INPUT");
this.stopButton.setAttribute("type", "button");
this.stopButton.setAttribute("value", "stop");
this.stopButton.className = "stop " + this.obName;
this.placeholder.insertBefore(this.startButton, this.block);
this.placeholder.insertBefore(this.stopButton, this.block);
this.startButton.addEventListener("click", function () {
//if (this.hours === 0 && this.minutes === 0 && this.seconds === 0){
self.startTime = new Date();
// }
tm = window.setInterval(self.renderTime.bind(self), 1000);
});
this.stopButton.addEventListener("click", function () {
window.clearInterval(tm);
self.startDiff = self.timeDiff;
console.log(':', self, self.startDiff);
//timePassed = this.endTime - this.startTime;
//endTime = new Date();
// timePassed = endTime - startTime;
});
//give listener to clear and start interval
};
}
function createNewTimer() {
obName = document.getElementById("ObName").value;
if (obName !== "") {
obName = new TimerObject(obName);
obName.addBlock();
obName.renderButtons();
obName.renderTime();
//window.setInterval('obName.renderTime()',1000);
} else {
document.getElementById("ObName").value = "Fill me";
}
}
There were several issues with the code:
1. Some functions weren't being bound to the correct context (this).
2. The reference set to "obName" was global and constantly changing to the newly created instance.
3. The start time variable was global and constantly being reset every time you called the renderTime function.
I have made the modifications to your code in jsFiddle and they can be found in this update: http://jsfiddle.net/3qxoea52/5/
Rendering:
this.renderTime = function (startTime) {
if( startTime ) {
this.startTime = startTime;
}
this.endTime = new Date();
// time difference in ms
this.timeDiff = this.endTime - this.startTime;
// strip the miliseconds
this.timeDiff /= 1000;
// get seconds
this.seconds = Math.round(this.timeDiff % 60);
// remove seconds from the date
this.timeDiff = Math.floor(this.timeDiff / 60);
// get minutes
this.minutes = Math.round(this.timeDiff % 60);
// remove minutes from the date
this.timeDiff = Math.floor(this.timeDiff / 60);
// get hours
this.hours = Math.round(this.timeDiff % 24);
this.block.innerHTML = this.hours + " h " + this.minutes + " min " + this.seconds + " sec";
// window.setInterval('this.obName.renderTime()',1000);// Uncomment if you want to test your PCs limit
}
Binding:
this.startButton.addEventListener("click", function () {
//if (this.hours === 0 && this.minutes === 0 && this.seconds === 0){
this.startTime = new Date();
// }
this.tm = window.setInterval(this.renderTime.bind(this), 1000);
}.bind(this))
this.stopButton.addEventListener("click", function () {
window.clearInterval(this.tm);
//timePassed = this.endTime - this.startTime;
//endTime = new Date();
// timePassed = endTime - startTime;
}.bind(this))
CreateTimer:
function createNewTimer() {
obName = document.getElementById("ObName").value;
if (obName !== "") {
obName = new timerObject(obName);
obName.addBlock();
obName.renderButtons();
startTime = new Date();
obName.renderTime(startTime);
//window.setInterval('obName.renderTime()',1000);
} else {
document.getElementById("ObName").value = "Fill me";
}
};