diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..886150d
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,29 @@
+{
+ "name": "jQuery-Countdown",
+ "homepage": "https://github.com/martinaglv/jQuery-Countdown",
+ "authors": [
+ "Martin Angelov"
+ ],
+ "description": "A simple jQuery plugin for creating a countdown timer.",
+ "main": "./countdown/jquery.countdown.js",
+ "moduleType": [
+ "amd",
+ "globals",
+ "node"
+ ],
+ "keywords": [
+ "countdown"
+ ],
+ "license": "MIT",
+ "private": true,
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests"
+ ],
+ "dependencies": {
+ "jquery": "~1.11.3 || ~2.1.4"
+ }
+}
diff --git a/countdown/jquery.countdown.js b/countdown/jquery.countdown.js
index 2f06b47..8d1079b 100644
--- a/countdown/jquery.countdown.js
+++ b/countdown/jquery.countdown.js
@@ -1,138 +1,217 @@
/**
* @name jQuery Countdown Plugin
* @author Martin Angelov
- * @version 1.0
+ * @version 1.1
* @url http://tutorialzine.com/2011/12/countdown-jquery/
+ * @link https://github.com/martinaglv/jQuery-Countdown
* @license MIT License
+ *
+ * Changelog:
+ * ----------
+ *
+ * v1.0 Initial Commit
+ * v1.1 Add support for more than 99 days
*/
-(function($){
-
+(function (root, factory) {
+ if (typeof define === "function" && define.amd) {
+ // AMD
+ define(["jquery"], factory);
+ } else if (typeof exports === "object") {
+ // Node, CommonJS-like
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals (root is window)
+ root.jcountdown = factory(root.$);
+ }
+}(this, function ($) {
+ 'use strict';
+
// Number of seconds in every time division
var days = 24*60*60,
hours = 60*60,
minutes = 60;
-
- // Creating the plugin
+
+ /**
+ * Creating the plugin
+ *
+ * @param prop
+ * @returns {jQuery}
+ */
$.fn.countdown = function(prop){
-
var options = $.extend({
callback : function(){},
timestamp : 0
- },prop);
-
- var left, d, h, m, s, positions;
+ }, prop);
// Initialize the plugin
init(this, options);
-
- positions = this.find('.position');
-
+
+ // Get the position elements once the html has been set in the init above
+ var positions = this.find('.position');
+
(function tick(){
-
- // Time left
- left = Math.floor((options.timestamp - (new Date())) / 1000);
-
- if(left < 0){
- left = 0;
- }
-
- // Number of days left
- d = Math.floor(left / days);
- updateDuo(0, 1, d);
- left -= d*days;
-
- // Number of hours left
- h = Math.floor(left / hours);
- updateDuo(2, 3, h);
- left -= h*hours;
-
- // Number of minutes left
- m = Math.floor(left / minutes);
- updateDuo(4, 5, m);
- left -= m*minutes;
-
- // Number of seconds left
- s = left;
- updateDuo(6, 7, s);
-
+ var time = calculateRemainingTime(options.timestamp),
+ position = 0;
+
+ $.each(time, function(index, value) {
+ var digits = getDigits(value);
+
+ // We might have to shift 1 places (because we normalized to a minimum of 2 digits)
+ if(digits < 2) {
+ value = '0' + value;
+ digits = 2;
+ }
+
+ for(var i = 0; i < digits; i++){
+ switchDigit(positions.eq(position), value.toString()[i]);
+ position++;
+ }
+ });
+
// Calling an optional user supplied callback
- options.callback(d, h, m, s);
-
+ options.callback(time.d, time.h, time.m, time.s);
+
// Scheduling another call of this function in 1s
setTimeout(tick, 1000);
})();
-
- // This function updates two digit positions at once
- function updateDuo(minor,major,value){
- switchDigit(positions.eq(minor),Math.floor(value/10)%10);
- switchDigit(positions.eq(major),value%10);
- }
-
+
return this;
};
+ /**
+ * Calculate the amount of time ramaining given a timestamp
+ *
+ * @param {number} timestamp - A timestamp in seconds (Unix date)
+ * @returns {Object} The remaining time to the present
+ */
+ function calculateRemainingTime (timestamp) {
+ var left, time = {};
+
+ // Time left
+ left = (timestamp - new Date().getTime()) / 1000;
+ left = left < 0 && 0 || left;
+
+ // Number of days left
+ time.d = Math.floor(left / days);
+ left -= time.d * days;
+
+ // Number of hours left
+ time.h = Math.floor(left / hours);
+ left -= time.h * hours;
+
+ // Number of minutes left
+ time.m = Math.floor(left / minutes);
+ left -= time.m * minutes;
+
+ // Number of seconds left
+ time.s = Math.floor(left);
+
+ return time;
+ }
+
+ /**
+ * Get the number of digits of a number
+ *
+ * @param {number} number
+ * @returns {number} - The number of digits
+ */
+ function getDigits(number) {
+ return number ? Math.log(number) * Math.LOG10E + 1 | 0 : 1;
+ }
+
+ /**
+ * Returns an HTML string containing a certain number of digits
+ *
+ * @param {number} number
+ * @returns {String} - An HTML string
+ */
+ function getDigitsHTML(number) {
+ var digitHTML = '0',
+ digitsHTML = '',
+ digits = getDigits(number);
+
+ // Normalize minimum number of digits (we always show at least 2 digits)
+ if(digits < 2) digits = 2;
+
+ // Build the digits html
+ for(var i = 0; i < digits; i++){
+ digitsHTML += digitHTML;
+ }
+ return digitsHTML;
+ }
+
+ /**
+ * Initializes the countdown widget
+ *
+ * @param {jQuery} elem - The wrapper element for the countdown
+ * @param {Object} options - Contains the callback and timestamp arguments
+ * @returns {void}
+ */
function init(elem, options){
+ // Get the time offset from the start
+ var time = calculateRemainingTime(options.timestamp);
+
+ // Add own class to countdown wrapper
elem.addClass('countdownHolder');
// Creating the markup inside the container
- $.each(['Days','Hours','Minutes','Seconds'],function(i){
- $('').html(
- '\
- 0\
- \
- \
- 0\
- '
+ $.each(['d','h','m','s'], function(index, value){
+ $('').html(
+ getDigitsHTML(time[value])
).appendTo(elem);
-
- if(this!="Seconds"){
- elem.append('');
+
+ if(this !== "s"){
+ elem.append('');
}
});
-
}
- // Creates an animated transition between the two numbers
- function switchDigit(position,number){
-
- var digit = position.find('.digit')
-
- if(digit.is(':animated')){
+ /**
+ * Creates an animated transition between the two numbers
+ *
+ * Note: The .static class is added when the animation completes. This makes it run smoother.
+ *
+ * @param position
+ * @param {number} number
+ * @returns {boolean} - TRUE if it switched the digit
+ */
+ function switchDigit(position, number){
+ var digit = position.find('.digit'),
+ replacement = $('',{
+ 'class':'digit',
+ css: {
+ top:'-2.1em',
+ opacity:0
+ },
+ html: number
+ });
+
+ // No transition is necessary
+ if(digit.is(':animated'))
return false;
- }
-
- if(position.data('digit') == number){
- // We are already showing this number
+
+ // We are already showing this number
+ if(position.data('digit') == number)
return false;
- }
-
- position.data('digit', number);
-
- var replacement = $('',{
- 'class':'digit',
- css:{
- top:'-2.1em',
- opacity:0
- },
- html:number
- });
-
- // The .static class is added when the animation
- // completes. This makes it run smoother.
-
+
+ position
+ .data('digit', number);
+
digit
.before(replacement)
.removeClass('static')
- .animate({top:'2.5em',opacity:0},'fast',function(){
+ .animate({top:'2.5em', opacity:0}, 'fast', function(){
digit.remove();
- })
+ });
replacement
.delay(100)
- .animate({top:0,opacity:1},'fast',function(){
+ .animate({top:0, opacity:1}, 'fast', function(){
replacement.addClass('static');
});
+
+ return true;
}
-})(jQuery);
\ No newline at end of file
+}));
\ No newline at end of file