How to create a stopwatch using JavaScript? - javascript

if(stopwatch >= track[song].duration)
track[song].duration finds the duration of a soundcloud track.
I am looking to create a stopwatch function that starts counting milliseconds when you click on the swap ID stopwatch so that when the function has been "clicked" for a certain amount of time the if function will do something. In my case replace an image. And also that the function will reset it itself when clicked again.
so like stopwatch = current time - clicked time How can I set up the clicked time
current time = new Date().getTime(); ? And is this in milliseconds?
$('#swap').click(function()...

You'll see the demo code is just a start/stop/reset millisecond counter. If you want to do fanciful formatting on the time, that's completely up to you. This should be more than enough to get you started.
This was a fun little project to work on. Here's how I'd approach it
var Stopwatch = function(elem, options) {
var timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return document.createElement("span");
}
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render(0);
}
function update() {
clock += delta();
render();
}
function render() {
timer.innerHTML = clock / 1000;
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
// public API
this.start = start;
this.stop = stop;
this.reset = reset;
};
// basic examples
var elems = document.getElementsByClassName("basic");
for (var i = 0, len = elems.length; i < len; i++) {
new Stopwatch(elems[i]);
}
// programmatic examples
var a = document.getElementById("a-timer");
aTimer = new Stopwatch(a);
aTimer.start();
var b = document.getElementById("b-timer");
bTimer = new Stopwatch(b, {
delay: 100
});
bTimer.start();
var c = document.getElementById("c-timer");
cTimer = new Stopwatch(c, {
delay: 456
});
cTimer.start();
var d = document.getElementById("d-timer");
dTimer = new Stopwatch(d, {
delay: 1000
});
dTimer.start();
.stopwatch {
display: inline-block;
background-color: white;
border: 1px solid #eee;
padding: 5px;
margin: 5px;
}
.stopwatch span {
font-weight: bold;
display: block;
}
.stopwatch a {
padding-right: 5px;
text-decoration: none;
}
<h2>Basic example; update every 1 ms</h2>
<p>click <code>start</code> to start a stopwatch</p>
<pre>
var elems = document.getElementsByClassName("basic");
for (var i=0, len=elems.length; i<len; i++) {
new Stopwatch(elems[i]);
}
</pre>
<div class="basic stopwatch"></div>
<div class="basic stopwatch"></div>
<hr>
<h2>Programmatic example</h2>
<p><strong>Note:</strong> despite the varying <code>delay</code> settings, each stopwatch displays the correct time (in seconds)</p>
<pre>
var a = document.getElementById("a-timer");
aTimer = new Stopwatch(a);
aTimer.start();
</pre>
<div class="stopwatch" id="a-timer"></div>1 ms<br>
<pre>
var b = document.getElementById("b-timer");
bTimer = new Stopwatch(b, {delay: 100});
bTimer.start();
</pre>
<div class="stopwatch" id="b-timer"></div>100 ms<br>
<pre>
var c = document.getElementById("c-timer");
cTimer = new Stopwatch(c, {delay: 456});
cTimer.start();
</pre>
<div class="stopwatch" id="c-timer"></div>456 ms<br>
<pre>
var d = document.getElementById("d-timer");
dTimer = new Stopwatch(d, {delay: 1000});
dTimer.start();
</pre>
<div class="stopwatch" id="d-timer"></div>1000 ms<br>
Get some basic HTML wrappers for it
<!-- create 3 stopwatches -->
<div class="stopwatch"></div>
<div class="stopwatch"></div>
<div class="stopwatch"></div>
Usage is dead simple from there
var elems = document.getElementsByClassName("stopwatch");
for (var i=0, len=elems.length; i<len; i++) {
new Stopwatch(elems[i]);
}
As a bonus, you get a programmable API for the timers as well. Here's a usage example
var elem = document.getElementById("my-stopwatch");
var timer = new Stopwatch(elem, {delay: 10});
// start the timer
timer.start();
// stop the timer
timer.stop();
// reset the timer
timer.reset();
jQuery plugin
As for the jQuery portion, once you have nice code composition as above, writing a jQuery plugin is easy mode
(function($) {
var Stopwatch = function(elem, options) {
// code from above...
};
$.fn.stopwatch = function(options) {
return this.each(function(idx, elem) {
new Stopwatch(elem, options);
});
};
})(jQuery);
jQuery plugin usage:
// all elements with class .stopwatch; default delay (1 ms)
$(".stopwatch").stopwatch();
// a specific element with id #my-stopwatch; custom delay (10 ms)
$("#my-stopwatch").stopwatch({delay: 10});
jsbin.com demo

Two native solutions
performance.now --> Call to ... took 6.414999981643632 milliseconds.
console.time --> Call to ... took 5.815 milliseconds
The difference between both is precision.
For usage and explanation read on.
Performance.now (For microsecond precision use)
var t0 = performance.now();
doSomething();
var t1 = performance.now();
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.");
function doSomething(){
for(i=0;i<1000000;i++){var x = i*i;}
}
performance.now
Unlike other timing data available to JavaScript (for example
Date.now), the timestamps returned by Performance.now() are not
limited to one-millisecond resolution. Instead, they represent times
as floating-point numbers with up to microsecond precision.
Also unlike Date.now(), the values returned by Performance.now()
always increase at a constant rate, independent of the system clock
(which might be adjusted manually or skewed by software like NTP).
Otherwise, performance.timing.navigationStart + performance.now() will
be approximately equal to Date.now().
console.time
Example: (timeEnd wrapped in setTimeout for simulation)
console.time('Search page');
doSomething();
console.timeEnd('Search page');
function doSomething(){
for(i=0;i<1000000;i++){var x = i*i;}
}
You can change the Timer-Name for different operations.

A simple and easy clock for you and don't forget me ;)
var x;
var startstop = 0;
function startStop() { /* Toggle StartStop */
startstop = startstop + 1;
if (startstop === 1) {
start();
document.getElementById("start").innerHTML = "Stop";
} else if (startstop === 2) {
document.getElementById("start").innerHTML = "Start";
startstop = 0;
stop();
}
}
function start() {
x = setInterval(timer, 10);
} /* Start */
function stop() {
clearInterval(x);
} /* Stop */
var milisec = 0;
var sec = 0; /* holds incrementing value */
var min = 0;
var hour = 0;
/* Contains and outputs returned value of function checkTime */
var miliSecOut = 0;
var secOut = 0;
var minOut = 0;
var hourOut = 0;
/* Output variable End */
function timer() {
/* Main Timer */
miliSecOut = checkTime(milisec);
secOut = checkTime(sec);
minOut = checkTime(min);
hourOut = checkTime(hour);
milisec = ++milisec;
if (milisec === 100) {
milisec = 0;
sec = ++sec;
}
if (sec == 60) {
min = ++min;
sec = 0;
}
if (min == 60) {
min = 0;
hour = ++hour;
}
document.getElementById("milisec").innerHTML = miliSecOut;
document.getElementById("sec").innerHTML = secOut;
document.getElementById("min").innerHTML = minOut;
document.getElementById("hour").innerHTML = hourOut;
}
/* Adds 0 when value is <10 */
function checkTime(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
function reset() {
/*Reset*/
milisec = 0;
sec = 0;
min = 0
hour = 0;
document.getElementById("milisec").innerHTML = "00";
document.getElementById("sec").innerHTML = "00";
document.getElementById("min").innerHTML = "00";
document.getElementById("hour").innerHTML = "00";
}
<h1>
<span id="hour">00</span> :
<span id="min">00</span> :
<span id="sec">00</span> :
<span id="milisec">00</span>
</h1>
<button onclick="startStop()" id="start">Start</button>
<button onclick="reset()">Reset</button>

This is my simple take on this question, I hope it helps someone out oneday, somewhere...
let output = document.getElementById('stopwatch');
let ms = 0;
let sec = 0;
let min = 0;
function timer() {
ms++;
if(ms >= 100){
sec++
ms = 0
}
if(sec === 60){
min++
sec = 0
}
if(min === 60){
ms, sec, min = 0;
}
//Doing some string interpolation
let milli = ms < 10 ? `0`+ ms : ms;
let seconds = sec < 10 ? `0`+ sec : sec;
let minute = min < 10 ? `0` + min : min;
let timer= `${minute}:${seconds}:${milli}`;
output.innerHTML =timer;
};
//Start timer
function start(){
time = setInterval(timer,10);
}
//stop timer
function stop(){
clearInterval(time)
}
//reset timer
function reset(){
ms = 0;
sec = 0;
min = 0;
output.innerHTML = `00:00:00`
}
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
const resetBtn = document.getElementById('resetBtn');
startBtn.addEventListener('click',start,false);
stopBtn.addEventListener('click',stop,false);
resetBtn.addEventListener('click',reset,false);
<p class="stopwatch" id="stopwatch">
<!-- stopwatch goes here -->
</p>
<button class="btn-start" id="startBtn">Start</button>
<button class="btn-stop" id="stopBtn">Stop</button>
<button class="btn-reset" id="resetBtn">Reset</button>

Solution by Mosh Hamedani
Creating a StopWatch function constructor.
Define 4 local variables
startTime
endTime
isRunning
duration set to 0
Next create 3 methods
start
stop
reset
start method
check if isRunning is true if so throw an error that start cannot be called twice.
set isRunning to true
assign the current Date object to startTime.
stop method
check if isRunning is false if so throw an error that stop cannot be called twice.
set isRunning to false
assign the current Date object to endTime.
calculate the seconds by endTime and startTime Date object
increment duration with seconds
reset method:
reset all the local variables.
Read-only property
if you want to access the duration local variable you need to define a property using Object.defineProperty.
It's useful when you want to create a read-only property.
Object.defineProperty takes 3 parameters
the object which to define a property (in this case the current object (this))
the name of the property
the value of the key property.
We want to create a Read-only property so we pass an object as a value.
The object contain a get method that return the duration local variable.
in this way we cannot change the property only get it.
The trick is to use Date() object to calculate the time.
Reference the code below
function StopWatch() {
let startTime,
endTime,
isRunning,
duration = 0;
this.start = function () {
if (isRunning) throw new Error("StopWatch has already been started.");
isRunning = true;
startTime = new Date();
};
this.stop = function () {
if (!isRunning) throw new Error("StopWatch has already been stop.");
isRunning = false;
endTime = new Date();
const seconds = (endTime.getTime() - startTime.getTime()) / 1000;
duration += seconds;
};
this.reset = function () {
duration = 0;
startTime = null;
endTime = null;
isRunning = false;
};
Object.defineProperty(this, "duration", {
get: function () {
return duration;
},
});
}
const sw = new StopWatch();

function StopWatch() {
let startTime, endTime, running, duration = 0
this.start = () => {
if (running) console.log('its already running')
else {
running = true
startTime = Date.now()
}
}
this.stop = () => {
if (!running) console.log('its not running!')
else {
running = false
endTime = Date.now()
const seconds = (endTime - startTime) / 1000
duration += seconds
}
}
this.restart = () => {
startTime = endTime = null
running = false
duration = 0
}
Object.defineProperty(this, 'duration', {
get: () => duration.toFixed(2)
})
}
const sw = new StopWatch()
sw.start()
sw.stop()
sw.duration

well after a few modification of the code provided by mace,i ended up building a stopwatch.
https://codepen.io/truestbyheart/pen/EGELmv
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Stopwatch</title>
<style>
#center {
margin: 30% 30%;
font-family: tahoma;
}
.stopwatch {
border:1px solid #000;
background-color: #eee;
text-align: center;
width:656px;
height: 230px;
overflow: hidden;
}
.stopwatch span{
display: block;
font-size: 100px;
}
.stopwatch p{
display: inline-block;
font-size: 40px;
}
.stopwatch a{
font-size:45px;
}
a:link,
a:visited{
color :#000;
text-decoration: none;
padding: 12px 14px;
border: 1px solid #000;
}
</style>
</head>
<body>
<div id="center">
<div class="timer stopwatch"></div>
</div>
<script>
const Stopwatch = function(elem, options) {
let timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval,
hrs = 0,
min = 0;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return document.createElement("span");
}
function createButton(action, handler) {
if (action !== "reset") {
let a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
} else if (action === "reset") {
let a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
clean();
event.preventDefault();
});
return a;
}
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render(0);
}
function clean() {
min = 0;
hrs = 0;
clock = 0;
render(0);
}
function update() {
clock += delta();
render();
}
function render() {
if (Math.floor(clock / 1000) === 60) {
min++;
reset();
if (min === 60) {
min = 0;
hrs++;
}
}
timer.innerHTML =
hrs + "<p>hrs</p>" + min + "<p>min</p>" + Math.floor(clock / 1000)+ "<p>sec</p>";
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
};
// Initiating the Stopwatch
var elems = document.getElementsByClassName("timer");
for (var i = 0, len = elems.length; i < len; i++) {
new Stopwatch(elems[i]);
}
</script>
</body>
</html>

Related

How can I fix the stop-start process within this Javascript stopwatch-clock?

I have a JavaScript stopwatch here, I require the start-stop button to keep the same time when continuing.
Currently, if I stop and continue the clock diff is something ridiculous such as '-19330839:-3:-53'
Can anyone explain how this is fixed?
I have various method stopwatches made; however I would rather use real date time instead of a counter, this is because (I have tested after being made aware of this) that counters are very inaccurate over a period of time.
Any help is much appreciated.
html:
Please ignore the reset button for now. I will configure this later.
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst1" id='btnRst1' value="Reset" onclick="resetclock();"/>
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>
JS:
const outputElement = document.getElementById("outputt");
var startTime = 0;
var running = false;
var splitcounter = 0;
function startstop() {
if (running == false) {
running = true;
startTime = new Date(sessionStorage.getItem("time"))
if (isNaN(startTime)) startTime = Date.now();
startstopbutton.value = 'Stop';
document.getElementById("outputt").style.backgroundColor = "#2DB37B";
updateTimer();
} else {
running = false;
logTime();
startstopbutton.value = 'Start';
document.getElementById("outputt").style.backgroundColor = "#B3321B";
}
}
function updateTimer() {
if (running == true) {
let differenceInMillis = Date.now() - startTime;
sessionStorage.setItem("time", differenceInMillis)
let {
hours,
minutes,
seconds
} = calculateTime(differenceInMillis);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
requestAnimationFrame(updateTimer);
}
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
I just need the timer to continue on from where it was stopped at.
Issue with your code:
You start with initial value for sessionStorage as Date.now but then save difference on update.
You interact a lot with session storage. Any communication with external API is expensive. Instead use local variables and find an event to initialise values.
Time difference logic is a bit off.
Date.now - startTime does not considers the difference between stop action and start action.
You can use this logic: If startTime is defined, calculate difference and add it to start time. If not, initialise it to Date.now()
Suggestions:
Instead of adding styles, use classes. That will help you in reset functionality
Define small features and based on it, define small functions. That would make reusability easy
Try to make functions independent by passing arguments and only rely on them. That way you'll reduce side-effect
Note: as SO does not allow access to Session Storage, I have removed all the related code.
const outputElement = document.getElementById("outputt");
var running = false;
var splitcounter = 0;
var lastTime = 0;
var startTime = 0;
function logTime() {
console.log('Time: ', lastTime)
}
function resetclock() {
running = false;
startTime = 0;
printTime(Date.now())
applyStyles(true)
}
function applyStyles(isReset) {
startstopbutton.value = running ? 'Stop' : 'Start';
document.getElementById("outputt").classList.remove('red', 'green')
if (!isReset) {
document.getElementById("outputt").classList.add(running ? 'red' : 'green')
}
}
function startstop() {
running = !running;
applyStyles();
if (running) {
if (startTime) {
const diff = Date.now() - lastTime;
startTime = startTime + diff;
} else {
startTime = Date.now()
}
updateTimer(startTime);
} else {
lastTime = Date.now()
logTime();
}
}
function printTime(startTime) {
let differenceInMillis = Date.now() - startTime;
let {
hours,
minutes,
seconds
} = calculateTime(differenceInMillis);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
}
function updateTimer(startTime) {
if (running == true) {
printTime(startTime)
requestAnimationFrame(() => updateTimer(startTime));
}
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
.red {
background-color: #2DB37B
}
.green {
background-color: #B3321B
}
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst1" id='btnRst1' value="Reset" onclick="resetclock();" />
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>
simple stopwatch example
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<input class="startstop" style="width: 120px;" type="button" value="Start" onclick="startstop();">
<input class="reset" style="width: 120px;" type="button" value="Reset" onclick="reset();"/>
<div class="timerClock" value="00:00:00">00:00:00</div>
<script type="text/javascript">
var second = 0
var minute = 0
var hour = 0
var interval
var status = false
var element = document.querySelector('.startstop')
var clock = document.querySelector('.timerClock')
var string = ''
function startstop()
{
if(status == 'false')
{
element.value = 'Stop'
clock.style.backgroundColor = "#2DB37B";
status = true
interval = setInterval(function()
{
string = ''
second += 1
if(second >= 60)
{
minute += 1
second = 0
}
if(minute >= 60)
{
hour += 1
minute = 0
}
if(hour < 10)
string += `0${hour}:`
else
string += `${hour}:`
if(minute < 10)
string += `0${minute}:`
else
string += `${minute}:`
if(second < 10)
string += `0${second}`
else
string += `${second}`
clock.innerHTML = string
},1000)
}
else
{
clock.style.backgroundColor = "#B3321B";
element.value = 'Start'
status = false
clearInterval(interval)
}
}
function reset()
{
second = 0
minute = 0
hour = 0
status = false
element.value = 'Start'
clearInterval(interval)
clock.innerHTML = `00:00:00`
clock.style.backgroundColor = "transparent";
}
</script>
</body>
</html>
One thing to know about requestAnimationFrame is that it returns an integer that is a reference to the next animation. You can use this to cancel the next waiting animation with cancelAnimationFrame.
As mentioned by #Rajesh, you shouldn't store the time each update, as it will stop the current process for a (very) short while. Better in that case to fire an event, preferably each second, that will wait until it can run. I haven't updated the code to take that into account, I only commented it away for now.
It's also better to use classes than updating element styles. I wrote sloppy code that overwrites all classes on the #outputt element (it's spelled "output"). That's bad programming, because it makes it impossible to add other classes, but it serves the purpose for now. #Rajesh code is better written for this purpose.
I added two variables - diffTime and animationId. The first one corrects startTime if the user pauses. The second one keeps track if there is an ongoing timer animation.
I refactored your style updates into a method of its own. You should check it out, because it defines standard values and then changes them with an if statement. It's less code than having to type document.getElementById("outputt").style... on different rows.
I also added a resetclock method.
const outputElement = document.getElementById("outputt");
var startTime = 0;
var diffTime = 0;
var animationId = 0;
function startstop() {
const PAUSED = 0;
let paused = animationId == PAUSED;
//diffTime = new Date(sessionStorage.getItem("time")) || 0;
startTime = Date.now() - diffTime;
if (paused) {
updateTimer();
} else {
cancelAnimationFrame(animationId);
animationId = PAUSED;
}
updateTimerClass(paused);
}
function updateTimerClass(paused) {
var outputClass = 'red';
var buttonText = 'Start';
if (paused) {
outputClass = 'green';
buttonText = 'Stop';
}
startstopbutton.value = buttonText;
outputElement.classList = outputClass;
}
function updateTimer() {
let differenceInMillis = Date.now() - startTime;
//sessionStorage.setItem("time", differenceInMillis)
let {
hours,
minutes,
seconds
} = calculateTime(differenceInMillis);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
diffTime = differenceInMillis;
animationId = requestAnimationFrame(updateTimer);
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
function resetclock() {
let paused = animationId == 0;
startTime = Date.now();
diffTime = 0;
if (paused) {
const REMOVE_ALL_CLASSES = '';
outputElement.className = REMOVE_ALL_CLASSES;
outputElement.innerText = '00:00:00';
}
}
#outputt.green {
background-color: #2DB37B;
}
#outputt.red {
background-color: #B3321B;
}
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst1" id='btnRst1' value="Reset" onclick="resetclock();"/>
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>
class Stopwatch {
constructor(display, results) {
this.running = false;
this.display = display;
this.results = results;
this.laps = [];
this.reset();
this.print(this.times);
}
reset() {
this.times = [ 0, 0, 0 ];
}
click(){
var x=document.getElementById('ctrl');
if(x.value=="start"){
this.start();
x.value="stop";
document.getElementById("outputt").style.backgroundColor = "#2DB37B";
}
else{
x.value="start";
this.stop();
document.getElementById("outputt").style.backgroundColor = "#B3321B";
}
}
start() {
if (!this.time) this.time = performance.now();
if (!this.running) {
this.running = true;
requestAnimationFrame(this.step.bind(this));
}
}
stop() {
this.running = false;
this.time = null;
}
resets() {
document.getElementById("outputt").style.backgroundColor = "#2DB37B";
if (!this.time) this.time = performance.now();
if (!this.running) {
this.running = true;
requestAnimationFrame(this.step.bind(this));
}
this.reset();
}
step(timestamp) {
if (!this.running) return;
this.calculate(timestamp);
this.time = timestamp;
this.print();
requestAnimationFrame(this.step.bind(this));
}
calculate(timestamp) {
var diff = timestamp - this.time;
// Hundredths of a second are 100 ms
this.times[2] += diff / 1000;
// Seconds are 100 hundredths of a second
if (this.times[2] >= 100) {
this.times[1] += 1;
this.times[2] -= 100;
}
// Minutes are 60 seconds
if (this.times[1] >= 60) {
this.times[0] += 1;
this.times[1] -= 60;
}
}
print() {
this.display.innerText = this.format(this.times);
}
format(times) {
return `\
${pad0(times[0], 2)}:\
${pad0(times[1], 2)}:\
${pad0(Math.floor(times[2]), 2)}`;
}
}
function pad0(value, count) {
var result = value.toString();
for (; result.length < count; --count)
result = '0' + result;
return result;
}
function clearChildren(node) {
while (node.lastChild)
node.removeChild(node.lastChild);
}
let stopwatch = new Stopwatch(
document.querySelector('.stopwatch'),
document.querySelector('.results'));
<input type="button" id="ctrl" value="start" onClick="stopwatch.click();">
<input type="button" value="Reset" onClick="stopwatch.resets();">
<div id="outputt" class="stopwatch"></div>

HTML: How to get multiple timers to combine

I am building a timer based on user inputs. Below is how to code should work:
User inputs:
Time on: 30s
Time off: 10s
Number of sets: 4
Number of exercises per set: 5
Rest in between sets: 30s
With the above user inputs the timer will do this:
Hopefully that makes sense on what It is supposed to do. I am currently trying to implement the rest in between sets. Does anyone know how I could make that happen with how my code currently is? Also totalTime already includes the amount of time the rest in between sets would add on if that helps.
var numsets = document.getElementById("userInput1");
var numex = document.getElementById("userInput2");
var numwork = document.getElementById("userInput3");
var numrest = document.getElementById("userInput4");
var numrestafterset = document.getElementById("userInput5");
var sets;
var OGtimeon;
var OGtimeoff;
var totalTime;
var timeRemaining;
var hasBeenStarted = false; // Boolean value to test what time to use
var isTimeON = true;
var timeon;
var timeoff;
var timeonRemaining;
var timeoffRemaining;
var setsRemaining;
var OGsets;
var Prepare;
var OGExPS;
var OGTOASets;
var ExercisePS;
var RestAfterS;
var Intervals
var j = 0;
var ExercisesRemaining;
var RestRemaining;
// function sleep(milliseconds) { //function I found online to create a sleep function
// const date = Date.now();
// let currentDate = null;
// do {
// currentDate = Date.now();
// } while (currentDate - date < milliseconds);
// }
// function updateRest() {
// if (RestAfterS > 0) {
// interval3 = setInterval(RestCount, 1000);
// }
// else {
// startTime();
// }
// function RestCount() {
// while (RestAfterS != 0) {
// RestAfterS--;
// }
// j = 0;
// }
function updatePrep() {
if (hasBeenStarted == false) {
Prepare = 5;
interval2 = setInterval(PrepCount, 1000);
}
else {
startTime();
}
}
function PrepCount() {
let seconds = parseFloat(Prepare) % 60;
if (Prepare == 0) {
clearInterval(interval2);
startTime();
}
else {
PWR.innerHTML = "Get Ready!";
textarea.innerHTML = Prepare;
console.log(Prepare);
Prepare--;
}
}
function startTime() {
// Set values in code
OGsets = numsets.value;
OGtimeon = numwork.value;
OGtimeoff = numrest.value;
OGTOASets = numrestafterset.value;
OGExPS = numex.value;
timeon = (hasBeenStarted)? timeonRemaining : OGtimeon;
timeoff = (hasBeenStarted)? timeoffRemaining : OGtimeoff;
sets = (hasBeenStarted)? setsRemaining : OGsets;
ExercisePS = (hasBeenStarted)? ExercisesRemaining : OGExPS;
RestAfterS = (hasBeenStarted)? RestRemaining : OGTOASets;
// How much time on timer
// Var = (expression)? true : false this is basically an if statement
totalTime = (hasBeenStarted)? timeRemaining : ((parseFloat(OGtimeon)*parseFloat(sets)*parseFloat(ExercisePS))+(parseFloat(OGTOASets)*(parseFloat(sets)-1))+(parseFloat(OGtimeoff)*(parseFloat(sets)*(parseFloat(ExercisePS)-1))));
Intervals = ((parseFloat(sets)*parseFloat(ExercisePS))+((parseFloat(sets)-1))+((parseFloat(sets)*(parseFloat(ExercisePS)-1))));
hasBeenStarted = true;
// Start timer
interval = setInterval(updateCountdown, 1000);
}
function updateCountdown() {
IntervalsLeft.innerHTML = Intervals;
setsLeft.innerHTML = sets;
var minutes= Math.floor (parseFloat(totalTime) / 60);
var seconds = parseFloat(totalTime) % 60;
if (seconds < 10) {
textareaRemaining.innerHTML = minutes + ":0" + seconds;
} else {
textareaRemaining.innerHTML = minutes + ":" + seconds;
}
// Update TimeON / Time OFF
if(isTimeON){
PWR.innerHTML = "Work!";
textarea.innerHTML = timeon;
timeon--;
if(timeon == 0){
isTimeON = false;
timeon = OGtimeon;
Intervals--;
IntervalsLeft.innerHTML = Intervals;
}
}
//BELOW IS THE AREA I AM STUCK ON
else{
textarea.innerHTML = timeoff;
timeoff--;
PWR.innerHTML = "Rest!";
if(timeoff == 0){
isTimeON = true;
timeoff = OGtimeoff;
j++;
Intervals--;
IntervalsLeft.innerHTML = Intervals;
if (j == OGExPS) {
sets--;
//updateRest();
j = 0;
}
}
}
if( totalTime == 0 ){
clearTimeout(interval);
hasBeenStarted = false;
console.log(sets);
sets--;
setsLeft.innerHTML = sets;
PWR.innerHTML = "OMG YOU'RE DONE";
}
totalTime--;
}
function updateRest() {
if (RestAfterS > 0) {
interval3 = setInterval(RestCount, 5000);
}
else {
startTime();
}
}
function RestCount() {
while (RestAfterS != 0) {
RestAfterS--;
PWR.innerHTML = "Set Rest!";
textarea.innerHTML = RestAfterS;
}
j = 0;
clearInterval(interval3);
}
function stop(){
timeRemaining = totalTime;
timeonRemaining = timeon;
timeoffRemaining = timeoff;
RestRemaining = RestAfterS;
ExercisesRemaining = OGExPS;
setsRemaining = sets;
clearTimeout(interval);
// document.getElementById("Counter").innerHTML = j;
}
p {
display: inline-flex;
align-items: center;
}
label {
float: left;
display: block;
}
#userInput1 {
display: flex;
margin-bottom: 10px;
}
#userInput2 {
display: flex;
margin-bottom: 10px;
}
#userInput3 {
display: flex;
margin-bottom: 10px;
}
#userInput4 {
display: flex;
margin-bottom: 10px;
}
#userInput5 {
display: flex;
margin-bottom: 10px;
}
#Prepare {
display: flex;
margin-bottom: 10px;
}
#sets {
display: flex;
margin-bottom: 10px;
}
#timeon {
display: flex;
margin-bottom: 10px;
}
#timeoff {
display: flex;
margin-bottom: 10px;
}
#TotalTime {
display: flex;
margin-bottom: 10px;
}
#Counter {
display: flex;
margin-bottom: 10px;
}
input {
height: 20px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-compatible" content="ie=edge" />
<title>Document</title>
<link rel="stylesheet" href="Countdown From Scratch.css" />
</head>
<script src="Countdown From Scratch.js" defer></script>
<body>
<label>Number of Sets </label>
<input id="userInput1" type="numsets" value = "0"/>
<label>Number of Exercises per Set </label>
<input id="userInput2" type="numex" value = "0"/>
<label>Time to Work </label>
<input id="userInput3" type="numwork" value = "0"/>
<label>Time to Rest </label>
<input id="userInput4" type="numrest" value = "0"/>
<label>Time Inbetween Sets </label>
<input id="userInput5" type="numrestafterset" value = "0"/>
<p id="Prepare"></p>
<div id="sets"> </div>
<div id="timeon"> </div>
<div id="timeoff"> </div>
<div id="TotalTime"> </div>
<textarea id="textarea" placeholder="00:00"></textarea>
<textarea id="PWR" placeholder="Hello!"></textarea>
<textarea id="textareaRemaining" placeholder="00:00"></textarea>
<textarea id="setsLeft" placeholder="00"></textarea>
<textarea id="IntervalsLeft" placeholder="00"></textarea>
<button onclick="updatePrep()">Start time</button>
<button onclick="stop()">Stop time</button>
</body>
</html>
I think I have a rough idea of what you are trying to accomplish here, but please let me know if I have misinterpreted anything.
Suppose you want to execute a sequence of effects with some duration in between them. To keep the example small, we'll use console.log as a stand-in for any effect you'd want to execute (for instance, setting the innerHTML of a DOM element).
As a first example, here we wait for 1 second, display "Hello", then wait for 1.5 seconds and display "There":
setTimeout(() => {
console.log('Hello');
setTimeout(() => {
console.log('There');
}, 1500);
}, 1000);
We can clarify this by describing the common parts as a function:
function logAfter(message, delay, callback) {
setTimeout(() => {
console.log(message);
if (callback) callback();
}, delay);
}
Then our example can be written as:
logAfter('Hello', 1000, () => {
logAfter('There', 1500);
});
As another example that is perhaps more relevant to your project, here is how we can create a "loop" that performs an effect multiple times:
function logNAfter(message, times, delay, callback) {
if (times === 0 && callback) {
callback();
}
else {
setTimeout(() => {
console.log(message);
logNAfter(message, times-1, delay, callback);
}, delay);
}
}
We could use this to display "Hi There!" 3 times, each separated by half a second, and then display "Goodbye!" once, 2 seconds later:
logNAfter('Hi There!', 3, 500, () => {
logAfter('Goodbye!', 2000);
});
In theory, you could create an arbitrarily-long sequence of appropriately spaced effects in this way. However, I should also mention that many would prefer to describe these effects as Promises instead:
function logAfter(message, delay) {
return new Promise(resolve => {
setTimeout(() => {
console.log(message);
resolve();
}, delay);
});
}
function logNAfter(message, times, delay) {
if (times === 0) {
return Promise.resolve();
} else {
return logAfter(message, delay)
.then(() => logNAfter(message, times-1, delay));
}
}
The original examples then become:
logAfter('Hello', 1000)
.then(() => logAfter('There', 1500));
logNAfter('Hi There!', 3, 500)
.then(() => logAfter('Goodbye!', 2000));
This is arguably only a slight improvement over the callback-style approach above, but it is much clearer if you are able to use async/await:
async function logAfter(message, delay) {
return new Promise(resolve => {
setTimeout(() => {
console.log(message);
resolve();
}, delay);
});
}
async function logNAfter(message, times, delay) {
for (let i = 0; i < times; ++i) {
await logAfter(message, delay);
}
}
async function demoSequence1() {
await logAfter('Hello', 1000);
await logAfter('There', 1500);
}
async function demoSequence2() {
await logNAfter('Hi There!', 3, 500);
await logAfter('Goodbye!', 2000);
}
Hope that helps!
I like Williams suggested of breaking it down into different timers that could be controlled easier by the user. However, using this approach, I personally ran into the issue of how to pause the timer.
I decided to take a slightly different approach. From the table given, there is a fairly clear pattern of how the timer needs to be set up.The timer generally alternates between "Workout time" and "Rest time" for the whole duration. Rest time can take 3 different values:
Rest time between exercises
Rest time between Sets
The workout is complete
Since all of these values are known when the the values are inputed, my approach is set up the course of the timer before starting the timer. This creates a little bit of setup time but I believe this is negotiable and will not impact performance heavily. To do this, I created a created an array before starting the timer. Each item in this array contains data including the total time remaining, the current set, the label (Working out or resting), and the label timer. After creating this array, we can just create a timer that is based off the number of items in the array. I hope that this little explanation helps you understand my solution a little bit better.
Index.html
<!DOCTYPE html>
<html>
<style>
td, th {
text-align: left;
padding: 8px;
}
</style>
<head>
<title>Timer</title>
</head>
<body>
<!-- Inputs -->
<h2>Inputs</h2>
<p>
<label for="sets-input">Number of Sets: </label>
<input type="number" id="sets-input" min="1" max="3600">
</p>
<p>
<label for="exercises-input">Number of Exersizes per Set: </label>
<input type="number" id="exercises-input" min="1" max="3600">
</p>
<p>
<label for="workout-input">Exersise Time: </label>
<input type="number" id="workout-input" min="1" max="3600">
</p>
<p>
<label for="exersiseRest-input">Rest between exersises: </label>
<input type="number" id="exersiseRest-input" min="1" max="3600">
</p>
<p>
<label for="setRest-input">Rest between Sets: </label>
<input type="number" id="setRest-input" min="1" max="3600">
</p>
<!-- Buttons -->
<p>
<button id="start-button">Start</button>
<button id="reset-button">Reset</button>
</p>
<!-- Timer Display -->
<h2>Outputs:</h2>
<table>
<tr>
<th>Total Time Remaining: </th>
<td id="timer-display">???</td>
</tr>
<tr>
<th>Set Number: </th>
<td id="set-display">???</td>
</tr>
<tr>
<th id="label-display">???</th>
<td id="labelTimer-display">???</td>
</tr>
</table>
<script src="tabada.js"></script>
</body>
</html>
Tabada.js
//-----------------------------------------------------------------------------------------------
// GLOBAL VARIABLES
//-----------------------------------------------------------------------------------------------
// HTML
var setsInput = document.getElementById("sets-input");
var exersisesInput = document.getElementById("exercises-input");
var workoutInput = document.getElementById("workout-input");
var exersiseRestInput = document.getElementById("exersiseRest-input");
var setRestInput = document.getElementById("setRest-input");
var timerDisplay = document.getElementById("timer-display");
var setDisplay = document.getElementById("set-display");
var labelDisplay = document.getElementById("label-display");
var labelTimerDisplay = document.getElementById("labelTimer-display");
var startButton = document.getElementById("start-button");
var resetButton = document.getElementById("reset-button");
// JavaScript
var sets = 2;
var exersises = 3;
var workout = 5;
var exersiseRest = 2;
var setRest = 3;
var totalTime = -1;
var myInterval = -1;
var tabadaArray = [];
var tabadaIndex = 0;
//-----------------------------------------------------------------------------------------------
// BUTTON FUNCTIONS
//-----------------------------------------------------------------------------------------------
// Start / Pause Button
startButton.addEventListener("click", function(event){
// Set up Tabada Timer
if (totalTime == -1){
collectInputs(); // Comment this line for testing without inputs
calculateTotalTime();
createTabadaArray();
}
// Start timer
if (myInterval == -1){
startButton.innerHTML = "Pause";
myInterval = setInterval(tabadaTimer, 1000);
}
// Pause timer
else{
startButton.innerHTML = "Start";
clearInterval(myInterval);
myInterval = -1
}
});
// Reset Button
resetButton.addEventListener("click", function(event){
// Stop Timer
clearInterval(myInterval);
// Refresh Timer Display
calculateTotalTime();
updateOutputs(totalTime, 1, 'Workout', workout);
totalTime=-1; // Alows user to change input values before clicking start button.
// Reset start / pause button
myInterval = -1;
startButton.innerHTML = "Start";
});
//-----------------------------------------------------------------------------------------------
// SETUP FOR TABADA TIMER
//-----------------------------------------------------------------------------------------------
function collectInputs(){
sets = parseFloat(setsInput.value);
exersises = parseFloat(exersisesInput.value);
workout = parseFloat(workoutInput.value);
exersiseRest = parseFloat(exersiseRestInput.value);
setRest = parseFloat(setRestInput.value);
}
function calculateTotalTime(){
let totalWorkoutTime = workout * exersises * sets;
let totalExersiseRest = exersiseRest * (exersises - 1) * sets;
let totalSetsRest = setRest * (sets - 1);
totalTime = totalWorkoutTime + totalExersiseRest + totalSetsRest;
}
function createTabadaArray() {
tabadaIndex = 0; // Global variable used for tabada timer
tabadaArray = [];
for( let set=1; set<=sets; set++ ){
for( let exersise=1; exersise<=exersises; exersise++){
// Workout
addTimeBlock(set, 'Workout', workout);
// Exersise Rest
if ( exersise < exersises){
addTimeBlock(set, 'Rest', exersiseRest);
}
// Set Rest
else if( set < sets){
addTimeBlock(set, 'Rest', setRest);
}
// Done
else{break;} // Very end exersize has no rest, so we must break the loop.
}
}
}
function addTimeBlock(set, label, labelTime) {
// Add a sub timer to the array (workout, exersice rest, or set rest)
for (let i=labelTime; i>0; i--) {
tabadaArray.push({
"totalTimeRemaining" : totalTime--,
"set" : set,
"label" : label,
"labelTimeRemaining" : i,
});
}
}
//-----------------------------------------------------------------------------------------------
// TABADA TIMER
//-----------------------------------------------------------------------------------------------
function tabadaTimer(){
// Still time left
if (tabadaIndex < tabadaArray.length){
let displayInfo = tabadaArray[tabadaIndex];
updateOutputs( displayInfo.totalTimeRemaining,
displayInfo.set,
displayInfo.label,
displayInfo.labelTimeRemaining );
tabadaIndex++;
}
// End of tabada timer
else{
clearInterval(myInterval); // stop timer
updateOutputs(0, 1, 'Rest', 0);
totalTime = -1
}
}
function updateOutputs(totalTimeRemaining, setNumber, label, labelTimeRemaining){
timerDisplay.innerHTML = convertSeconds(totalTimeRemaining);
setDisplay.innerHTML = setNumber;
labelDisplay.innerHTML = label;
labelTimerDisplay.innerHTML = convertSeconds(labelTimeRemaining);
}
function convertSeconds(s){
// Seconds -> mm:ss format
// Calculate
let minutes = Math.floor(s/60);
let seconds = s%60;
// Format
let formattedminutes = ("0" + minutes).slice(-2);
let formattedseconds = ("0" + seconds).slice(-2);
return formattedminutes + ':' + formattedseconds;
}

Increment issues

I have a timer going that adds 1 every second to the variable MenuTimer.
What I want is when the next button is pressed TillOpen The MenuTimer will stop having 1 added to it after that and a new variable to have 1 added instead PackTime
window.onload = function () {
var StopwatchSeconds= 00;
var StopwatchMinutes = 00;
var ShowSeconds = document.getElementById("seconds");
var ShowMinutes = document.getElementById("minutes");
var StartButton = document.getElementById("ButtonStart");
var Interval;
var menuTime;
var serviceTime;
var orders;
var menuAvg;
var serviceAvg;
StartButton.onclick= function(){
clearInterval(Interval);
Interval = setInterval(startTimer, 1000);
}
function startTimer () {
StopwatchSeconds++;
if(StopwatchSeconds > 59) {
ShowSeconds.innerHTML = "0" + StopwatchSeconds;
StopwatchSeconds = 0;
ShowMinutes.innerHTML = StopwatchMinutes;
StopwatchMinutes++;
}
if(StopwatchSeconds < 59) {
ShowSeconds.innerHTML = StopwatchSeconds;
}
}
}
Here's all of it. It half works but hopefully you get a better Idea of what i'm trying to go for.
var Interval;
var PackInterval;
var StopwatchSeconds= 00;
var StopwatchMinutes = 00;
var ShowSeconds = document.getElementById("seconds");
var ShowMinutes = document.getElementById("minutes");
var StartButton = document.getElementById("ButtonStart");
var TillOpenButton = document.getElementById("TillOpen");
var FinishButton = document.getElementById("Finish");
var ShowMenuTime = document.getElementById("MenuTime");
var ShowPackTime = document.getElementById("PackTime");
var ShowPackAvgSeconds = document.getElementById("PackerSeconds");
var ShowPackAvgMinutes = document.getElementById("PackerMinutes");
var ShowMenuAvgSeconds = document.getElementById("MenuMinutes");
var ShowMenuAvgMinutes = document.getElementById("MenuSeconds");
var DivisionSeconds = 60;
var TotalTime = 0;
var MenuTime = 0;
var PackTime = 0;
var AllMenuTimes = 0;
var AllPackTimes = 0;
var TotalMenuOrders = 0;
var TotalPackOrders = 0;
var MenuOrdersTotalSeconds = 0;
var PackOrdersTotalSeconds = 0;
var MenuAvgMinutes = 0;
var MenuAvgSeconds = 0;
var PackAvgSeconds = 0;
var PackAvgMinutes = 0;
StartButton.onclick = function(){
TotalMenuOrders + 1;
MenuTime = 0;
ShowMenuTime.innerHTML = MenuTime;
clearInterval(Interval);
Interval = setInterval(startTimer, 1000);
window.alert ("I work");
}
//This starts the timer. Inverval is a variable that holds the timer number.
function startTimer () {
StopwatchSeconds++;
TotalTime++;
MenuTime++;
AllMenuTime++;
if(StopwatchSeconds > 59) {
ShowSeconds.innerHTML = "0" + StopwatchSeconds;
StopwatchSeconds = 0;
StopwatchMinutes++;
ShowMinutes.innerHTML = StopwatchMinutes; // Makes this a string in html
}
if(StopwatchSeconds < 59) {
ShowSeconds.innerHTML = StopwatchSeconds;
}
}
// When the start button is pressed this function starts. it adds 1 to
Stopwatch, total and Menu every 1000 increments that Interval hits.
// This also says if StopwatchSeconds goes above 59 itll reset to 0 and if
its below itll keep counting.
TillOpenButton.onclick = function () {
PackTime = 0;
ShowPackTime.innerHTML = PackTime;
ShowMenuTime.innerHTML = MenuTime;
PackInterval = setInterval(startPackerTimer, 1000);
Interval+PackInterval;
clearInterval(Interval);
/* if (TotalMenuOrders < 1) {
AllMenuTimes / TotalMenuOrders = MenuOrdersTotalSeconds;
MenuOrderTotalSeconds % 60 = MenuAvgSeconds;
MenuAvgMinutes = Math.floor(MenuOrderTotalSeconds/60);
ShowMenuAvgMinutes.innerHTML = MenuAvgMinutes;
ShowMenuAvgSeconds.innerHTML = MenuAvgSeconds;
}
*/
}
// When this button is pressed it stops the first timer and the menu timer.
It then starts a new timer and function which add to the variable that will
show the total time.
// It does clear the variable Interval though
FinishButton.onclick = function (){
clearInterval(Interval);
ShowPackTime.innerHTML = PackTime;
clearInterval(PackInterval);
StopwatchSeconds = 0;
StopwatchMinutes = 0;
ShowSeconds.innerHTMl = 0 + StopwatchSeconds;
ShowMinutes.innerHTML = 0 + StopwatchMinutes;
AllPackTimes += PackTime;
TotalPackOrders++;
/*AllPackTimes/TotalPackOrders = PackOrderTotalSeconds;
PackOrderTotalSeconds % DivisionSeconds = PackAvgSeconds;
PackAvgMinutes = Math.floor(PackOrderTotalSeconds/60);
ShowPackAvgMinutes.innerHTML = PackAvgMinutes;
ShowPackAvgSeconds.innerHTML = PackAvgSeconds;*/
}
// When the Finish Button is pressed it clears everything. Resets
everything. except Menu Time, Total Time and PackTime. I need 3 new
variables to hold these to get the average.
function startPackerTimer () {
StopwatchSeconds++;
TotalTime++;
PackTime++;
if(StopwatchSeconds > 59) {
ShowSeconds.innerHTML = "0" + StopwatchSeconds;
StopwatchSeconds = 0;
StopwatchMinutes++;
ShowMinutes.innerHTML = StopwatchMinutes;
}
if(StopwatchSeconds < 59) {
ShowSeconds.innerHTML = StopwatchSeconds;
}
// Same deal but with the Till open button. Still adds onto
STopwatchSeconds so the variable doesn't change.
}
New solution, wich allows to create different timers and keep track of them:
//a method to setup a new timer
function Timer(Name){
this.timeElement=document.createElement("div");
(this.stopButton=document.createElement("button")).innerHTML="STOP";
(this.startButton=document.createElement("button")).innerHTML="START";
(this.Name=document.createElement("h1")).innerHTML=Name;
[this.Name,this.timeElement,this.startButton,this.stopButton].forEach(el=>document.body.appendChild(el));
this.stopButton.addEventListener("click",this.stop.bind(this));
this.startButton.addEventListener("click",this.start.bind(this));
this.seconds=0;
this.minutes=0;
}
Timer.prototype={
update:function() {
this.seconds++;
if(this.seconds > 59) {
this.seconds=0;
this.minutes++;
}
var secTemp="00"+this.seconds, minTemp="00"+this.minutes;
this.timeElement.innerHTML=minTemp.slice(minTemp.length-2)+":"+secTemp.slice(secTemp.length-2);
},
stop:function(){
if(this.interval) clearInterval(this.interval);
this.running=false;
if(this.onstop) this.onstop(this);
}
start:function(){
if(this.interval) clearInterval(this.interval);
this.interval = setInterval(this.update.bind(this), 1000);
this.running=true;
if(this.onstart) this.onstart(this);
}
};
This implements a Timer with OOP. So you can create multiple timers, and they wont influence each other.
You can create a timer like this:
var timer= new Timer("The Name");
You can also change events, set/read the times and check if running:
timer.start();//start the timer ( can also be done with the ui button)
timer.stop();
timer.onstart=()=>alert("Started!");
timer.onstop=()=>alert("Stopped!");
console.log(timer.running,timer.minutes,timer.seconds);
If you want to wait for multiple timers and to calculate the average if all of them stopped:
var timers=["Timer 1", "Timer 2"].map(name=>new Timer(name));//create two timers and store in array
timers.forEach(function(timer){
timer.running=true;
timer.onstop=function(){
if(timers.some(t=>t.running)) return;//if theres a running timer dont procceed
var seconds=timers.reduce((seconds,timer)=>seconds+=(timer.seconds+timer.minutes*60),0);
var average=seconds/timers.length;
alert("Average: "+average+"s");
};
});
http://jsbin.com/coduvohewu/edit?output
The old solution, adding a timer if the new button is pressed, and stops the old one then:
So you want to stop the current timer, and create a new one below that? Maybe you could refactor the code a bit, doing sth like this:
window.onload = function () {
var seconds= 0,minutes = 0;
var times=[];
var Interval;
var timeElement;
//a method to setup a new timer
function createTimer(dontsave){
if(times.length>3) return alert(times.map(el=>el.join(":")).join());
timeElement=document.createElement("div");
document.body.appendChild(timeElement);
if(!dontsave) times.push([minutes,seconds]);
}
createTimer(true);
//a method to let the timer run
function startTimer () {
seconds++;
if(seconds > 59) {
seconds=0;
minutes++;
}
var secTemp="00"+seconds,minTemp="00"+minutes;
timeElement.innerHTML=minTemp.slice(minTemp.length-2)+":"+secTemp.slice(secTemp.length-2);
}
//assign to buttons:
document.getElementById("ButtonStart").onclick= function(){
clearInterval(Interval);
Interval = setInterval(startTimer, 1000);
}
document.getElementById("ButtonNew").onclick=createTimer;
};
http://jsbin.com/mujisaweyo/edit?output
This simply creates a new div in the DOM if you press a button with the id ButtonNew . So the current time stays as a text in the old Element, and it keeps counting in the new one. Ive also added a zero filling...

Get length of touchevent

How can I get the time between touchstart and touchend in javasscript.
// define startTime variable
var startTime = 0;
function initi() {
console.log('init');
// Get a reference to our touch-sensitive element
var touchzone = document.getElementById("myCanvas");
// Add an event handler for the touchstart event
touchzone.addEventListener("mousedown", startTouch, false);
// You need mouseup to capture the stop event
touchzone.addEventListener("mouseup", stopTouch, false);
}
function startTouch(event) {
// You can access the event here too..
// But for demo I will only get the current Time
startTime = new Date().getTime();
}
function stopTouch(event) {
// Get a reference to our coordinates div
var can = document.getElementById("myCanvas");
// Write the coordinates of the touch to the div
if (event.pageX < x * 100 && event.pageY > y * 10) {
// Calculate the duration, only if needed
var duration = new Date().getTime() - startTime;
bally -= 0.001 * duration; // use duration
}
// I hope bally if defined in the outer scope somewhere ;)
console.log(event, x, bally);
draw();
}
The longer the time between touchstart and touchend the more the ball should move, but how can I get the time/length of the touchevent?
var startTime = 0;
function start() {
startTime = new Date().getTime();
}
function stop() {
var duration = (new Date().getTime() - startTime);
growBar(duration);
}
var clickEle = document.getElementsByTagName("button")[0];
var timerEle = document.getElementsByClassName("timer")[0];
var ms = document.getElementById('ms');
clickEle.onmousedown = start;
clickEle.onmouseup = stop;
function growBar(timerCount) {
ms.innerHTML = timerCount;
timerEle.setAttribute("style", "width:" + timerCount + "px;");
}
.bar {
height: 10px;
width: 100%;
background: black;
}
.timer {
width: 0;
height: 100%;
background: red;
}
<button id="button-id">Click This!</button>
<div><strong id="ms"></strong> ms</div>
<div class="bar">
<div class="timer"></div>
</div>
var clickEle = document.getElementsByTagName("button")[0];
var timerEle = document.getElementsByClassName("timer")[0];
var msEle = document.getElementById('ms');
var COUNTER_INCREMENT = 1; // In milliseconds
var timerCount = 0;
var timer = null;
clickEle.onmousedown = startTimer;
clickEle.onmouseup = stopTimer;
var ms = 0;
function startTimer() {
ms = new Date().getTime();
timer = setInterval(incrementTimer, COUNTER_INCREMENT);
}
function incrementTimer() {
timerCount += COUNTER_INCREMENT;
// For Demo purposes only
timerEle.innerHTML = timerCount;
}
function stopTimer() {
clearInterval(timer);
timerCount = 0;
msEle.innerHTML = new Date().getTime() - ms;
}
<button>Click This!</button>
<p>
<strong>How Long Was the Mouse Held Down for?</strong>
<span class="timer">0</span> milliseconds
</p>
<p><span id="ms"></span> real milliseconds</p>
You can start a Javascript Interval, of any number of milliseconds (depending on "smoothness" needed). See this below, mimicking what you can do, just using mousedown and mouseup events.
var clickEle = document.getElementsByTagName("button")[0];
var timerEle = document.getElementsByClassName("timer")[0];
var COUNTER_INCREMENT = 10; // In milliseconds
var timerCount = 0;
var timer = null;
clickEle.onmousedown = startTimer;
clickEle.onmouseup = stopTimer;
function startTimer() {
timer = setInterval(incrementTimer, COUNTER_INCREMENT);
}
function incrementTimer() {
timerCount += COUNTER_INCREMENT;
// For Demo purposes only
timerEle.innerHTML = timerCount;
}
function stopTimer() {
clearInterval(timer);
timerCount = 0;
}
<button>Click This!</button>
<p>
<strong>How Long Was the Mouse Held Down for?</strong>
<span class="timer">0</span> milliseconds
</p>
Or you can use requestAnimationFrame which is a little more optimal, but its availability depends on the browsers you're supporting.
https://css-tricks.com/using-requestanimationframe/
var clickEle = document.getElementsByTagName("button")[0];
var timerEle = document.getElementsByClassName("timer")[0];
var COUNTER_INCREMENT = 10; // In milliseconds
var startTime = 0;
var timerCount = 0;
var timer = null;
clickEle.onmousedown = startTimer;
clickEle.onmouseup = stopTimer;
function startTimer() {
timer = window.requestAnimationFrame(incrementTimer);
startTime = new Date();
}
function incrementTimer() {
var newTimerCount = new Date() - startTime;
// Update the DOM sparingly
if(newTimerCount - timerCount > COUNTER_INCREMENT) {
// For Demo purposes only
timerEle.innerHTML = timerCount = newTimerCount;
}
timer = window.requestAnimationFrame(incrementTimer)
}
function stopTimer() {
cancelAnimationFrame(timer);
timerCount = 0;
}
<button>Click This!</button>
<p>
<strong>How Long Was the Mouse Held Down for?</strong>
<span class="timer">0</span> milliseconds
</p>
You have to define the startTime variable somewhere, in the "outer scope", where both functions have access to. the when you call the first function it will just change its value, the second function can access the variable too ;)
var startTime = 0;
function one() {
startTime = new Date().getTime();
}
function two() {
var duration = new Date().getTime() - startime;
console.log(duration + 'ms between one() and two()');
}
var btn = document.getElementById('some-btn-id');
btn.onmousedown = one;
btn.onmouseup = two;

How do you call the start and stop function in a timer

Hi I've found a great timer here on SO for a while ago and I was wondering how to call the start and stop function, so when you call the start function the timer starts and when you call the stop function the timer stops. I have tried a lot of different solutions but I can't figure it out anyway here is the code:
<!DOCTYPE html>
<html>
<head>
<title>JS Bin</title>
<style>
.stopwatch {
display: inline-block;
background-color: white;
border: 1px solid #eee;
padding: 5px;
margin: 5px;
}
.stopwatch span {
font-weight: bold;
display: block;
}
.stopwatch a {
padding-right: 5px;
text-decoration: none;
}
</style>
</head>
<body>
<h2>Basic example; update every 1 ms</h2>
<p>click <code>start</code> to start a stopwatch</p>
<pre>
var elems = document.getElementsByClassName("basic");
for (var i=0, len=elems.length; i<len; i++) {
new Stopwatch(elems[i]);
}
</pre>
<div class="basic stopwatch"></div>
<hr>
<script>
var Stopwatch = function(elem, options) {
var timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return document.createElement("span");
}
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render(0);
}
function update() {
clock += delta();
render();
}
function render() {
timer.innerHTML = clock/1000;
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
// public API
this.start = start;
this.stop = stop;
this.reset = reset;
};
// basic examples
var elems = document.getElementsByClassName("basic");
for (var i=0, len=elems.length; i<len; i++) {
new Stopwatch(elems[i]);
}
</script>
</body>
</html>
If you look through the code, you can see that each button is created using the below function:
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
All this does is append a series of links to the DOM, each with a click event handler calling the relevant function (passed as the handler variable), stop, start or reset.
To call one of these directly, you can simply call the function- e.g. stop()
var Stopwatch = {
init: function(elem, options) {
var timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return document.createElement("span");
}
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render(0);
}
function update() {
clock += delta();
render();
}
function render() {
timer.innerHTML = clock / 1000;
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
// public API
this.start = start;
this.stop = stop;
this.reset = reset;
}
};
// basic examples
var elems = document.getElementsByClassName("basic");
for (var i = 0, len = elems.length; i < len; i++) {
Stopwatch.init(elems[i]);
}
.stopwatch {
display: inline-block;
background-color: white;
border: 1px solid #eee;
padding: 5px;
margin: 5px;
}
.stopwatch span {
font-weight: bold;
display: block;
}
.stopwatch a {
padding-right: 5px;
text-decoration: none;
}
<div class="basic stopwatch"></div>
<button onclick="Stopwatch.stop()">STOP!</button>

Categories