Stopwatch +
With updated tooltip
by KooiInc MeHere
June 09, 2022
HTML
<div id="time" data-tt="Hours, Minutes, Seconds, MilliSeconds
Note: stopwatch runs from starttime, so resuming
(clicking start/continue after having paused) may show a gap">00:00:00.000</div>
<div id="ctrl">
<button id="start">START/CONTINUE</button>
<button id="stop">PAUSE</button>
<button id="reset">RESET</button>
</div>
CSS
body {
font: 12px normal verdana, arial;
}
#time {
width: 300px;
font-family: "Segoe UI",Roboto,Ubuntu,sans-serif;
margin: 25px auto;
border: 1px solid #000;
padding: 10px;
text-align: center;
font-size: 2em;
background: #efefef;
box-shadow: 1px 1px 5px #888;
border-radius: 5px;
}
[data-tt]:before {
content: attr(data-tt);
opacity: 0;
height: 1em;
position: absolute;
top: -1000em;
font-size: 0.6em;
padding: 6px;
max-width: 400px;
border: 1px solid #888;
background: white;
white-space: pre;
text-align: left;
border-radius: 5px;
box-shadow: 1px 1px 7px #888;
transition: opacity 0.2s ease-out;
}
[data-tt]:hover:before {
opacity: 1;
top: auto;
height: auto;
margin-top: 2em;
transition: opacity 0.4s 0.5s ease-in;
}
#ctrl {
text-align: center;
}
JavaScript
/*
Inital version @http://jsfiddle.net/U64Xr/5/ is not accurate
because the timer resolution of a browser isn't.
Thus, you'll need a more granular measure like performance.now().
*/
(_ => {
let starttime, interval;
const d2 = `2-digit`;
const timeOpts = { hour: d2, minute: d2, second: d2, fractionalSecondDigits: 3, hour12: false };
const timer = document.querySelector('#time');
const formatDate = (d = new Date()) => new Intl.DateTimeFormat('en', timeOpts).format(d);
const padLeft = (number = `0`, len = 2, chr = `0`) => `${number}`.padStart(len, chr);
const timeDiff = (milliseconds = 0) => {
milliseconds = Math.abs(milliseconds);
return `${
padLeft(Math.floor(((milliseconds / 1000) / 60) / 60) % 24)}:${
padLeft(Math.floor((milliseconds / 1000) / 60) % 60)}:${
padLeft(Math.floor(milliseconds / 1000) % 60)}.${
padLeft(Math.floor(milliseconds % 1000), 3)}`;
};
const updateTimer = (diff = 0) => timer.textContent = diff < 1 ? `00:00:00.000` : timeDiff(diff);
const addTT = txt => timer.setAttribute('data-tt', `${timer.getAttribute('data-tt')}\n${txt}`);
const run = _ => updateTimer(performance.now() - starttime);
const stop = _ => {
clearInterval(interval || 0);
addTT(starttime ? `Stopped: ${formatDate()}` : ``);
};
const reset = _ => {
stop();
starttime = undefined;
updateTimer();
};
const start = _ => {
clearInterval(interval || 0);
addTT(`${starttime ? `Resumed` : `Started`}: ${formatDate()}`);
starttime = starttime || performance.now();
interval = setInterval(run, 50);
};
const actions = { start, stop, reset, };
document.body.addEventListener( `click`, evt =>
evt.target.id in actions ? actions[evt.target.id]() : true );
})();