forked from KittyGiraudel/Countdown.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
countdown.js
192 lines (158 loc) · 4.99 KB
/
countdown.js
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
(function(global) {
"use strict";
// Vanilla JS alternative to $.extend
global.extend = function (obj, extObj) {
obj = obj || {};
if (arguments.length > 2) {
for (var a = 1; a < arguments.length; a++) {
global.extend(obj, arguments[a]);
}
} else {
for (var i in extObj) {
obj[i] = extObj[i];
}
}
return obj;
};
// Countdown constructor
var Countdown = function (conf) {
this.conf = global.extend({
// Dates
dateStart : new Date(),
dateEnd : new Date(new Date().getTime() + (24 * 60 * 60 * 1000)),
// Default elements
selector : ".timer",
// Messages
msgBefore : "Be ready!",
msgAfter : "It's over, sorry folks!",
msgPattern : "{days} days, {hours} hours, {minutes} minutes and {seconds} seconds left.",
// Callbacks
onStart : null,
onEnd : null,
// Extra options
leadingZeros : false,
initialize : true
}, conf);
// Private variables
this.started = false;
this.selector = document.querySelectorAll(this.conf.selector);
this.interval = 1000;
this.patterns = [
{ pattern: "{years}", secs: 31536000 },
{ pattern: "{months}", secs: 2628000 },
{ pattern: "{weeks}", secs: 604800 },
{ pattern: "{days}", secs: 86400 },
{ pattern: "{hours}", secs: 3600 },
{ pattern: "{minutes}", secs: 60 },
{ pattern: "{seconds}", secs: 1 }
];
// Doing all the things!
if (this.initialize !== false) {
this.initialize();
}
};
// Initializing the instance
Countdown.prototype.initialize = function () {
this.defineInterval();
// Already over
if (this.isOver()) {
return this.outOfInterval();
}
this.run();
};
// Converting a date into seconds
Countdown.prototype.seconds = function (date) {
return date.getTime() / 1000;
};
// Returning if countdown has started yet
Countdown.prototype.isStarted = function () {
return this.seconds(new Date()) >= this.seconds(this.conf.dateStart);
};
// Returning if countdown is over yet
Countdown.prototype.isOver = function () {
return this.seconds(new Date()) >= this.seconds(this.conf.dateEnd);
};
// Running the countdown
Countdown.prototype.run = function () {
var that = this,
sec = Math.abs(this.seconds(this.conf.dateEnd) - this.seconds(new Date())),
timer;
// Initial display before first tick
if (this.isStarted()) {
this.display(sec);
}
// Not started yet
else {
this.outOfInterval();
}
// Vanilla JS alternative to $.proxy
timer = global.setInterval(function () {
sec--;
// Time over
if (sec <= 0) {
global.clearInterval(timer);
that.outOfInterval();
that.callback("end");
}
else if (that.isStarted()) {
if (!that.started) {
that.callback("start");
that.started = true;
}
that.display(sec);
}
}, this.interval);
};
// Displaying the countdown
Countdown.prototype.display = function (sec) {
var output = this.conf.msgPattern;
for (var b = 0; b < this.patterns.length; b++) {
var currentPattern = this.patterns[b];
if (this.conf.msgPattern.indexOf(currentPattern.pattern) !== -1) {
var number = Math.floor(sec / currentPattern.secs),
displayed = this.conf.leadingZeros && number <= 9 ? "0" + number : number;
sec -= number * currentPattern.secs;
output = output.replace(currentPattern.pattern, displayed);
}
}
for (var c = 0; c < this.selector.length; c++) {
this.selector[c].innerHTML = output;
}
};
// Defining the interval to be used for refresh
Countdown.prototype.defineInterval = function () {
for (var e = this.patterns.length; e > 0; e--) {
var currentPattern = this.patterns[e-1];
if (this.conf.msgPattern.indexOf(currentPattern.pattern) !== -1) {
this.interval = currentPattern.secs * 1000;
return;
}
}
};
// Canceling the countdown in case it's over
Countdown.prototype.outOfInterval = function () {
var message = new Date() < this.conf.dateStart ? this.conf.msgBefore : this.conf.msgAfter;
for (var d = 0; d < this.selector.length; d++) {
if (this.selector[d].innerHTML !== message) {
this.selector[d].innerHTML = message;
}
}
};
// Dealing with events and callbacks
Countdown.prototype.callback = function (event) {
var e = event.capitalize();
// onStart callback
if (typeof this.conf["on" + e] === "function") {
this.conf["on" + e]();
}
// Triggering a jQuery event if jQuery is loaded
if (typeof global.jQuery !== "undefined") {
global.jQuery(this.conf.selector).trigger("countdown" + e);
}
};
// Adding a capitalize method to String
String.prototype.capitalize = function () {
return this.charAt(0).toUpperCase() + this.slice(1);
};
global.Countdown = Countdown;
}(window));