JavaScript Countdown Timer

Summary: in this tutorial, you’ll learn how to develop a reusable JavaScript countdown timer.

What is a countdown timer

A countdown timer is a virtual clock running on a landing page. And it counts down from a certain date to indicate the beginning (or the end) of an event.

On eCommerce websites, you can use a countdown timer to display the beginning (or the end) of an offer. The purpose of the countdown timer is to urge customers to take actions such as buying products or services.

In this tutorial, you’ll learn how to create a countdown timer in JavaScript from scratch. And you’ll learn how to use it to build a New Year countdown timer.

The following shows the final New Year countdown landing page.

Note that the countdown timer that you’re going to build is reusable so you can use it on any landing page. In addition, you can use this countdown to create multiple countdown timers on a single page.

Create the project structure

First, create a project folder called countdown-timer. Inside that folder, create three subfolders: js, css, and img that will store the JavaScript, CSS, and image files.

Second, create the style.css in the css folder, app.js and countdown.js files in the js folder, and the index.html in the countdown-timer folder:

Third, download this firework picture and copy it to the img folder. You’ll use this picture as the background of the New Year countdown page.

The project structure will look like this:

Create the HTML page

The HTML page is quite simple because you’ll generate most of the HTML code from JavaScript.

The following shows the complete HTML page:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript Countdown Timer - New Year Countdown</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <h1>New Year Countdown</h1>
    <div class="countdown-timer"></div>
    <div class="message"></div>
    <div class="year"></div>

    <script src="js/countdown.js"></script>
    <script src="js/app.js"></script>

</body>
</html>Code language: HTML, XML (xml)

In the index.html file, you place a link to the style.css file in the <head> section and the countdown.js and app.js files in the <body> section.

Note that the countdown.js file must appear before the app.js file because the app.js will use the objects in the countdown.js file.

The <body> section has four elements:

  • A heading 1 (<h1>) . This element will show a heading. It can be anything that describes the countdown e.g., New Year Countdown.
  • A <div> with the class countdown-timer . This element will display the countdown.
  • A <div> with the message class. This element will display the message when the countdown completes.
  • And a <div> with the year class. This element will show the New Year e.g., 2021.

A quick overview of the Date object

To create the timer, you’ll need to work with the Date object, which is available in all web browsers.

The Date object represents a single moment in time. It contains a number that represents the milliseconds since January 1, 1970 UTC.

The following shows how to create a new Date object that represents the current date and time:

const now = new Date();Code language: JavaScript (javascript)

And this example shows how to call the getTime() method of the Date object to get the number of milliseconds since January 1, 1970 00:00:00 UTC:

const time = now.getTime();
console.log(time);Code language: JavaScript (javascript)

To create a new Date object with a specified date and time, you can pass a date string into the Date() constructor like this:

const d = new Date('February 02, 2020 01:02:03');
console.log(d.getTime()); // 1580580123000Code language: JavaScript (javascript)

To calculate the number of milliseconds between two times, you call the getTime() method and use the - operator. For example:

const d1 = new Date('September 17, 2020 00:00:00');
const d2 = new Date('September 19, 2020 01:00:00');

const time = d2.getTime() - d1.getTime();
console.log(time); // 176400000Code language: JavaScript (javascript)

Calculate the remaing time

The countdown timer will need to calculate the remaining days, hours, minutes, and seconds from a number of milliseconds and display this information on a webpage.

The following declare a time variable with the value 150000 milliseconds:

const time = 150000; // msCode language: JavaScript (javascript)

To convert milliseconds to minutes, you divide the milliseconds by 1000 to get the seconds and divide the seconds by 60 to get the minutes. For example:

console.log(time / 1000 / 60); Code language: JavaScript (javascript)

Output:

2.5Code language: CSS (css)

To get the remaining minutes (2), you use the Math.floor() function:

const minutes = Math.floor(time / 1000 / 60);
console.log(minutes); // 2Code language: JavaScript (javascript)

To get the remaining seconds (30), you use the modulus operator ( % ) that returns the division remainder:

const seconds = Math.floor(time / 1000) % 60;
console.log(seconds); // 30Code language: JavaScript (javascript)

Develop the CountDown class

First, create a new CountDown class in the countdown.js file:

class CountDown {
}Code language: JavaScript (javascript)

The CountDown class should be initialized with three arguments:

  • an expired date.
  • a callback that is responsible for rendering the countdown timer.
  • and another callback that will be called when the countdown completes.

The constructor of the CountDown class will look like this:

class CountDown {
    constructor(expiredDate, onRender, onComplete) {
        this.onRender = onRender;
        this.onComplete = onComplete;
        // handle the expired Date
        ..
    }
}Code language: JavaScript (javascript)

Based on the expiredDate argument, you can calculate the remaining time in milliseconds:

const currentTime = new Date().getTime();
const timeRemaining = expiredDate.getTime() - currentTime;Code language: JavaScript (javascript)

Since you’ll need to access the remaining time (timeRemaining) across methods of the class, you should define it as a property of the CountDown class.

The setExpiredDate() method

The following defines a new method called setExpiredDate() that initializes the timeRemaining property:

 setExpiredDate(expiredDate) {
    // get the current time
    const currentTime = new Date().getTime();
    // calculate the remaining time 
    this.timeRemaining = expiredDate.getTime() - currentTime;
}Code language: JavaScript (javascript)

If the timeRemaining is greater than zero, the setExpiredDate() method will execute the start() method to start the timer. Otherwise, it’ll execute the complete() method.

The setExpiredDate() will look like this:

setExpiredDate(expiredDate) {
    // get the current time
    const currentTime = new Date().getTime();

    // calculate the remaining time 
    this.timeRemaining = expiredDate.getTime() - currentTime;

    // should the countdown completes or start
    this.timeRemaining > 0 ?
        this.start() :
        this.complete();
}Code language: JavaScript (javascript)

Note that we use the ternary operator ?: to execute the complete() or start() method based on the value of the this.timeRemaining property.

The complete() method

The complete() method checks if the onComplete callback is passed and invoke it. If the onComplete isn’t available, the complete() won’t do anything.

complete() {
    if (typeof this.onComplete === 'function') {
        onComplete();
    }
}Code language: JavaScript (javascript)

start() method

The start() method reduces the timeRemaining property every second (1000 ms).

If the remaining time is less than zero, the start() method will:

  • First, call the complete() method.
  • Second, clear the timer using the clearInterval() function.
start() {
    //  setup a timer
    const intervalId = setInterval(() => {
        // update the timer  
        this.timeRemaining -= 1000;

        if (this.timeRemaining < 0) {
            // call the callback
            complete();

            // clear the interval if expired
            clearInterval(intervalId);
        }

    }, 1000);
}Code language: JavaScript (javascript)

In case the remaining time is greater than zero, the start() method should call a method that executes the onRender callback.

The getTime() method

The following getTime() method returns an object that contains the remaining days, hours, minutes, and seconds based on the timeRemaining property.

  getTime() {
    return {
        days: Math.floor(this.timeRemaining / 1000 / 60 / 60 / 24),
        hours: Math.floor(this.timeRemaining / 1000 / 60 / 60) % 24,
        minutes: Math.floor(this.timeRemaining / 1000 / 60) % 60,
        seconds: Math.floor(this.timeRemaining / 1000) % 60
    };
}Code language: JavaScript (javascript)

The update() method

The following defines the update() method that calls the onRender() callback with the current remaining time object returned by the getTime() method:

update() {
    if (typeof this.onRender === 'function') {
        this.onRender(this.getTime());
    }
}Code language: JavaScript (javascript)

The start() method will call the update() method at the beginning and every second after that:

start() {
    // update the countdown
    this.update();

    //  setup a timer
    const intervalId = setInterval(() => {
        // update the timer  
        this.timeRemaining -= 1000;

        if (this.timeRemaining < 0) {
            // call the callback
            complete();

            // clear the interval if expired
            clearInterval(intervalId);
        } else {
            this.update();
        }

    }, 1000);
}Code language: JavaScript (javascript)

The following shows the complete CountDown class:

class CountDown {
    constructor(expiredDate, onRender, onComplete) {
        this.setExpiredDate(expiredDate);

        this.onRender = onRender;
        this.onComplete = onComplete;
    }

    setExpiredDate(expiredDate) {
        // get the current time
        const currentTime = new Date().getTime();

        // calculate the remaining time 
        this.timeRemaining = expiredDate.getTime() - currentTime;

        this.timeRemaining <= 0 ?
            this.complete() :
            this.start();
    }


    complete() {
        if (typeof this.onComplete === 'function') {
            onComplete();
        }
    }
    getTime() {
        return {
            days: Math.floor(this.timeRemaining / 1000 / 60 / 60 / 24),
            hours: Math.floor(this.timeRemaining / 1000 / 60 / 60) % 24,
            minutes: Math.floor(this.timeRemaining / 1000 / 60) % 60,
            seconds: Math.floor(this.timeRemaining / 1000) % 60
        };
    }

    update() {
        if (typeof this.onRender === 'function') {
            this.onRender(this.getTime());
        }
    }

    start() {
        // update the countdown
        this.update();

        //  setup a timer
        const intervalId = setInterval(() => {
            // update the timer  
            this.timeRemaining -= 1000;

            if (this.timeRemaining < 0) {
                // call the callback
                complete();

                // clear the interval if expired
                clearInterval(intervalId);
            } else {
                this.update();
            }

        }, 1000);
    }
}Code language: JavaScript (javascript)

Build the New Year countdown

First, create a new function called getNewYear() method that returns the New Year:

const getNewYear = () => {
    const currentYear = new Date().getFullYear();
    return new Date(`January 01 ${currentYear + 1} 00:00:00`);
};Code language: JavaScript (javascript)

Second, select and update the .year element. It’ll show a four-digit year number of the New Year e.g., 2021:

// update the year element
const year = document.querySelector('.year');
year.innerHTML = getNewYear().getFullYear();Code language: JavaScript (javascript)

Third, select the .countdown-timer, .message and h1 elements:

// select elements
const app = document.querySelector('.countdown-timer');
const message = document.querySelector('.message');
const heading = document.querySelector('h1');Code language: JavaScript (javascript)

Fourth, define a format function that pad a number with the '0' if the number is less than 10. For example, 5 will be 05. But 10 will remain the same.

const format = (t) => {
    return t < 10 ? '0' + t : t;
};Code language: JavaScript (javascript)

Fifth, define a render() method that composes HTML markup from the time object and update it to the .countdown-timer element. It’ll show the remaining days, hours, minutes, and seconds.


const render = (time) => {
    app.innerHTML = `
        <div class="count-down">
            <div class="timer">
                <h2 class="days">${format(time.days)}</h2>
                <small>Days</small>
            </div>
            <div class="timer">
                <h2 class="hours">${format(time.hours)}</h2>
                <small>Hours</small>
            </div>
            <div class="timer">
                <h2 class="minutes">${format(time.minutes)}</h2>
                <small>Minutes</small>
            </div>
            <div class="timer">
                <h2 class="seconds">${format(time.seconds)}</h2>
                <small>Seconds</small>
            </div>
        </div>
        `;
};
Code language: HTML, XML (xml)

Fifth, when the countdown completes, it shows a message e.g., "Happy New Year".

The following showMessage() function displays the Happy New Year message. In addition, it clears the contents of the .countdown-timer element and hides the heading element:

const showMessage = () => {
    message.innerHTML = `Happy New Year ${newYear}!`;
    app.innerHTML = '';
    heading.style.display = 'none';
};Code language: JavaScript (javascript)

Sixth, the New Year countdown should show the Happy New Year greeting message for a period of time and then displays the countdown for the New Year again.

The following defines a function that hides the greeting message and shows the heading element:

const hideMessage = () => {
    message.innerHTML = '';
    heading.style.display = 'block';
}Code language: JavaScript (javascript)

Seventh, define a complete() function that shows the message for a period of time and then hides it. In addition, it sets the expiredDate to the New Year:

const complete = () => {
    showMessage();
    // restart the countdown after showing the 
    // greeting message for a day ()
    setTimeout(() => {
        hideMessage();
        countdownTimer.setExpiredDate(getNewYear());
    }, 1000 * 60 * 24);
};Code language: JavaScript (javascript)

Finally, create the new CountDown instance and pass the New Year date, render function, and complete function into its constructor:

const countdownTimer = new CountDown(
    getNewYear(),
    render,
    complete
);Code language: JavaScript (javascript)

The following shows the complete app.js file:

// Get the new year 
const getNewYear = () => {
    const currentYear = new Date().getFullYear();
    return new Date(`January 01 ${currentYear + 1} 00:00:00`);
};

// update the year element
const year = document.querySelector('.year');
year.innerHTML = getNewYear().getFullYear();

// select elements
const app = document.querySelector('.countdown-timer');
const message = document.querySelector('.message');
const heading = document.querySelector('h1');


const format = (t) => {
    return t < 10 ? '0' + t : t;
};

const render = (time) => {
    app.innerHTML = `
        <div class="count-down">
            <div class="timer">
                <h2 class="days">${format(time.days)}</h2>
                <small>Days</small>
            </div>
            <div class="timer">
                <h2 class="hours">${format(time.hours)}</h2>
                <small>Hours</small>
            </div>
            <div class="timer">
                <h2 class="minutes">${format(time.minutes)}</h2>
                <small>Minutes</small>
            </div>
            <div class="timer">
                <h2 class="seconds">${format(time.seconds)}</h2>
                <small>Seconds</small>
            </div>
        </div>
        `;
};


const showMessage = () => {
    message.innerHTML = `Happy New Year ${newYear}!`;
    app.innerHTML = '';
    heading.style.display = 'none';
};

const hideMessage = () => {
    message.innerHTML = '';
    heading.style.display = 'block';
};

const complete = () => {
    showMessage();

    // restart the countdown after showing the 
    // greeting message for a day ()
    setTimeout(() => {
        hideMessage();
        countdownTimer.setExpiredDate(getNewYear());
    }, 1000 * 60 * 60 * 24);
};

const countdownTimer = new CountDown(
    getNewYear(),
    render,
    complete
);Code language: JavaScript (javascript)

If you open the index.html, you’ll see that the New Year countdown is up and running.

Sumary

In this tutorial, you’ve learned how to:

  • Use the ES6 class to define a reusable countdown timer component.
  • Use the Date object to manipulate time.
  • Use the setInterval() and clearInterval() to create and cancel a timed repeating action.
Was this tutorial helpful ?