1/*! 2 * Missofis Countdown Timer 3 * 4 * Author: Kemal Yılmaz 5 * Website: http://missofis.com 6 * License: MIT 7 * 8 * @see http://jqueryboilerplate.com/ for this jQuery plugin boilerplate details 9 */ 10;( function ( $, window, document, undefined ) { 11 12 13 14 'use strict'; 15 16 17 18 /** 19 * Plugin defaults 20 */ 21 var PLUGIN_NAME = 'countdown', 22 defaults = { 23 24 from: 180, // 3 minutes (3*60) 25 to: 0, // stop at zero 26 movingUnit: 1000, // 1000 for 1 second increment/decrements 27 timerEnd: undefined, 28 outputPattern: '$day Days $hour : $minute : $second', 29 autostart: true 30 31 }, 32 outputReplacement = new RegExp( '\\$day|\\$hour|\\$minute|\\$second', 'g' ); 33 34 35 36 /** 37 * Plugin constructor 38 * 39 * @param element 40 * 41 * @param options 42 */ 43 function Plugin( element, options ) { 44 45 // set scope vars 46 this.element = element; 47 this.$element = $( element ); 48 49 // set plugin setting 50 this.settings = $.extend( {}, defaults, options ); 51 52 // set name and defaults 53 this._defaults = defaults; 54 this._name = PLUGIN_NAME; 55 56 // set counter direction (counting up/down) and timer current position 57 // _displacement is -1 for count down +1 for counting up, NaN for equality 58 // set current interval id memory 59 // set counter status flag 60 this._displacement = -1 * ( this.settings.from - this.settings.to ) / Math.abs( this.settings.from - this.settings.to ); 61 this._timerAt = this.settings.from; 62 this._intervalId = undefined; 63 this._isCounting = false; 64 65 // call initialize 66 this.init(); 67 68 } 69 70 71 72 /** 73 * Plugin prototype 74 */ 75 Plugin.prototype = { 76 77 /* 78 ------------------------------------------------------------ 79 PLUGIN PUBLIC API 80 ------------------------------------------------------------ 81 */ 82 83 /** 84 * Plugin initialization 85 */ 86 init: function() { 87 88 // initiate timer starting text 89 this._updateTimerText(); 90 91 // check autostart and start counter 92 if( this.settings.autostart ) 93 this._start(); 94 95 }, 96 97 /** 98 * Remove timer javascript counter and delete timer instance from element 99 */ 100 destroy: function() { 101 102 // clear timer 103 window.clearInterval( this._intervalID ); 104 105 // remove plugin instance 106 $.data( this.element, 'plugin_' + PLUGIN_NAME, null ); 107 108 }, 109 110 /** 111 * Resumes counter 112 */ 113 resume: function() { 114 115 // check if counter is running and return 116 if( this._isCounting ) 117 return; 118 119 // start timer 120 this._start(); 121 122 }, 123 124 /** 125 * Pause counter 126 */ 127 pause: function() { 128 129 // check if counter is not running and return 130 if( ! this._isCounting ) 131 return; 132 133 // set counter as stopped 134 this._isCounting = false; 135 136 // clear old interval 137 if( undefined !== this._intervalID ) 138 window.clearInterval( this._intervalID ); 139 140 }, 141 142 143 144 /* 145 ------------------------------------------------------------ 146 PLUGIN PSEUDO-PRIVATE API by "_" NAMING CONVENTION 147 ------------------------------------------------------------ 148 */ 149 150 151 /** 152 * Starts counter 153 */ 154 _start: function() { 155 156 // get plugin 157 var that = this; 158 159 // clear old interval 160 if( undefined !== this._intervalID ) 161 window.clearInterval( this._intervalID ); 162 163 // 164 this._isCounting = true; 165 166 // todo :: do not set an interval for from == to equality 167 168 // 169 this._intervalID = window.setInterval( function() { 170 171 // update timer position (fire event?) 172 that._timerAt += that._displacement; 173 174 // update timer 175 that._update(); 176 177 }, that.settings.movingUnit ); 178 179 }, 180 181 /** 182 * Stop and destroy counter 183 */ 184 _stop: function() { 185 186 // destroy timer 187 this.destroy(); 188 189 // call timerEnd callback if defined 190 if( this.settings.timerEnd && 'function' === typeof this.settings.timerEnd ) { 191 192 // set calback functions scope to jQuery element timer being created 193 // todo :: change context with native element instead of jQuery one 194 this.settings.timerEnd.call( this.$element ); 195 196 } 197 198 }, 199 200 /** 201 * Update counter data 202 */ 203 _update: function() { 204 205 // get plugin 206 var that = this; 207 208 // 209 this._updateTimerText(); 210 211 // 212 if( this._timerAt === this.settings.to || isNaN( this._timerAt ) ) { 213 214 // 215 this._stop(); 216 217 } 218 219 }, 220 221 /** 222 * Update timer via intervalID's 223 */ 224 _updateTimerText: function() { 225 226 // get plugin 227 var that = this; 228 229 // 230 this.$element.text( function( index, text ) { 231 232 // 233 var _parsedStuff = that._parseSeconds( that._timerAt ); 234 235 // 236 var _daysParsed = _parsedStuff.days.toString(), 237 _hoursParsed = _parsedStuff.hours.toString(), 238 _minutesParsed = _parsedStuff.minutes.toString(), 239 _secondsParsed = _parsedStuff.seconds.toString(); 240 241 // check days/hours/minutes/second and change single digit result with 2 digit ones ( 1's to 01's ) 242 if( _parsedStuff.days < 10 ) 243 _daysParsed = '0' + _daysParsed; 244 if( _parsedStuff.hours < 10 ) 245 _hoursParsed = '0' + _hoursParsed; 246 if( _parsedStuff.minutes < 10 ) 247 _minutesParsed = '0' + _minutesParsed; 248 if( _parsedStuff.seconds < 10 ) 249 _secondsParsed = '0' + _secondsParsed; 250 251 // todo :: compare perfromance between length check and regexp replace 252 253 // return parsed timer string 254 return that.settings.outputPattern.replace( outputReplacement, function( match, offset, string ) { 255 256 // 257 switch( match ) { 258 case '$day': 259 return _daysParsed; 260 case '$hour': 261 return _hoursParsed; 262 case '$minute': 263 return _minutesParsed;
264 case '$second': 265 return _secondsParsed; 266 default: 267 return ''; 268 } 269 270 } ); 271 272 } ); 273 274 }, 275 276 /** 277 * Split up seconds to time components (days, hours, minutes, seconds) 278 * 279 * @param seconds 280 */ 281 _parseSeconds: function( seconds ) { 282 283 // handle negative counting 284 seconds = Math.abs( seconds ); 285 286 // 287 var _parsedTime = { 288 days: 0, 289 hours: 0, 290 minutes: Math.floor( seconds / 60 ), 291 seconds: 0 292 }; 293 294 // get days 295 if( seconds >= 86400 ) { 296 297 _parsedTime.days = Math.floor( seconds / 86400 ); 298 _parsedTime.hours = Math.floor( seconds % 86400 / 3600 ); 299 300 } 301 else if( seconds >= 3600 ) 302 _parsedTime.hours = Math.floor( seconds / 3600 ); 303 304 // get minutes 305 if( seconds >= 3600 ) 306 _parsedTime.minutes = Math.floor( seconds % 3600 / 60 ); 307 308 // get seconds 309 _parsedTime.seconds = seconds % 60; 310 311 // return parset numeric values 312 return _parsedTime; 313 314 } 315 316 }; 317 318 319 320 /** 321 * Plugin wrapper 322 */ 323 $.fn[ PLUGIN_NAME ] = function ( options ) { 324 325 // instantiate plugin with chaining enabled if options is omitted or is an object 326 if( undefined === options || 'object' === typeof options ) { 327 328 return this.each( function () { 329 330 // create new plugin in elements data object which plugin is executed from 331 // skip plugin instantiation if plugin set in element's data object already 332 if ( ! $.data( this, 'plugin_' + PLUGIN_NAME ) ) 333 $.data( this, 'plugin_' + PLUGIN_NAME, new Plugin( this, options ) ); 334 335 } ); 336 337 } 338 // capture any public plugin method call 339 // skip pseudo-private function via "_" skipper 340 // skip 'init' call 341 // @see https://github.com/jquery-boilerplate/jquery-boilerplate/wiki/Extending-jQuery-Boilerplate 342 else if( 'string' === typeof options && options[ 0 ] !== '_' && options !== 'init' ) { 343 344 return this.each( function() { 345 346 // get current instance of plugin 347 var instance = $.data( this, 'plugin_' + PLUGIN_NAME ); 348 349 // check if plugin instance is available and instance has target method being called 350 if( instance instanceof Plugin && 'function' === typeof instance[ options ] ) { 351 352 // call the plugin public method 353 instance[ options ].call( instance ); 354 355 } 356 357 } ); 358 359 } 360 361 }; 362 363 364 365} ) ( jQuery, window, document );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.