mrkaluzny homepage
Tips & Tricks

Pomodoro Clock - Free Code Camp Project

Jun 29, 2016

Since I have a new and shiny website I can finally add some more insights into Free Code Camp projects. In order to get my Front-End Certification I need to complete few last projects - one of which is creating a Pomodoro Clock.

What’s a pomodoro clock?

The Pomodoro Technique is a time management method developed by Francesco Cirillo in the late 1980s. The technique uses a timer to break down work into intervals, traditionally 25 minutes in length, separated by short breaks. These intervals are named pomodoros, the plural in English of the Italian word pomodoro (tomato), after the tomato-shaped kitchen timer that Cirillo used as a university student. The method is based on the idea that frequent breaks can improve mental agility. 1

Therefore the purpose of the app I’ll be building is to enable our user to set the timer to given value and alert him or her after the countdown is completed.

Pomodoro Clock - User Stories & Objective

Objective: Build a CodePen.io app that is functionally similar to this.

User Stories:

  • I can start a 25 minute pomodoro, and the timer will go off once 25 minutes has elapsed.
  • I can reset the clock for my next pomodoro.
  • I can customize the length of each pomodoro.

Preparing the working directory

Simple enough it’s time to start coding. First of all it’s time to create a basic file structure for our project. To do it quickly I often take advantage of Terminal for Mac. After launching the terminal I typed in `cd path/to/my/project` to enter the right directory.

The second thing I tend to do is initiating git directory by using git init command. Now it’s time to add basic files to my project - command touch index.html style.css script.js README.md creates basic files necessary for the project.

Let’s code

Now that I created all the files necessary it’s time to create first prototype of my app.

First HTML

<!DOCTYPE html>
<html>
  <head>
    <title>Pomodoro Clock</title>
    <meta name="author" content="Wojciech Kałużny" />
    <link
      rel="stylesheet"
      href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"
    />
    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <div class="container app">
      <div class="row">
        <div class="col-md-12">
          <h2 class="name-tag">Pomodoro Clock</h2>
        </div>
      </div>
      <div class="row">
        <div class="col-xs-6 controls">
          <h4>Break Length</h4>
          <div class="btn-group">
            <div
              class="btn btn-default btn-lg switchDeduceBreak"
              onclick="deduceBreakTime()"
            >
              -
            </div>
            <div class="btn btn-lg" id="timer-break">5</div>
            <div
              class="btn btn-default btn-lg switchAddBreak"
              onclick="addBreakTime()"
            >
              +
            </div>
          </div>
        </div>
        <div class="col-xs-6 controls">
          <h4>Session Length</h4>
          <div class="btn-group">
            <div
              class="btn btn-default btn-lg switchDeduceSession"
              onclick="deduceSessionTime()"
            >
              -
            </div>
            <div id="timer-session" class="btn btn-lg">25</div>
            <div
              class="btn btn-default btn-lg switchAddSession"
              onclick="addSessionTime()"
            >
              +
            </div>
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-xs-12">
          <div class="countdown-clock">
            <div class="countdown-timer">
              <h2>Current Session</h2>
              <h3 id="timeLeft">25</h3>
            </div>
          </div>
        </div>
      </div>
    </div>

    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <script src="script.js"></script>
  </body>
</html>

Basic CSS

body {
  background-color: #292f36;
  color: #14cc60;
  font-family: 'Work Sans', sans-serif;
}

.app {
  background-color: white;
  padding: 20px;
  margin: 20px auto;
  border-left: 4px solid slategray;
}

.countdown-clock {
  border: 2px solid black;
  width: 400px;
  height: 400px;
  border-radius: 400px;
  margin: 50px auto;
}

.controls {
  margin: 10px auto;
}

.countdown-timer {
  text-align: center;
  margin-top: 120px;
}

#timeLeft {
  font-size: 6em;
  text-align: center;
}

That basic code is a great starting point for building the app further. The core functionality is developed with JavaScript. I already approach this project some time ago, that’s why I have some js to start with.

var sessionLength = 25;
var breakLength = 5;

function addSessionTime() {
  sessionLength += 1;
  $('#timer-session').text(sessionLength);
  $('#timeLeft').text(sessionLength);
}

function deduceSessionTime() {
  if (sessionLength > 1) {
    sessionLength -= 1;
  } else {
    sessionLength = 1;
  }
  $('#timer-session').text(sessionLength);
  $('#timeLeft').text(sessionLength);
}

function deduceBreakTime() {
  if (breakLength > 1) {
    breakLength -= 1;
  } else {
    breakLength = 1;
  }
  $('#timer-break').text(breakLength);
}

function addBreakTime() {
  breakLength += 1;
  $('#timer-break').text(breakLength);
}

This simple JavaScript adds basic functionality to my app. Different functions enables running the code when necessary (only when click event is triggered on particular button).

Functions responsible for deducing time utilize simple if..else statements in order to prevent user from going into negative values. All functions are connected to html elements with onclick attribute.

Core functionality

Building the core functionality is the most difficult part of building this simple app. Using previously shown functions we set the most important variables to the right values.

Now it’s time to enable user to start the timer. For this purpose I created a simple function called startTimer() which doesn’t take any arguments.

Here’s the full function:

function startTimer() {
  seconds = 0;
  countDown(sessionLength, seconds);
}

Ok so what it does? The function sets value of a global variable seconds to 0, and then passes it to a new function called countDown(m,s) which takes 2 arguments. The first argument is m (short for minutes) and the other one is s (short for seconds).

Countdown function is responsible for the whole functionality of the app.

Here’s complete countDown function:

function countDown(m,s) {
    countInt = setInterval(function(){

    if (m == 0 &amp;&amp; s == 0) {
        clearInterval(countInt);
        if (loop == 0) {
            timeLeft = breakLength;
            loop += 1;
            $('#sessionName').text('Current Break');
        } else {
            timeLeft = sessionLength;
            loop -= 1;
            $('#sessionName').text('Current Session');
        }
        alarm.play();
        countDown(timeLeft,0);
    } else if (s != 0) {
        if (s <= 10){
            s -= 1;
            timeLeft = m + ':0' + s;
        } else {
            s -= 1;
            timeLeft = m + ':' + s;
        }
    } else if (s == 0) {
        s = 59;
        m -= 1;
        timeLeft = m + ':' + s;
    }
        $('#timeLeft').text(timeLeft);

    }, 1000);
}

At first the function sets an interval of 1000ms (1s). The interval enables this function to loop every 1 second changing the time left on the clock.

Within the interval there’s quite complicated if..else statement. The first if statement checks whether any minutes or seconds left to count down from. If not, then the interval is cleared and new break or session starts again. Also the sound is played (it was declared at the top of .js code using var alarm = new Audio('alarm.mp3’);).

Other parts of this function use appropriate form of counting the time for the best displaying method (sloppy, but effective).

Conclusion

The whole app is quite simple to make. It took me about 2 hrs to complete this challenge along with writing this simple article and copying it to CodePen and GitHub.

As always if you have any questions/comments - tweet @mrkaluzny or leave a comment below.