Your current implementation is actually wrong. Every time you call startTimer
, it installs startTimer
as a new window focus event handler, leading to multiple started intervals when you focus the window the second time; growing exponentially. The onfocus handler should only run the timerId = setInterval(…)
line - put that in a nested helper function to call only that.
This also makes it unnecessary to declare the variables globally.
function createTimer() {
let secondsPassed = 0;
let timerId;
function resume() {
if (timerId) return; // prevent multiple intervals running at the same time
timerId = setInterval(() => {
const seconds = twoDigits((Math.floor(secondsPassed )) % 60);
const minutes = twoDigits(Math.floor(secondsPassed / 60) % 60);
const hours = Math.floor(secondsPassed / 60 / 60);
$('#timer').text(`${hours}:${minutes}:${seconds}`);
secondsPassed++;
}, 1000);
}
function pause() {
clearInterval(timerId);
timerId = undefined;
}
$(window).blur(pause); // stop timer when user leaves tab
$(window).focus(resume); // continue timer when user comes back
resume(); // now start the timer
}
Now how to make that object-oriented? Just return an object from createTimer
. Put resume
and pause
as methods on that object. Maybe add some more methods for starting, stopping, resetting, whatever you need. Maybe use a property on the object instead of the secondsPassed
local variable. Or expose the local variable using a getter.
And to make it reusable, of course you can make createTimer
accept arguments, from the selector of the output element, to the output element itself, to a callback function that will be called with the current time on every tick.