1+ /*!
2+ * The Final Countdown for jQuery v2.1.0 (http://hilios.github.io/jQuery.countdown/)
3+ * Copyright (c) 2015 Edson Hilios
4+ *
5+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
6+ * this software and associated documentation files (the "Software"), to deal in
7+ * the Software without restriction, including without limitation the rights to
8+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+ * the Software, and to permit persons to whom the Software is furnished to do so,
10+ * subject to the following conditions:
11+ *
12+ * The above copyright notice and this permission notice shall be included in all
13+ * copies or substantial portions of the Software.
14+ *
15+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21+ */
22+ ( function ( factory ) {
23+ "use strict" ;
24+ if ( typeof define === "function" && define . amd ) {
25+ define ( [ "jquery" ] , factory ) ;
26+ } else {
27+ factory ( jQuery ) ;
28+ }
29+ } ) ( function ( $ ) {
30+ "use strict" ;
31+ var instances = [ ] , matchers = [ ] , defaultOptions = {
32+ precision : 100 ,
33+ elapse : false
34+ } ;
35+ matchers . push ( / ^ [ 0 - 9 ] * $ / . source ) ;
36+ matchers . push ( / ( [ 0 - 9 ] { 1 , 2 } \/ ) { 2 } [ 0 - 9 ] { 4 } ( [ 0 - 9 ] { 1 , 2 } ( : [ 0 - 9 ] { 2 } ) { 2 } ) ? / . source ) ;
37+ matchers . push ( / [ 0 - 9 ] { 4 } ( [ \/ \- ] [ 0 - 9 ] { 1 , 2 } ) { 2 } ( [ 0 - 9 ] { 1 , 2 } ( : [ 0 - 9 ] { 2 } ) { 2 } ) ? / . source ) ;
38+ matchers = new RegExp ( matchers . join ( "|" ) ) ;
39+ function parseDateString ( dateString ) {
40+ if ( dateString instanceof Date ) {
41+ return dateString ;
42+ }
43+ if ( String ( dateString ) . match ( matchers ) ) {
44+ if ( String ( dateString ) . match ( / ^ [ 0 - 9 ] * $ / ) ) {
45+ dateString = Number ( dateString ) ;
46+ }
47+ if ( String ( dateString ) . match ( / \- / ) ) {
48+ dateString = String ( dateString ) . replace ( / \- / g, "/" ) ;
49+ }
50+ return new Date ( dateString ) ;
51+ } else {
52+ throw new Error ( "Couldn't cast `" + dateString + "` to a date object." ) ;
53+ }
54+ }
55+ var DIRECTIVE_KEY_MAP = {
56+ Y : "years" ,
57+ m : "months" ,
58+ n : "daysToMonth" ,
59+ w : "weeks" ,
60+ d : "daysToWeek" ,
61+ D : "totalDays" ,
62+ H : "hours" ,
63+ M : "minutes" ,
64+ S : "seconds"
65+ } ;
66+ function escapedRegExp ( str ) {
67+ var sanitize = str . toString ( ) . replace ( / ( [ . ? * + ^ $ [ \] \\ ( ) { } | - ] ) / g, "\\$1" ) ;
68+ return new RegExp ( sanitize ) ;
69+ }
70+ function strftime ( offsetObject ) {
71+ return function ( format ) {
72+ var directives = format . match ( / % ( - | ! ) ? [ A - Z ] { 1 } ( : [ ^ ; ] + ; ) ? / gi) ;
73+ if ( directives ) {
74+ for ( var i = 0 , len = directives . length ; i < len ; ++ i ) {
75+ var directive = directives [ i ] . match ( / % ( - | ! ) ? ( [ a - z A - Z ] { 1 } ) ( : [ ^ ; ] + ; ) ? / ) , regexp = escapedRegExp ( directive [ 0 ] ) , modifier = directive [ 1 ] || "" , plural = directive [ 3 ] || "" , value = null ;
76+ directive = directive [ 2 ] ;
77+ if ( DIRECTIVE_KEY_MAP . hasOwnProperty ( directive ) ) {
78+ value = DIRECTIVE_KEY_MAP [ directive ] ;
79+ value = Number ( offsetObject [ value ] ) ;
80+ }
81+ if ( value !== null ) {
82+ if ( modifier === "!" ) {
83+ value = pluralize ( plural , value ) ;
84+ }
85+ if ( modifier === "" ) {
86+ if ( value < 10 ) {
87+ value = "0" + value . toString ( ) ;
88+ }
89+ }
90+ format = format . replace ( regexp , value . toString ( ) ) ;
91+ }
92+ }
93+ }
94+ format = format . replace ( / % % / , "%" ) ;
95+ return format ;
96+ } ;
97+ }
98+ function pluralize ( format , count ) {
99+ var plural = "s" , singular = "" ;
100+ if ( format ) {
101+ format = format . replace ( / ( : | ; | \s ) / gi, "" ) . split ( / \, / ) ;
102+ if ( format . length === 1 ) {
103+ plural = format [ 0 ] ;
104+ } else {
105+ singular = format [ 0 ] ;
106+ plural = format [ 1 ] ;
107+ }
108+ }
109+ if ( Math . abs ( count ) === 1 ) {
110+ return singular ;
111+ } else {
112+ return plural ;
113+ }
114+ }
115+ var Countdown = function ( el , finalDate , options ) {
116+ this . el = el ;
117+ this . $el = $ ( el ) ;
118+ this . interval = null ;
119+ this . offset = { } ;
120+ this . options = $ . extend ( { } , defaultOptions ) ;
121+ this . instanceNumber = instances . length ;
122+ instances . push ( this ) ;
123+ this . $el . data ( "countdown-instance" , this . instanceNumber ) ;
124+ if ( options ) {
125+ if ( typeof options === "function" ) {
126+ this . $el . on ( "update.countdown" , options ) ;
127+ this . $el . on ( "stoped.countdown" , options ) ;
128+ this . $el . on ( "finish.countdown" , options ) ;
129+ } else {
130+ this . options = $ . extend ( { } , defaultOptions , options ) ;
131+ }
132+ }
133+ this . setFinalDate ( finalDate ) ;
134+ this . start ( ) ;
135+ } ;
136+ $ . extend ( Countdown . prototype , {
137+ start : function ( ) {
138+
139+ if ( this . interval !== null ) {
140+ clearInterval ( this . interval ) ;
141+ }
142+ var self = this ;
143+ this . update ( ) ;
144+ this . interval = setInterval ( function ( ) {
145+ self . update . call ( self ) ;
146+ } , this . options . precision ) ;
147+ } ,
148+ stop : function ( ) {
149+ clearInterval ( this . interval ) ;
150+ this . interval = null ;
151+ this . dispatchEvent ( "stoped" ) ;
152+ } ,
153+ toggle : function ( ) {
154+ if ( this . interval ) {
155+ this . stop ( ) ;
156+ } else {
157+ this . start ( ) ;
158+ }
159+ } ,
160+ pause : function ( ) {
161+ this . stop ( ) ;
162+ } ,
163+ resume : function ( ) {
164+ this . start ( ) ;
165+ } ,
166+ remove : function ( ) {
167+ this . stop . call ( this ) ;
168+ instances [ this . instanceNumber ] = null ;
169+ delete this . $el . data ( ) . countdownInstance ;
170+ } ,
171+ setFinalDate : function ( value ) {
172+ this . finalDate = parseDateString ( value ) ;
173+ } ,
174+ update : function ( ) {
175+ if ( this . $el . closest ( "html" ) . length === 0 ) {
176+ this . remove ( ) ;
177+ return ;
178+ }
179+ var hasEventsAttached = $ . _data ( this . el , "events" ) !== undefined , now = new Date ( ) , newTotalSecsLeft ;
180+ newTotalSecsLeft = this . finalDate . getTime ( ) - now . getTime ( ) ;
181+
182+ newTotalSecsLeft = Math . ceil ( newTotalSecsLeft / 1e3 ) ;
183+ newTotalSecsLeft = ! this . options . elapse && newTotalSecsLeft < 0 ? 0 : Math . abs ( newTotalSecsLeft ) ;
184+ if ( this . totalSecsLeft === newTotalSecsLeft || ! hasEventsAttached ) {
185+ return ;
186+ } else {
187+ this . totalSecsLeft = newTotalSecsLeft ;
188+ }
189+ this . elapsed = now >= this . finalDate ;
190+ this . offset = {
191+ seconds : this . totalSecsLeft % 60 ,
192+ minutes : Math . floor ( this . totalSecsLeft / 60 ) % 60 ,
193+ hours : Math . floor ( this . totalSecsLeft / 60 / 60 ) % 24 ,
194+ days : Math . floor ( this . totalSecsLeft / 60 / 60 / 24 ) % 7 ,
195+ daysToWeek : Math . floor ( this . totalSecsLeft / 60 / 60 / 24 ) % 7 ,
196+ daysToMonth : Math . floor ( this . totalSecsLeft / 60 / 60 / 24 % 30.4368 ) ,
197+ totalDays : Math . floor ( this . totalSecsLeft / 60 / 60 / 24 ) ,
198+ weeks : Math . floor ( this . totalSecsLeft / 60 / 60 / 24 / 7 ) ,
199+ months : Math . floor ( this . totalSecsLeft / 60 / 60 / 24 / 30.4368 ) ,
200+ years : Math . abs ( this . finalDate . getFullYear ( ) - now . getFullYear ( ) )
201+ } ;
202+ if ( ! this . options . elapse && this . totalSecsLeft === 0 ) {
203+ this . stop ( ) ;
204+ this . dispatchEvent ( "finish" ) ;
205+ } else {
206+ this . dispatchEvent ( "update" ) ;
207+ }
208+ } ,
209+ dispatchEvent : function ( eventName ) {
210+ var event = $ . Event ( eventName + ".countdown" ) ;
211+ event . finalDate = this . finalDate ;
212+ event . elapsed = this . elapsed ;
213+ event . offset = $ . extend ( { } , this . offset ) ;
214+ event . strftime = strftime ( this . offset ) ;
215+ this . $el . trigger ( event ) ;
216+ }
217+ } ) ;
218+ $ . fn . countdown = function ( ) {
219+ var argumentsArray = Array . prototype . slice . call ( arguments , 0 ) ;
220+ return this . each ( function ( ) {
221+ var instanceNumber = $ ( this ) . data ( "countdown-instance" ) ;
222+ if ( instanceNumber !== undefined ) {
223+ var instance = instances [ instanceNumber ] , method = argumentsArray [ 0 ] ;
224+ if ( Countdown . prototype . hasOwnProperty ( method ) ) {
225+ instance [ method ] . apply ( instance , argumentsArray . slice ( 1 ) ) ;
226+ } else if ( String ( method ) . match ( / ^ [ $ A - Z _ ] [ 0 - 9 A - Z _ $ ] * $ / i) === null ) {
227+ instance . setFinalDate . call ( instance , method ) ;
228+ instance . start ( ) ;
229+ } else {
230+ $ . error ( "Method %s does not exist on jQuery.countdown" . replace ( / \% s / gi, method ) ) ;
231+ }
232+ } else {
233+ new Countdown ( this , argumentsArray [ 0 ] , argumentsArray [ 1 ] ) ;
234+ }
235+ } ) ;
236+ } ;
237+ } ) ;
0 commit comments