In this tutorial we are going to create a Pomodoro Clock to help you track the time you spend working on different tasks.
The Result
You can see a live demo of this project Here
The Task
- Difficulty: Beginner/Intermediate
- Tools: Text Editor of your choice
- Duration: 1-2 hours
- Github Repo: https://github.com/AlbertoMontalesi/InspiredWebDev-Tutorials/pomodoro-clock
These are the user stories for this Pomodoro Clock:
- [ ] User can start / pause / stop a timer
- [ ] User can edit the title of a task
- [ ] User can see a list of the completed pomodoro sessions
- [ ] User can customize the duration of each work / break session
Now that we know what we want to achieve with this Pomodoro Clock, let's start building a simple HTML structure.
Get my ebook on Amazon and Leanpub
Play and Pause a timer
We will start by creating a simple HTML structure to display a timer and add buttons to start, pause and stop it.
<div id="pomodoro-container">
<div id="pomodoro-clock">
<div id="pomodoro-timer"></div>
<div id="pomodoro-clock-actions">
<button id="pomodoro-start">Start</button>
<button id="pomodoro-pause">Pause</button>
<button id="pomodoro-stop">Stop</button>
</div>
</div>
</div>
Now that we have a basic structure let's start working on our toggleClock
function in the script.js
file.
This function will be called by all three buttons and will either start, pause or stop the timer.
First, let's attach an event listener to our buttons:
const pomodoroTimer = document.querySelector('#pomodoro-timer');
const startButton = document.querySelector('#pomodoro-start');
const pauseButton = document.querySelector('#pomodoro-pause');
const stopButton = document.querySelector('#pomodoro-stop');
// START
startButton.addEventListener('click', () => {
toggleClock();
})
// PAUSE
pauseButton.addEventListener('click', () => {
toggleClock();
})
// STOP
stopButton.addEventListener('click', () => {
toggleClock(true);
})
We stored each of our buttons in a variable and attached event listeners to them.
As you can see, for the stopButton
we are passing an argument in the toggleClock
function. You will see why in a moment.
In order to know whether we need to play or pause the timer, we need an additional variable which we'll call isClockRunning
which by default will be bind to false
.
let isClockRunning = false;
We will need a few more variables to complete our initial set:
// in seconds = 25 mins
let workSessionDuration = 1500;
let currentTimeLeftInSession = 1500;
// in seconds = 5 mins;
let breakSessionDuration = 300;
Now let's start writing our toggleClock
function.
const toggleClock = (reset) => {
if (reset) {
// STOP THE TIMER
} else {
if (isClockRunning === true) {
// PAUSE THE TIMER
isClockRunning = false;
} else {
// START THE TIMER
isClockRunning = true;
}
}
}
toggleClock
takes one argument, reset
which gets passed only when we are stopping the timer, otherwise we will look at the value of the variable isClockRunning
to see whether we need to play or pause the timer.
We will leverage the built-in method setInterval
to track our timer.
Inside of the else
statement, right below isClockRunning = true
we can write:
clockTimer = setInterval(() => {
// decrease time left / increase time spent
currentTimeLeftInSession--;
}, 1000)
What this does, is decrease our session time by 1 every second.
We want to be able to pause this timer when we click the pause button so go ahead and add this code to the toggleClock
function right above isClockRunning = false
:
clearInterval(clockTimer);
This will clear the timer that we set when we click the play button.
Create a function to format and display the time
The last step for this initial milestone will be to display the timer in our page.
To do that we will create a function called displayCurrentTimeLeftInSession
which will get called every second from our timer.
First, let's add this line right under currentTimeLeftInSession--;
so that our setInterval
looks like this
clockTimer = setInterval(() => {
currentTimeLeftInSession--;
displayCurrentTimeLeftInSession();
}, 1000);
Now, under our toggleClock
function, let's create a new one:
const displayCurrentTimeLeftInSession = () => {
const secondsLeft = currentTimeLeftInSession;
let result = '';
const seconds = secondsLeft % 60;
const minutes = parseInt(secondsLeft / 60) % 60;
let hours = parseInt(secondsLeft / 3600);
// add leading zeroes if it's less than 10
function addLeadingZeroes(time) {
return time < 10 ? `0${time}` : time
}
if (hours > 0) result += `${hours}:`
result += `${addLeadingZeroes(minutes)}:${addLeadingZeroes(seconds)}`
pomodoroTimer.innerText = result.toString();
}
Wow, I bet you got caught off-guard by this function but don't worry, it's not as complicate as it seems.
Since we are storing our timer in seconds, we need a way to format it so that the user can see minutes and seconds and not just seconds.
The symbol %
is called the remainder and you can read more about it here.
What it does is return the left over of the division of the first and second operand.
Example:
const x = 70;
x % 60;
// 10
Now image that x
is our secondsLeft
. 70 seconds essentially means 1 minute and 10 seconds.
As you can see, by using % 60
we get the seconds to display.
The next step is to get how many minutes are left in our timer and we do that like this:
const minutes = parseInt(secondsLeft / 60) % 60;
This will return us 1.
The last step is to count the hours like so:
let hours = parseInt(secondsLeft / 3600);
3600 is the amount of seconds in one hour.
A proper clock should display time in this format: "07:08" so we need to have a way to add leading zeroes when the minutes or seconds are less than 10.
function addLeadingZeroes(time) {
return time < 10 ? `0${time}` : time
}
This syntax may be confusing for a beginner but this is what is called a ternary operator and it is actually very simple and easy to use.
return time < 10 ? `0${time}` : time
Everytime before the '?' is what gets evaluated, in this case "is time less than 10?" and the first part in between the '?' and the ':' is what will return if the answer is YES whie the code after the ':' is what returns for a NO answer.
In plain text: "If time is less than 10, return time with a zero in front of it (eg: 09 instead of 9) and if time is more than 10, just return it".
The last part of the code simply creates a string by interpolating hours (if any), minutes and seconds together.
if (hours > 0) result += `${hours}:`
result += `${addLeadingZeroes(minutes)}:${addLeadingZeroes(seconds)}`
If you don't know what ${}
means, you can read more about string interpolation here.
In short, it allows us to write both variables and plain text together without having to constantly add strings to each other with a plus sign.
Once we have our nicely formatted string representing the time left in our timer, it's time to add it to our page with this simple line of code:
pomodoroTimer.innerText = result;
You can continue reading this tutorial at this link
Top comments (2)
is there a complete tutorial? I like the content so far, unfortunately the link takes me to a blank page.
Thanks for pointing that out, i didn't notice a bug on my website, this is the page for the tutorial inspiredwebdev.com/create-pomodoro... you can scroll down and continue reading, I'll sort out the bug today.