├── img
├── bg-tile.png
├── digits.png
├── digits.psd
├── digits-min.png
└── time-placeholder.png
├── css
└── media.css
├── index.html
├── README.md
└── js
├── jquery.countdown.min.js
└── jquery.countdown.js
/img/bg-tile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/download/jquery-countdown/master/img/bg-tile.png
--------------------------------------------------------------------------------
/img/digits.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/download/jquery-countdown/master/img/digits.png
--------------------------------------------------------------------------------
/img/digits.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/download/jquery-countdown/master/img/digits.psd
--------------------------------------------------------------------------------
/img/digits-min.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/download/jquery-countdown/master/img/digits-min.png
--------------------------------------------------------------------------------
/img/time-placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/download/jquery-countdown/master/img/time-placeholder.png
--------------------------------------------------------------------------------
/css/media.css:
--------------------------------------------------------------------------------
1 | html, body, .wrapper {
2 | height: 100%;
3 | width: 100%;
4 | }
5 | body { background: url(../img/bg-tile.png) repeat; }
6 |
7 | .wrapper { display: table; }
8 |
9 | .cell {
10 | display: table-cell;
11 | margin: 0;
12 | padding: 0;
13 | text-align: center;
14 | vertical-align: middle;
15 | }
16 |
17 | #holder {
18 | width: 603px;
19 | height: 383px;
20 | margin: auto;
21 | }
22 |
23 | .cntSeparator { display: none; }
24 |
25 | .cntDigit {
26 | margin-top: 148px !important;
27 | }
28 |
29 | .cntDigit#cnt_0 { margin-left: 52px; }
30 | .cntDigit#cnt_2 { margin-left: 7px; }
31 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | jquery-countdown plugin test
5 |
6 |
7 |
8 |
17 |
18 |
19 |
20 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jQuery Countdown
2 |
3 | jQuery Countdown is a countdown library with an amazing animation. Take a look
4 | at the [demonstration](http://reflejo.github.com/jquery-countdown/)
5 |
6 | Now you can download the PSD file
7 | [here](https://github.com/Reflejo/jquery-countdown/blob/master/img/digits.psd).
8 |
9 | ### Basic usage:
10 |
11 | ```javascript
12 | $('#counter').countdown({startTime: "01:12:32:55"});
13 | ```
14 |
15 | ### Complete usage:
16 |
17 | ```javascript
18 | $('#counter').countdown({
19 | stepTime: 60,
20 | format: 'hh:mm:ss',
21 | startTime: "12:32:55",
22 | digitImages: 6,
23 | digitWidth: 53,
24 | digitHeight: 77,
25 | timerEnd: function() { alert('end!!'); },
26 | image: "digits.png"
27 | });
28 | ```
29 |
30 | ### Added continuous countdown
31 |
32 | ```javascript
33 | $('#counter').countdown({
34 | format: 'sss',
35 | startTime: "120",
36 | continuous: true,
37 | timerEnd: function() { alert('end!!'); },
38 | image: "digits.png"
39 | });
40 | ```
41 |
42 | ### Countdown to a Date
43 |
44 | Relative to current hour:
45 |
46 | ```javascript
47 | $('#counter').countdown({
48 | image: "digits.png",
49 | format: "mm:ss",
50 | endTime: '50:00'
51 | });
52 | ```
53 |
54 | An absolute date:
55 |
56 |
57 | ```javascript
58 | $('#counter').countdown({
59 | image: "digits.png",
60 | format: "mm:ss",
61 | endTime: new Date('07/16/13 05:00:00')
62 | });
63 | ```
64 |
65 | Start manually the counter:
66 |
67 | ```javascript
68 | $('#counter').countdown({
69 | image: "digits.png",
70 | format: "mm:ss",
71 | endTime: new Date('07/16/13 05:00:00'),
72 | start: false
73 | });
74 | $("#startButton").click(function (e) {
75 | $('#counter').start();
76 | });
77 | ```
78 |
79 | Did I mention that js code weighs just **4.0 KB**?
80 |
81 | ### Developers
82 |
83 | - Martín Conte Mac Donell - - [@fz](https://twitter.com/fz)
84 | - [Matt Neary](http://mattneary.com) -
85 |
86 | ### Demo
87 |
88 | Look at the [demo](http://reflejo.github.com/jquery-countdown/).
89 |
90 |
--------------------------------------------------------------------------------
/js/jquery.countdown.min.js:
--------------------------------------------------------------------------------
1 | var createDigits=function(t,e){var i,n,r=0;digits=[],intervals=[];for(var a=0;a=0){if(elem=$('').css({height:e.digitHeight,"float":"left",background:"url('"+e.image+"')",width:e.digitWidth}),elem.current=parseInt(e.startTime[a]),digits.push(elem),margin(r,-elem.current*e.digitHeight*e.digitImages),e.continuous===!0)digits[r]._max=function(){return 9};else switch(e.format[a]){case"h":digits[r]._max=function(t,e){return t%2==0?2:e?3:9};break;case"d":digits[r]._max=function(){return 9};break;case"m":digits[r]._max=function(t){return i||(i=t),t==i?9:5};break;case"s":digits[r]._max=function(t){return n||(n=t),t==n?9:5}}r+=1}else elem=$('').css({"float":"left"}).text(e.startTime[a]);t.append(elem)}},makeMovement=function(t,e,i,n){intervals[t]&&window.clearInterval(intervals[t]);var r=-(n.digitHeight*n.digitImages*digits[t].current);margin(t,r),digits[t].current=digits[t].current+(i?e:-e);var a=0;intervals[t]=setInterval(function(){if(a++===n.digitImages*e)return window.clearInterval(intervals[t]),void delete intervals[t];var s=i?-n.digitHeight:n.digitHeight;margin(t,r+a*s)},n.stepTime/e)},margin=function(t,e){return void 0!==e?(digits[t].margin=e,digits[t].css({backgroundPosition:"0 "+e+"px"})):digits[t].margin||0},moveDigit=function(t,e){if(0!=digits[t].current)makeMovement(t,1,!1,e);else if(t>0){var i=0==digits[t-1].current;makeMovement(t,digits[t]._max(t,i),!0,e),moveDigit(t-1,e)}else{for(var n=0;n
5 | * Dual licensed under the MIT and GPL licenses.
6 | * http://docs.jquery.com/License
7 | *
8 | */
9 |
10 | // Draw digits in given container
11 | var createDigits = function(where, options) {
12 | var counter = 0;
13 | // Iterate each startTime digit, if it is not a digit
14 | // we'll asume that it's a separator
15 | var mFirstPos, sFirstPos;
16 | // reset digits and intervals array.
17 | digits = [];
18 | intervals = [];
19 |
20 | for (var i = 0; i < options.startTime.length; i++) {
21 | if (parseInt(options.startTime[i]) >= 0) {
22 | elem = $('').css({
23 | height: options.digitHeight,
24 | float: 'left',
25 | background: 'url(\'' + options.image + '\')',
26 | width: options.digitWidth
27 | });
28 |
29 | elem.current = parseInt(options.startTime[i]);
30 | digits.push(elem);
31 |
32 | margin(counter, -elem.current * options.digitHeight * options.digitImages);
33 |
34 | if (options.continuous === true) {
35 | digits[counter]._max = function() { return 9; };
36 | } else {
37 | // Add max digits, for example, first digit of minutes (mm) has
38 | // a max of 5. Conditional max is used when the left digit has reach
39 | // the max. For example second "hours" digit has a conditional max of 4
40 | switch (options.format[i]) {
41 | case 'h':
42 | digits[counter]._max = function(pos, isStart) {
43 | if (pos % 2 == 0)
44 | return 2;
45 | else
46 | return (isStart) ? 3: 9;
47 | };
48 | break;
49 | case 'd':
50 | digits[counter]._max = function() { return 9; };
51 | break;
52 | case 'm':
53 | digits[counter]._max = function(pos) {
54 | if(!mFirstPos) { mFirstPos = pos; }
55 | return pos == mFirstPos ? 9 : 5;
56 | };
57 | break;
58 | case 's':
59 | digits[counter]._max = function(pos) {
60 | if(!sFirstPos) { sFirstPos = pos; }
61 | return pos == sFirstPos ? 9 : 5;
62 | };
63 | }
64 | }
65 |
66 | counter += 1;
67 | } else {
68 | elem = $('').css({float: 'left'})
69 | .text(options.startTime[i]);
70 | }
71 | where.append(elem)
72 | }
73 | };
74 |
75 | var makeMovement = function(elem, steps, isForward, options) {
76 | // Stop any other movement over the same digit.
77 | if (intervals[elem])
78 | window.clearInterval(intervals[elem]);
79 |
80 | // Move to the initial position (We force that because in chrome
81 | // there are some scenarios where digits lost sync)
82 | var initialPos = -(options.digitHeight * options.digitImages *
83 | digits[elem].current);
84 | margin(elem, initialPos);
85 | digits[elem].current = digits[elem].current + ((isForward) ? steps: -steps);
86 |
87 | var x = 0;
88 | intervals[elem] = setInterval(function() {
89 | if (x++ === options.digitImages * steps) {
90 | window.clearInterval(intervals[elem]);
91 | delete intervals[elem];
92 | return;
93 | }
94 |
95 | var diff = isForward ? -options.digitHeight: options.digitHeight;
96 | margin(elem, initialPos + (x * diff));
97 | }, options.stepTime / steps);
98 | };
99 |
100 | // Set or get element margin
101 | var margin = function(elem, val) {
102 | if (val !== undefined) {
103 | digits[elem].margin = val;
104 | return digits[elem].css({'backgroundPosition': '0 ' + val + 'px'});
105 | }
106 |
107 | return digits[elem].margin || 0;
108 | };
109 |
110 |
111 | // Makes the movement. This is done by "digitImages" steps.
112 | var moveDigit = function(elem, options) {
113 | if (digits[elem].current == 0) {
114 | // Is there still time left?
115 | if (elem > 0) {
116 | var isStart = (digits[elem - 1].current == 0);
117 |
118 | makeMovement(elem, digits[elem]._max(elem, isStart), true, options);
119 | moveDigit(elem - 1, options);
120 | } else { // That condition means that we reach the end! 00:00.
121 | for (var i = 0; i < digits.length; i++) {
122 | clearInterval(intervals[i]);
123 | clearInterval(intervals.main);
124 | margin(i, 0);
125 | }
126 | options.timerEnd();
127 | }
128 | return;
129 | }
130 | makeMovement(elem, 1, false, options);
131 | };
132 |
133 |
134 |
135 | // parses a date of the form hh:mm:ss, for example, where
136 | // ... precision is the same as the format.
137 | var parseRelativeDate = function(form, options) {
138 | // give the date the values of now by default
139 | var now = new Date();
140 | var d = now.getDate();
141 | var m = now.getMonth() + 1;
142 | var y = now.getFullYear();
143 | var h = now.getHours(), mm, s;
144 |
145 | // read in components and render based on format
146 | var format = options.format;
147 | var parts = form.split(':');
148 | if( format.indexOf('dd') == 0 ) {
149 | d = parts[0];
150 | parts = parts.slice(1);
151 | format = format.substr(3);
152 | }
153 | if( format.indexOf('hh') == 0 ) {
154 | h = parts[0];
155 | parts = parts.slice(1);
156 | format = format.substr(3);
157 | }
158 | if( format.indexOf('mm') == 0 ) {
159 | mm = parts[0];
160 | parts = parts.slice(1);
161 | format = format.substr(3);
162 | }
163 | if( format.indexOf('ss') == 0 ) {
164 | s = parts[0];
165 | parts = parts.slice(1);
166 | format = format.substr(3);
167 | }
168 | // return our constructed date object
169 | return new Date([m, d, y].join('/') + ' ' + [h, mm, s].map(pad).join(':') + ' GMT-0900');
170 | };
171 |
172 |
173 | // convert a date object to the format specified
174 | var formatCompute = function(d, options) {
175 | var format = options.format;
176 | var parse = {
177 | d: Math.floor( ( d - new Date( d.getFullYear(), 0, 1 ) ) / ( 1000 * 60 * 60 * 24 ) ),
178 | h: d.getUTCHours(),
179 | m: d.getUTCMinutes(),
180 | s: d.getUTCSeconds()
181 | };
182 | return format.replace(/(dd|hh|mm|ss)/g, function($0, form) {
183 | return pad(parse[form[0]]);
184 | });
185 | };
186 |
187 | // add leading zeros
188 | var pad = function(x){return (1e15+""+x).slice(-2)};
189 |
190 | var start = function (element) {
191 | if (element.attr('started') != 'true') {
192 | element.attr('started', true)
193 | intervals.main = setInterval(function () {
194 | moveDigit(digits.length - 1, element.data('options'));
195 | },
196 | 1000);
197 | }
198 | };
199 |
200 | var digits = [];
201 | var intervals = [];
202 | jQuery.fn.countdown = function(userOptions) {
203 | // Default options
204 | var options = {
205 | stepTime: 60,
206 | // startTime and format MUST follow the same format.
207 | // also you cannot specify a format unordered (e.g. hh:ss:mm is wrong)
208 | format: "dd:hh:mm:ss",
209 | startTime: "01:12:32:55",
210 | digitImages: 6,
211 | digitWidth: 67,
212 | digitHeight: 90,
213 | timerEnd: function(){},
214 | image: "digits.png",
215 | continuous: false,
216 | start: true
217 | };
218 | $.extend(options, userOptions);
219 |
220 | // if an endTime is provided...
221 | if( userOptions.endTime ) {
222 | // calculate the difference between endTime and present time
223 | var endDate = userOptions.endTime instanceof Date ? userOptions.endTime : parseRelativeDate(userOptions.endTime, options);
224 | var diff = endDate.getTime() - (new Date()).getTime();
225 | // and set that as the startTime
226 | userOptions.startTime = formatCompute(new Date(diff), options);
227 | delete userOptions.endTime;
228 | }
229 | $.extend(options, userOptions);
230 | if (this.length) {
231 | clearInterval(intervals.main);
232 | createDigits(this, options);
233 | this.data('options', options);
234 | if (options.start === true) {
235 | start(this);
236 | }
237 | }
238 | };
239 |
240 | // start the counter
241 | jQuery.fn.start = function () {
242 | start(this);
243 | };
244 |
--------------------------------------------------------------------------------