-
Notifications
You must be signed in to change notification settings - Fork 60
Expand file tree
/
Copy pathjquery.countdown.js
More file actions
217 lines (182 loc) · 4.9 KB
/
jquery.countdown.js
File metadata and controls
217 lines (182 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/**
* @name jQuery Countdown Plugin
* @author Martin Angelov
* @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 (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
*
* @param prop
* @returns {jQuery}
*/
$.fn.countdown = function(prop){
var options = $.extend({
callback : function(){},
timestamp : 0
}, prop);
// Initialize the plugin
init(this, options);
// Get the position elements once the html has been set in the init above
var positions = this.find('.position');
(function tick(){
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(time.d, time.h, time.m, time.s);
// Scheduling another call of this function in 1s
setTimeout(tick, 1000);
})();
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 = '<span class="position"><span class="digit static">0</span></span>',
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(['d','h','m','s'], function(index, value){
$('<span class="count'+ this +'">').html(
getDigitsHTML(time[value])
).appendTo(elem);
if(this !== "s"){
elem.append('<span class="countDiv countDiv'+ index +'"></span>');
}
});
}
/**
* 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 = $('<span>',{
'class':'digit',
css: {
top:'-2.1em',
opacity:0
},
html: number
});
// No transition is necessary
if(digit.is(':animated'))
return false;
// We are already showing this number
if(position.data('digit') == number)
return false;
position
.data('digit', number);
digit
.before(replacement)
.removeClass('static')
.animate({top:'2.5em', opacity:0}, 'fast', function(){
digit.remove();
});
replacement
.delay(100)
.animate({top:0, opacity:1}, 'fast', function(){
replacement.addClass('static');
});
return true;
}
}));