Building an extensible jQuery countdown plugin from scratch

Filed in Code 10 comments

It has been some time since I’ve last posted, I’ve been far too busy with a project I’ve been working on the past several months, but it’s almost ready and I hope I’ll get back to my weekly posting.

While working at this project, at some point I needed a countdown script to announce certain features being released on specific dates, maybe I’ve been a bit lazy and tried finding an already built countdown plugin to work with, but not much luck finding exactly what I was looking for so I’ve built my own.

Inspired from the countdown plugin video from The New Boston, I’ve decided to make this tutorial so everyone can be able to create their very own extensible jQuery countdown plugin.

If you don’t want to read the tutorial and just download the ready-to-use jQuery countdown script, then click here and read the instructions.txt file.

The point to build our own countdown script is to be able to have full control over it, to make it extensible and to be able to reuse it throughout our projects very easily.

Setting up our workspace

For this, we will obviously need the jQuery library which you can download from their website right here, but if you already have it, do make sure it’s the last stable version.

I’m assuming you already know how to create files and folders :) so create a folder for the CSS and one for the JavaScript files, because we want to be clean and work with unobtrusive code.

You can also download my clean workspace for this tutorial clicking here.

It’s entirely your decision where the countdown is positioned and how it is styled, but to keep this tutorial simple, we’ll use a basic look & feel and afterwards you can implement it as you wish.

Let’s create the HTML structure for the countdown:

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>jQuery countdown extensible plugin</title>
    <link rel="stylesheet" type="text/css" href="css/countdown.css">
  </head>
  <body>
    <ul id="countdown">
      <li>
        <span class="days">00</span>
        <p class="timeRef">days</p>
      </li>
      <li>
        <span class="hours">00</span>
        <p class="timeRef">hours</p>
      </li>
      <li>
        <span class="minutes">00</span>
        <p class="timeRef">minutes</p>
      </li>
      <li>
        <span class="seconds">00</span>
        <p class="timeRef">seconds</p>
      </li>
    </ul>
  </body>
</html>

The external stylesheet which goes in the CSS folder, containing some basic styles:

countdown.css

ul#countdown {
  margin: 10px auto;
  padding: 0;
}
ul#countdown li{
  background-color: #333;
  border: 2px solid #fff;
  color: #fff;
  display: inline;
  float: left;
  font: normal bold 36px Arial;
  letter-spacing: 5px;
  margin-left: 5px;
  text-align: center;
  width: 60px;
  border-radius: 6px;
  box-shadow: 0 0 3px #777;
}
ul#countdown span {
  padding-left: 5px;
}
ul#countdown  p.timeRef {
  font: normal normal 12px Arial;
  letter-spacing: 0;
  margin: 0;
  padding-bottom: 5px;
}

And in the JS folder goes the jQuery library.

Right now all we have is a static looking countdown, so let’s add the logic and build the plugin.
In the JS folder, create a file countdown.js, open it with your favorite code editor and let’s get to work.

We will build all of our code inside a plugin function that jQuery recognizes:

countdown.js

(function($) {
  $.fn.countdown = function() {
 
    // plugin code here
     
  }
}) (jQuery);

A jQuery plugin function requires a name and in our example we gave it countdown
Also, you’ll notice that the main function has a dollar sign parameter and the jQuery keyword at the end between paranthesis, if we wouldn’t have done that, we no longer could’ve used the short jQuery dollar sign namespace (i.e. $(“h1″) ) and had to use jQuery’s regular namespace (i.e. jQuery(“h1″) ).

It’s always good practice to test your functions before you start coding, a quick way to do it is to add a simple alert function and then just call it from an HTML page:

countdown.js

(function($) {
  $.fn.countdown = function() {
 
    alert("Hello!");
     
  }
}) (jQuery);

Now let’s test the plugin by calling it from our index.html

index.html

...

<head>
  <title>jQuery countdown extensible plugin</title>
  <script type="text/javascript" src="js/jquery-1.6.4.js"></script>
  <script type="text/javascript" src="js/countdown.js"></script>
  <link rel="stylesheet" type="text/css" href="css/countdown.css">
  <script type="text/javascript">
 
    $.fn.countdown();
 
  </script>
</head>

....

If you didn’t mistype anything, you should get an alert with the message “Hello!” when you open or refresh the page.

When you get different results than those mentioned in this article, try downloading the examples.

The beauty of a plugin is the control we can add to it by extending it with parameters where we can specify certain settings and a callback function that launches a code we want after it has successfully finished processing.
We’ll add two parameters to our plugin function, settings and callback.

countdown.js

(function($) {
  $.fn.countdown = function(options, callback) {
 
    //code here
     
  }
}) (jQuery);

Now that we have specified that our plugin requires two parameters, options and callback, let’s start adding our custom settings.
In our case, we’ll need to be able to add a date which we can make the plugin read and process.
We’ll specify our settings via an array, but we’ll start with just one setting for now:

countdown.js

(function($) {
  $.fn.countdown = function(options, callback) {
 
    //custom 'this' selector
    thisEl = $(this);
 
    // array of custom settings
    var settings = {
      'date': null,
    };
     
  }
}) (jQuery);

By default, we’ve set it to null so it would be empty if no date will be specified when calling the plugin.
Also, you’ll notice at the begining a new variable called thisEl (which can be called whatever you want), we added the $(this) selector onto this variable so we can easily reference our countdown’s html code later on. If you do not know what this means in JavaScript, do look it up as it’s one of the key elements of JavaScript.

To make the plugin’s options parameter recognize our settings array and reference all of our settings from it, we’ll use jQuery’s $.extend function

countdown.js

(function($) {
  $.fn.countdown = function(options, callback) {
 
    //custom 'this' selector
    thisEl = $(this);
 
    // array of custom settings
    var settings = {
      'date': null,
    };
   
    // append the settings array to options
    if(options) {
      $.extend(settings, options);
    }
  }
}) (jQuery);

We’ve told it that if the options parameter exists, then append the settings array to it.

So now we’re able to call the plugin and specify a date.

index.html

<!DOCTYPE html>
<html>
<head>
  <title>jQuery countdown plugin - devingredients.com</title>
  <link rel="stylesheet" type="text/css" href="css/countdown.css">
  <script type="text/javascript" src="js/jquery-1.6.4.js"></script>
  <script type="text/javascript" src="js/countdown.js"></script>
 
  <script type="text/javascript">
    $(document).ready(function() {
   
      $("#countdown").countdown({
        date: "4 december 2011 11:20:00", //add the countdown's end date (i.e. 3 november 2012 12:00:00)
      });
     
    });
  </script>
 
</head>
<body>
  <ul id="countdown">
    <li>
      <span class="days">00</span>
      <p class="timeRef">days</p>
    </li>
    <li>
      <span class="hours">00</span>
      <p class="timeRef">hours</p>
    </li>
    <li>
      <span class="minutes">00</span>
      <p class="timeRef">minutes</p>
    </li>
    <li>
      <span class="seconds">00</span>
      <p class="timeRef">seconds</p>
    </li>
  </ul>
</body>
</html>

We’ve applied the plugin onto an HTML’s countdown ID that holds the HTML elements for the countdown, this way the plugin will be much faster and won’t have to tranverse through the entire DOM to find the elements that it needs to interact with.
Now that we’re done with the basics, let’s get to the real processing.

But first! Let’s see how we can read the date value we specify when calling the plugin.
We’re going to create a new function inside our plugin called countdown_proc and we’re going to alert the date.

countdown.js

...

//create the countdown processing function
function countdown_proc() {
 
  alert(settings['date'];
 
}

//run the function
countdown_proc();

...

Since we assigned the settings array to be the place where we specify all of our properties, to fetch the date we use settings['date']. And if you add more properties, just use settings['PROPERTY_NAME'].
Now when you open or refresh the page, it will alert the date value you specify in your html page when calling the plugin.

Remove the alert and let’s make this plugin actually do something ;)
We’ll need two variables that will hold the current and end date. We’ll get the current date using the jQuery’s $.now() function that fetches the current date. The end date will be specified when calling the plugin so we’ll fetch it from there.

countdown.js

function countdown_proc() {
 
  eventDate = Date.parse(settings['date']) / 1000;
  currentDate = Math.floor($.now() / 1000);
 
}

To avoid confusion, let’s talk about date for a bit. We created the variable eventDate and we need to asign the date we specify when calling the plugin, like mentioned in the previous example (i.e. date: “4 december 2011 11:20:00″ ).
But what we really need is a timestamp date (number of seconds). So when we fetch the date value, we’ll also convert it into a timestamp date by using the Date.parse function, this will however give us the timestamp in milliseconds so we just divide it by 1000. Thus Date.parse(settings['date']) / 1000 results the timestamp in seconds.
As for the currentDate, jQuery has a function named $.now() that fetches the current date in milliseconds, again, we divide it by 1000 to work with seconds.

We have both variables for Current Date and for End Date, we’ll need to calculate the difference so we can populate the countdown with the difference between them, the remaining time that is.
We’ll create a variable seconds where we’ll do a simple math substraction to find out the number of seconds between the current and end date.

countdown.js

function countdown_proc() {
 
  eventDate = Date.parse(settings['date']) / 1000;
  currentDate = Math.floor($.now() / 1000);
 
  seconds = eventDate - currentDate;
 
}

Now that we know the remaining time in seconds, let’s calculate the number of days, hours, minutes and seconds and add them to variables which we can later use.

countdown.js

function countdown_proc() {
 
  eventDate = Date.parse(settings['date']) / 1000;
  currentDate = Math.floor($.now() / 1000);
 
  seconds = eventDate - currentDate;
 
  days = Math.floor(seconds / (60 * 60 * 24)); //calculate the number of days
  seconds -= days * 60 * 60 * 24; //update the seconds variable with no. of days removed
 
  hours = Math.floor(seconds / (60 * 60));
  seconds -= hours * 60 * 60; //update the seconds variable with no. of hours removed
 
  minutes = Math.floor(seconds / 60);
  seconds -= minutes * 60; //update the seconds variable with no. of minutes removed

}

Let’s explain days and you’ll figure out the rest of the math. To calculate the number of days, we used a simple math calculation where we divided the total number of seconds by a day (in seconds). A day has 86400 seconds, but just so we don’t have to remember how many seconds a period of time has, we just used (hours * minutes * seconds), equaling the number of seconds in a day. Thus, number of seconds divided by (60 * 60 * 24) => seconds / seconds in a day. Wow, I think I’m being way too explanatory here.
The Math.floor function that surrounds our math calculation does nothing more but to remove the remainder from our result and consider only the floor value of it, just so we won’t get results such as 3.3164400 days.

You’ll notice the seconds variable right afterwards, doing a math calculation with -=. What that does is remove the number of seconds used in the days variable so we can have an updated seconds variable without the number of days in order to continue calculating the hours, minutes and seconds.

var1 -= 3;

is the same as

var1 = var1 - 3;

And the process repeats for hours, minutes.

Finally the fun part, let’s populate our countdown’s html span values:

countdown.js

(function($) {
  $.fn.countdown = function(options, callback) {
 
    //custom jQuery 'this' selector
    thisEl = $(this);
 
    // array of custom settings
    var settings = {
      'date': null,
    };
   
    // append the settings array to options
    if(options) {
      $.extend(settings, options);
    }
   
    function countdown_proc() {
     
      eventDate = Date.parse(settings['date']) / 1000;
      currentDate = Math.floor($.now() / 1000);
     
      seconds = eventDate - currentDate;
     
      days = Math.floor(seconds / (60 * 60 * 24)); //calculate the number of days
      seconds -= days * 60 * 60 * 24; //update the seconds variable with no. of days removed
     
      hours = Math.floor(seconds / (60 * 60));
      seconds -= hours * 60 * 60; //update the seconds variable with no. of hours removed
     
      minutes = Math.floor(seconds / 60);
      seconds -= minutes * 60; //update the seconds variable with no. of minutes removed
     
      //update the countdown's html values.
      thisEl.find(".days").text(days);
      thisEl.find(".hours").text(hours);
      thisEl.find(".minutes").text(minutes);
      thisEl.find(".seconds").text(seconds);
     
    }
   
    //run the countdown_proc function
    countdown_proc();

  }
}) (jQuery);

If everything went well, each time you refresh the page and you should see the countdown updated with the remaining time.
We’ve used the thisEl variable to start working directly with the code of our countdown html portion, using .find to find the elements we want to update.

We do need to make the countdown update itself each second though, so we’ll just loop the process every second with the help of JavaScript’s setInterval function, we’ll add it after the countdown_proc function:

countdown.js

//loop the function
interval = setInterval(countdown_proc, 1000);

Now you should see the countdown updating itself each second.

setInterval requires the code you want to run and at what interval you want it to run (in milliseconds).
We’ve run it by also adding it to an interval variable so we can have control over it and in our case, stop it whenever the countdown finishes.

Even though the countdown’s working now, we still have a few more things to fix, or at least to consider.

If you’ll call the plugin with an event date that happens in a minute or so, you’ll notice that once it reaches time 0, it will not stop and start showing negative values. Let’s fix that.

Right after the eventDate and currentDate variables, let’s add the following condition

countdown.js

...

  if(eventDate <= currentDate) {
    callback.call(this);
    clearInterval(interval);
  }
     
...

What the condition basically does, is check whether the eventDate variable (that holds the timestamp date value of our event) is equal or less than the currentDate variable, if so, run the callback (the one we’ll specify when we’ll call the script in out html page) and also to clear the interval, at that point we no longer need the interval to keep looping our countdown script since the countdown ended.

Hoping that all of that was clear, let’s test it one more time and also make it alert a message when the countdown ends.

index.html

<!DOCTYPE html>
<html>
<head>
  <title>jQuery countdown plugin - devingredients.com</title>
  <link rel="stylesheet" type="text/css" href="css/countdown.css">
  <script type="text/javascript" src="js/jquery-1.6.4.js"></script>
  <script type="text/javascript" src="js/countdown.js"></script>
 
  <script type="text/javascript">
    $(document).ready(function() {
   
      $("#countdown").countdown({
        date: "18 february 2012 17:07:00", // add the countdown's end date (i.e. 3 november 2012 12:00:00)
      }, function() {
        alert("Countdown finished!");
      });
     
    });
  </script>
 
</head>
<body>
  <ul id="countdown">
    <li>
      <span class="days">00</span>
      <p class="timeRef">days</p>
    </li>
    <li>
      <span class="hours">00</span>
      <p class="timeRef">hours</p>
    </li>
    <li>
      <span class="minutes">00</span>
      <p class="timeRef">minutes</p>
    </li>
    <li>
      <span class="seconds">00</span>
      <p class="timeRef">seconds</p>
    </li>
  </ul>
</body>
</html>

countdown.js

(function($) {
  $.fn.countdown = function(options, callback) {

    //custom 'this' selector
    thisEl = $(this);

    // array of custom settings
    var settings = {
      'date': null,
    };
   
    // append the settings array to options
    if(options) {
      $.extend(settings, options);
    }
      function countdown_proc() {
       
        eventDate = Date.parse(settings['date']) / 1000;
        currentDate = Math.floor($.now() / 1000);
       
        if(eventDate <= currentDate) {
          callback.call(this);
          clearInterval(interval);
        }
       
        seconds = eventDate - currentDate;
       
        days = Math.floor(seconds / (60 * 60 * 24)); //calculate the number of days
        seconds -= days * 60 * 60 * 24; //update the seconds variable with no. of days removed
       
        hours = Math.floor(seconds / (60 * 60));
        seconds -= hours * 60 * 60; //update the seconds variable with no. of hours removed
       
        minutes = Math.floor(seconds / 60);
        seconds -= minutes * 60; //update the seconds variable with no. of minutes removed
       
        //update the countdown's html values.
        thisEl.find(".days").text(days);
        thisEl.find(".hours").text(hours);
        thisEl.find(".minutes").text(minutes);
        thisEl.find(".seconds").text(seconds);
       
    }
    countdown_proc();
   
    //loop the function
    interval = setInterval(countdown_proc, 1000);
   
  }
}) (jQuery);

As callback, we added an alert with the message “Countdown finished” that will show up when the countdown ends.
Now you have a functional countdown which you can use to announce features on a website, or perhaps the launch of an website itself.

We can however enhance this countdown even further.

Constant double digits setting

Depending on how you style the countdown, it can become inconsistent if the time displays both in single and double digits (i.e. 5:0:54 / 17:15:54), or maybe you want it to aways display with double digits for visual reasons only.
To achieve that, we’ll extend this plugin by adding one more setting, that is to turn on and off the display of double digits.
We’ll start by adding format as our new setting name with the value of null, in our settings array:

countdown.js

...

var settings = {
  'date': null,
  'format': null
};

...

We’ve set the value to null because we want it to hold no value as long as we do not set it when we call the plugin.
In our countdown.js script file, right after the last seconds variable we will add the following condition:

countdown.js

....

if(settings['format'] == "on") {
  days = (String(days).length >= 2) ? days : "0" + days;
  hours = (String(hours).length >= 2) ? hours : "0" + hours;
  minutes = (String(minutes).length >= 2) ? minutes : "0" + minutes;
  seconds = (String(seconds).length >= 2) ? seconds : "0" + seconds;
}

...

The reason why we want to have this condition set after the days, hours, minutes, seconds variables is because we want those variables to already exist and hold the real countdown values so we can now check whether their values are formed by two digits or not, and if not, we’ll add the missing 0.
So what we’ve done is to check if the format settings is set to ON and if so, check whether the values are formed by two digits and if not, add the missing zero.
The condition is quite simple and it’s exacty as an if-and-else statement.

Basically:

days = (String(days).length >= 2) ? days : "0" + days;

Is the same as:

if (String(days).length >= 2) {
  days = days;
} else {
  days  = "0" + days;
}

So if the days variable has two digits or more, leave it as it is, otherwise it must be made of just 1 character so append a 0 to it.

As a result we should have:

countdown.js

(function($) {
  $.fn.countdown = function(options, callback) {

    //custom 'this' selector
    thisEl = $(this);

    // array of custom settings
    var settings = {
      'date': null,
      'format' : null
    };
   
    // append the settings array to options
    if(options) {
      $.extend(settings, options);
    }
      function countdown_proc() {
       
        eventDate = Date.parse(settings['date']) / 1000;
        currentDate = Math.floor($.now() / 1000);
       
        if(eventDate <= currentDate) {
          callback.call(this);
          clearInterval(interval);
        }
       
        seconds = eventDate - currentDate;
       
        days = Math.floor(seconds / (60 * 60 * 24)); //calculate the number of days
        seconds -= days * 60 * 60 * 24; //update the seconds variable with no. of days removed
       
        hours = Math.floor(seconds / (60 * 60));
        seconds -= hours * 60 * 60; //update the seconds variable with no. of hours removed
       
        minutes = Math.floor(seconds / 60);
        seconds -= minutes * 60; //update the seconds variable with no. of minutes removed
       
        if(settings['format'] == "on") {
          days = (String(days).length >= 2) ? days : "0" + days;
          hours = (String(hours).length >= 2) ? hours : "0" + hours;
          minutes = (String(minutes).length >= 2) ? minutes : "0" + minutes;
          seconds = (String(seconds).length >= 2) ? seconds : "0" + seconds;
        }
       
        //update the countdown's html values.
        thisEl.find(".days").text(days);
        thisEl.find(".hours").text(hours);
        thisEl.find(".minutes").text(minutes);
        thisEl.find(".seconds").text(seconds);
       
    }
    countdown_proc();
   
    //loop the function
    interval = setInterval(countdown_proc, 1000);
   
  }
}) (jQuery);

and to force it to display two digits, we’ll call the plugin by specifying our format setting to ON.

index.html

<script type="text/javascript">
  $(document).ready(function() {
 
    $("#countdown").countdown({
      date: "18 november 2011 17:07:00", // add the countdown's end date (i.e. 3 november 2012 12:00:00)
      format: "on" // on (03:07:52) | off (3:7:52) - two_digits set to ON maintains layout consistency
    }, function() {
      alert("Countdown finished!");
    });
   
  });
</script>

Now the plugin has two settings to play with.
But it’s not yet an entirely fail-safe plugin, I say we should add a warning in case the date that’s added when calling the plugin is incorrect.
To do so all we have to do is wrap our *.text() methods in a condition where we check whether our eventDate variable is a number, if it’s not, that means the specified date is invalid and has been no longer successfully converted into a numerical timestamp.

countdown.js

//update the countdown's html values.
if(!isNaN(eventDate)) {
  thisEl.find(".days").text(days);
  thisEl.find(".hours").text(hours);
  thisEl.find(".minutes").text(minutes);
  thisEl.find(".seconds").text(seconds);
} else {
  alert("Invalid date. Here's an example: 12 Tuesday 2012 17:30:00");
  clearInterval(interval);
}

We used the isNaN function (which means is Not a Number) and prepended an exclamation mark to it to reverse the condition, so now it’s checking whether it is a number (!isNaN = if it’s not Not a Number).
And if it’s not, we just apply an alert with a warning and clear the interval to stop the timer.

What about the S endings of day(s) minute(s) when it actually display 1 as value?
We should make it display day when it shows 1 day and days when there are more days left.

Conditioning the Ss

To start, we’ll need to add a different class for each time reference (timeRef for days will become timeRefDays, for hours it will be timeRefHours and so on).

index.html

<!DOCTYPE html>
<html>
<head>
  <title>jQuery countdown plugin - devingredients.com</title>
  <link rel="stylesheet" type="text/css" href="css/countdown.css">
  <script type="text/javascript" src="js/jquery-1.6.4.js"></script>
  <script type="text/javascript" src="js/countdown.js"></script>
 
  <script type="text/javascript">
    $(document).ready(function() {
   
      $("#countdown").countdown({
        date: "4 december 2011 11:10:50", // add the countdown's end date (i.e. 3 november 2012 12:00:00)
        format: "on" // on (03:07:52) | off (3:7:52) - two_digits set to ON maintains layout consistency
      },
     
      function() {
       
        // the code here will run when the countdown ends
        alert("done!")

      });
    });
  </script>
 
</head>
<body>
  <ul id="countdown">
    <li>
      <span class="days">00</span>
      <p class="timeRefDays">days</p>
    </li>
    <li>
      <span class="hours">00</span>
      <p class="timeRefHours">hours</p>
    </li>
    <li>
      <span class="minutes">00</span>
      <p class="timeRefMinutes">minutes</p>
    </li>
    <li>
      <span class="seconds">00</span>
      <p class="timeRefSeconds">seconds</p>
    </li>
  </ul>
</body>
</html>

countdown.css

ul#countdown {
  margin: 10px auto;
  padding: 0;
}
ul#countdown li{
  background-color: #333;
  border: 2px solid #fff;
  color: #fff;
  display: inline;
  float: left;
  font: normal bold 36px Arial;
  letter-spacing: 5px;
  margin-left: 5px;
  text-align: center;
  width: 60px;
  border-radius: 6px;
  box-shadow: 0 0 3px #777;
}
ul#countdown span {
  padding-left: 5px;
}
ul#countdown  p.timeRefDays, ul#countdown  p.timeRefHours, ul#countdown  p.timeRefMinutes, ul#countdown  p.timeRefSeconds{
  font: normal normal 12px Arial;
  letter-spacing: 0;
  margin: 0;
  padding-bottom: 5px;
}

We already have access to our variables that display the coundown time, all we have to check is whether it’s 1 or not. If any time duration is 1, remove the s, otherwise show it.
Right before our format setting code, let’s add conditions for each time reference:

countdown.js

...

//conditional Ss
if (days == 1) { thisEl.find(".timeRefDays").text("day"); } else { thisEl.find(".timeRefDays").text("days"); }
if (hours == 1) { thisEl.find(".timeRefHours").text("hour"); } else { thisEl.find(".timeRefHours").text("hours"); }
if (minutes == 1) { thisEl.find(".timeRefMinutes").text("minute"); } else { thisEl.find(".timeRefMinutes").text("minutes"); }
if (seconds == 1) { thisEl.find(".timeRefSeconds").text("second"); } else { thisEl.find(".timeRefSeconds").text("seconds"); }

...

And there we have it! Man, me and my long articles :/
I hope that all the details at each step somehow helped you and didn’t actually clutter your mind more hehe

Here’s the final code:

index.html

<!DOCTYPE html>
<html>
<head>
  <title>jQuery countdown plugin - devingredients.com</title>
  <link rel="stylesheet" type="text/css" href="css/countdown.css">
  <script type="text/javascript" src="js/jquery-1.6.4.js"></script>
  <script type="text/javascript" src="js/countdown.js"></script>
 
  <script type="text/javascript">
    $(document).ready(function() {
   
      $("#countdown").countdown({
        date: "23 february 2012 1:50:30", // add the countdown's end date (i.e. 3 november 2012 12:00:00)
        format: "on" // on (03:07:52) | off (3:7:52) - two_digits set to ON maintains layout consistency
      },
     
      function() {
       
        // the code here will run when the countdown ends
        alert("done!")

      });
    });
  </script>
 
</head>
<body>
  <ul id="countdown">
    <li>
      <span class="days">00</span>
      <p class="timeRefDays">days</p>
    </li>
    <li>
      <span class="hours">00</span>
      <p class="timeRefHours">hours</p>
    </li>
    <li>
      <span class="minutes">00</span>
      <p class="timeRefMinutes">minutes</p>
    </li>
    <li>
      <span class="seconds">00</span>
      <p class="timeRefSeconds">seconds</p>
    </li>
  </ul>
</body>
</html>

countdown.css

ul#countdown {
  margin: 10px auto;
  padding: 0;
}
ul#countdown li{
  background-color: #333;
  border: 2px solid #fff;
  color: #fff;
  display: inline;
  float: left;
  font: normal bold 36px Arial;
  letter-spacing: 5px;
  margin-left: 5px;
  text-align: center;
  width: 60px;
  border-radius: 6px;
  box-shadow: 0 0 3px #777;
}
ul#countdown span {
  padding-left: 5px;
}
ul#countdown  p.timeRefDays, ul#countdown  p.timeRefHours, ul#countdown  p.timeRefMinutes, ul#countdown  p.timeRefSeconds{
  font: normal normal 12px Arial;
  letter-spacing: 0;
  margin: 0;
  padding-bottom: 5px;
}

countdown.js

(function($) {
  $.fn.countdown = function(options, callback) {

    //custom 'this' selector
    thisEl = $(this);

    //array of custom settings
    var settings = {
      'date': null,
      'format': null
    };

    //append the settings array to options
    if(options) {
      $.extend(settings, options);
    }
   
    //main countdown function
    function countdown_proc() {
     
      eventDate = Date.parse(settings['date']) / 1000;
      currentDate = Math.floor($.now() / 1000);
     
      if(eventDate <= currentDate) {
        callback.call(this);
        clearInterval(interval);
      }
     
      seconds = eventDate - currentDate;
     
      days = Math.floor(seconds / (60 * 60 * 24)); //calculate the number of days
      seconds -= days * 60 * 60 * 24; //update the seconds variable with no. of days removed
     
      hours = Math.floor(seconds / (60 * 60));
      seconds -= hours * 60 * 60; //update the seconds variable with no. of hours removed
     
      minutes = Math.floor(seconds / 60);
      seconds -= minutes * 60; //update the seconds variable with no. of minutes removed
     
      //conditional Ss
      if (days == 1) { thisEl.find(".timeRefDays").text("day"); } else { thisEl.find(".timeRefDays").text("days"); }
      if (hours == 1) { thisEl.find(".timeRefHours").text("hour"); } else { thisEl.find(".timeRefHours").text("hours"); }
      if (minutes == 1) { thisEl.find(".timeRefMinutes").text("minute"); } else { thisEl.find(".timeRefMinutes").text("minutes"); }
      if (seconds == 1) { thisEl.find(".timeRefSeconds").text("second"); } else { thisEl.find(".timeRefSeconds").text("seconds"); }
     
      //logic for the two_digits ON setting
      if(settings['format'] == "on") {
        days = (String(days).length >= 2) ? days : "0" + days;
        hours = (String(hours).length >= 2) ? hours : "0" + hours;
        minutes = (String(minutes).length >= 2) ? minutes : "0" + minutes;
        seconds = (String(seconds).length >= 2) ? seconds : "0" + seconds;
      }
     
      //update the countdown's html values.
      if(!isNaN(eventDate)) {
        thisEl.find(".days").text(days);
        thisEl.find(".hours").text(hours);
        thisEl.find(".minutes").text(minutes);
        thisEl.find(".seconds").text(seconds);
      } else {
        alert("Invalid date. Here's an example: 12 Tuesday 2012 17:30:00");
        clearInterval(interval);
      }
    }
   
    //run the function
    countdown_proc();
   
    //loop the function
    interval = setInterval(countdown_proc, 1000);
   
  }
}) (jQuery);

Once you’ve read the entire tutorial, all the code should no longer look difficult at all, in fact, keep spending some time playing with it, get comfortable with it, add more control as needed.

In fact, I’ll reward the first person who makes the countdown change its color once it’s about to end, and the time that it should start changing its color should be specified as a setting.

Reward: A free link in the footer of this blog for 3 whole months* :)

* Yes, that little pesky star, I’ll have to specify that I won’t be accepting any website that contains rude, obscene or racist content.

The code is free to use for both personal and commercial purposes, however, do try to subscribe, tweet, like and so on… share the love!

Good luck!

Posted by Catalin   @   22 November 2011 10 comments
Tags : , ,

Share This Post

RSS Digg Twitter StumbleUpon Delicious Technorati

10 Comments

Comments
Nov 23, 2011
2:54 AM
#1 Bud :

Awesome Tutorial Catalin-I have never used jquery but to link to it as part of a script.

I am going to try and ‘setting’ to change color as you challenged.

Author Nov 23, 2011
10:18 AM
#2 Catalin :

Good to hear from you, Bud :-)

If you manage to add the setting, then my friend, you can add jQuery to your web development skills.

Good luck!

Jan 2, 2012
8:51 AM

I’ve never used this jQuery. This time ‘m going to try out, well thanks for the tutorial, its been a great help.

Author Jan 2, 2012
8:54 PM
#4 Catalin :

@michelleweb
I’m glad it has helped you. jQuery is now a main dev ingredient :-) I strongly recommend that you dive in its world as well.

Feb 13, 2012
1:00 PM
#5 Doane*16 :

Thanks for the well indeed tutorial in creating the HTML structure for the countdown, But I can’t say that I’m good enough to catch up immediately the ideas that you share here, Because I’m not really familiar about it. However, Thanks a lot.

Mar 10, 2012
9:12 PM
#6 Andrew :

Where is this countdown plg going to? :) ) Ok, I must have the countdown with negative values after 0 time. I delete the code from “if(eventDate <= currentDate) {". And what I can find here? First – the first negative sign. It's right, couse we are on the second side of the 0. Second – is the time upgoing? NO, the time is downgoing to … the midnight of today!!! (start date 01 march 2012 00:00:00) Can you fixt it?
Second matter – how much of instances of this script can be displayed at one page? I need from 10 to 50, with different times. brgs, thank you for your lesson of Query, very fine for beginners. Thank You.

Mar 11, 2012
12:26 AM
#7 Andrew :

Math.abs(eventDate

Mar 11, 2012
1:12 AM
#8 Andrew :

can you change the incoming date format into (yyyy-mm-dd hours:minutes:seconds) or (yyy,mm,dd,hours,minutes,seconds)? It will be better to load it from dbase ..

Author Mar 11, 2012
8:20 PM
#9 Catalin :

I’m having a hard time understanding the end result you’re expecting for this countdown to do.

Can you please describe in details exactly what you’re trying to achieve? I’ll see if I’ll find the time to do it for you :-)

Trackbacks to this post.
Leave a Comment

Previous Post
«
Next Post
Luix designed by Video Game Music In conjunction with VPS Hosting , Website Hosting and Shared Hosting.