1/** 2 * jQuery Countdown 3 * 4 * Provides a javascript countdown timer based on the data-countdown attribute or by 5 * passing a schedule of events via options. It will default to data-countdown if the 6 * attribute is present, then the next day in a schedule if you pass one, and 7 * then it will fail silently as last result if neither of these are present. 8 * 9 * @author Kaleb Heitzman <[email protected]> 10 * @website http://github.com/kaleblex/jquery-countdown.js 11 * @created March 12, 2013 12 * 13 */ 14; 15(function($) { 16 17 /** 18 * Countdown 19 */ 20 $.fn.countdown = function(options) { 21 22 // default options 23 defaults = { 24 schedule: null, 25 datetime: null, 26 showYears: false, 27 showDays: true, 28 showHours: true, 29 showMinutes: true, 30 showSeconds: true, 31 showOnZeroYears: false, 32 showOnZeroDays: true, 33 showOnZeroHours: true, 34 showOnZeroMinutes: true, 35 showOnZeroSeconds: true, 36 unixFormat: false 37 }; 38 39 /** 40 * Extend the options 41 */ 42 var options = $.extend({ 43 timerCallback: function(options) {}, 44 initCallback: function(options) {}, 45 zeroCallback: function(options) {} 46 }, defaults, options); 47 48 /** 49 * Check for a specified datetime and use ternary to apply value 50 */ 51 options.datetime = $(this).attr('data-countdown') ? $(this).attr('data-countdown') : null; 52 53 /** 54 * Run Countdown on Element 55 */ 56 return this.each(function() { 57 58 /** 59 * Calculate Upcoming Day 60 * 61 * Calculate what the upcoming day is based on a combination of schedules 62 * and date-time attribute. If a date-time attribute is used, it should be 63 * used first. If a schedule is passed, calculate the date and time based 64 * on the schedule 65 */ 66 var upcomingDate = scheduler(options); 67 68 /** 69 * Get the element to update 70 */ 71 var element = $(this); 72 73 /** 74 * Start the timer 75 * 76 * The time will update the element every one second. 77 */ 78 var intervalHandle = setInterval(function() { 79 // get the timerObject 80 var timerObject = makeTimer(upcomingDate, options); 81 // set the timerObject in options 82 options.timerObject = timerObject; 83 // create the HTML 84 var timerHtml = htmlParser(timerObject, options); 85 /** 86 * Update the HTML for the counter 87 */ 88 updateElement(element, timerHtml, options); 89 /** 90 * Check for zeroCallback 91 */ 92 if (timerObject.timeLeft <= 0) { 93 /** 94 * Clear the interval because it's no longer needed 95 */ 96 clearInterval(intervalHandle); 97 /** 98 * Call the zeroCallback to see if there is anything to perform. 99 */ 100 options.zeroCallback(options); 101 } 102 /** 103 * call the callback timer 104 */ 105 else { 106 options.timerCallback(options); 107 } 108 }, 1000); 109 110 }); 111 112 /** 113 * An overball callback 114 */ 115 options.initCallback.call(this); 116 117 }; 118 119 /** 120 * Update the element 121 * 122 * Updates the html inside of the element that plugin is attached to based on 123 * schedule or date-time attr. 124 */ 125 var updateElement = function(element, html, options) { 126 // update the html 127 $(element).html(html); 128 } 129 130 /** 131 * Scheduler 132 * 133 * Returns Human Readable date string based on a combination of scheduel, 134 * date-time attr, and current datetime. 135 */ 136 var scheduler = function(options) { 137 138 /** 139 * Check for registerd data-countdown attr. 140 * 141 * If the date-time attr is filled in, skip schedule checking and return 142 * the passed data-countdown directly. 143 */ 144 if (options.datetime != null) { 145 return options.datetime; 146 } 147 148 /** 149 * Set a blank array to store date and time sin 150 */ 151 var upcomingDates = []; 152 153 /** 154 * Process the schedule 155 */ 156 for (var day in options.schedule) { 157 // get the next upcoming date 158 var nextDate = nextDayByName(day); 159 // get the time foreach each future date and push it to upcomingDates 160 for (var time in options.schedule[day]) { 161 // create a time string to push onto the upcomingDates array 162 var timeString = nextDate + " " + options.schedule[day][time]; 163 // push the string onto the array 164 upcomingDates.push(timeString); 165 } 166 } 167 168 /** 169 * Create the schedule to compare times agains 170 */ 171 schedule = []; 172 for (var key in upcomingDates) { 173 schedule.push(new Date(upcomingDates[key])); 174 } 175 176 /** 177 * Create the parsed schedule 178 */ 179 parsedSchedule = []; 180 for (var key in schedule) { 181 parsedSchedule.push(Date.parse(schedule[key]) / 1000); 182 } 183 184 /** 185 * Current Time 186 */ 187 var currentTime = new Date(), 188 currentTimeParsed = Date.parse(currentTime) / 1000; 189 190 191 /** 192 * Build time differences 193 */ 194 timeDifferences = []; 195 for (var key in parsedSchedule) { 196 timeDifferences.push(parsedSchedule[key] - currentTimeParsed); 197 } 198 199 /** 200 * Check for Negative 201 */ 202 timeDifferencesParsed = []; 203 for (key in timeDifferences) { 204 if (timeDifferences[key] > 0) { 205 timeDifferencesParsed.push(timeDifferences[key]); 206 } 207 } 208 209 /** 210 * Get the shortest time and store it in key 211 */ 212 var shortTime = Math.min.apply(null, timeDifferencesParsed); 213 for (var prop in timeDifferences) { 214 if (shortTime == timeDifferences[prop]) { 215 var shortTimeKey = prop; 216 } 217 } 218 219 /** 220 * Get the next scheduled date 221 */ 222 var scheduledDate = upcomingDates[shortTimeKey]; 223 224 /** 225 * Return the scheduledDate if it's not blank. 226 */ 227 if (scheduledDate != "") { 228 return scheduledDate; 229 } 230 231 /** 232 * When all else fails return null 233 */ 234 return null; 235 } 236 237 /** 238 * Make Timer 239 * 240 * This is the timing method. This will be called every 1 second to return 241 * the html needed to be placed in $(this.element) 242 */ 243 var makeTimer = function(upcomingDate, options) { 244 245 246 /** 247 * Check for null upcomingDate 248 */ 249 if (upcomingDate == null) { 250 return ""; 251 } 252 253 /** 254 * Current Time and Date 255 */ 256 var currentTime = new Date(); 257 258 /** 259 * Convert Dates 260 * 261 * Convert the dates to a time string to calculate differences. 262 */ 263 if (options.unixFormat) { 264 var endTime = (upcomingDate / 1000); 265 } else { 266 var endTime = (Date.parse(upcomingDate) / 1000); 267 } 268 269 270 var currentTime = (Date.parse(currentTime) / 1000); 271 272 /** 273 * Time Left 274 */ 275 var timeLeft = endTime - currentTime; 276 277 /** 278 * Set some vars for use
279 */ 280 var years = 0; 281 var days = 0; 282 var hours = 0; 283 var minutes = 0; 284 var seconds = 0; 285 286 /** 287 * Intercept on <= 0 and calculate differences based on timeLeft 288 */ 289 if (timeLeft > 0) { 290 var years = Math.floor((timeLeft / 31536000)); 291 var days = Math.floor((timeLeft / 86400)); 292 var hours = Math.floor((timeLeft - (days * 86400)) / 3600); 293 var minutes = Math.floor((timeLeft - (days * 86400) - (hours * 3600)) / 60); 294 var seconds = Math.floor((timeLeft - (days * 86400) - (hours * 3600) - (minutes * 60))); 295 // adjust days for for more than 1 year 296 if (days > 365) { 297 days = days % 365; 298 } 299 } 300 301 // create the Timer Object 302 var timerObject = { 303 "years": years, 304 "days": days, 305 "hours": hours, 306 "minutes": minutes, 307 "seconds": seconds, 308 "timeLeft": timeLeft 309 }; 310 311 // return Timer Object 312 return timerObject; 313 } 314 315 /** 316 * Parses a Timer Object to create html 317 */ 318 var htmlParser = function(timerObject, options, format) { 319 320 /** 321 * Adjust for zero 322 */ 323 if (timerObject.years < "10") { 324 timerObject.years = "0" + timerObject.years; 325 } 326 if (timerObject.days < "10") { 327 timerObject.days = "0" + timerObject.days; 328 } 329 if (timerObject.hours < "10") { 330 timerObject.hours = "0" + timerObject.hours; 331 } 332 if (timerObject.minutes < "10") { 333 timerObject.minutes = "0" + timerObject.minutes; 334 } 335 if (timerObject.seconds < "10") { 336 timerObject.seconds = "0" + timerObject.seconds; 337 } 338 339 /** 340 * Counter HTML to be passed back to the element 341 */ 342 var counter_years = '<div class="years"><span class="count">' + timerObject.years + '</span><span class="title">Years</span></div>'; 343 var counter_days = '<div class="days"><span class="count">' + timerObject.days + '</span><span class="title">Days</span></div>'; 344 var counter_hours = '<div class="hours"><span class="count">' + timerObject.hours + '</span><span class="title">Hours</span></div>'; 345 var counter_minutes = '<div class="minutes"><span class="count">' + timerObject.minutes + '</span><span class="title">Minutes</span></div>'; 346 var counter_seconds = '<div class="seconds"><span class="count">' + timerObject.seconds + '</span><span class="title">Seconds</span></div>'; 347 348 /** 349 * Setup string inclusions 350 */ 351 var includeYears = false, 352 includeDays = false, 353 includeHours = false, 354 includeMinutes = false, 355 includeSeconds = false; 356 357 /** 358 * Options base show logic 359 */ 360 if (options.showYears) { 361 includeYears = true; 362 } 363 if (options.showDays) { 364 includeDays = true; 365 } 366 if (options.showHours) { 367 includeHours = true; 368 } 369 if (options.showMinutes) { 370 includeMinutes = true; 371 } 372 if (options.showSeconds) { 373 includeSeconds = true; 374 } 375 376 /** 377 * Options showOnZero logic 378 */ 379 if ((!options.showOnZeroYears) && (timerObject.years == "00")) { 380 includeYears = false; 381 } 382 if ((!options.showOnZeroDays) && (timerObject.days == "00")) { 383 includeDays = false; 384 } 385 if ((!options.showOnZeroHours) && (timerObject.hours == "00")) { 386 includeHours = false; 387 } 388 if ((!options.showOnZeroMinutes) && (timerObject.minutes == "00")) { 389 includeMinutes = false; 390 } 391 if ((!options.showOnZeroSeconds) && (timerObject.seconds == "00")) { 392 includeSeconds = false; 393 } 394 395 /** Concatonate string 396 */ 397 var counter_html = ""; 398 399 if (includeYears) { 400 counter_html += counter_years; 401 } 402 if (includeDays) { 403 counter_html += counter_days; 404 } 405 if (includeHours) { 406 counter_html += counter_hours; 407 } 408 if (includeMinutes) { 409 counter_html += counter_minutes; 410 } 411 if (includeSeconds) { 412 counter_html += counter_seconds; 413 } 414 415 /**
416 * Return the Counter HTML 417 */ 418 return counter_html; 419 } 420 421 /** 422 * Next date via schedule or attribute 423 */ 424 var nextDayByName = function(scheduledDay) { 425 426 /** 427 * Date Strings 428 * 429 * Setup some date string to calculate futures events 430 */ 431 var D = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], 432 M = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; 433 434 /** 435 * Get the key for the scheduleDay 436 */ 437 for (var prop in D) { 438 if (scheduledDay == D[prop]) { 439 var whichNext = prop; 440 } 441 } 442 443 /** 444 * Current Date 445 * 446 * This is used to figure out the time difference to a 447 * scheduled or data-countdown reference 448 */ 449 var date = new Date(); 450 451 /** 452 * Time Difference 453 * 454 * Calcuate the difference between the current date and scheduled date. Once 455 * this has been calculated, we'll pass a human readable date back to the 456 * countdown method. 457 */ 458 var dif = date.getDay() - whichNext; 459 dif = dif > 0 ? dif = 7 - dif : -dif; 460 461 date.setDate(date.getDate() + dif); 462 date.setHours(1); //DST pseudobug correction 463 464 // get the day 465 var dd = date.getDate(); 466 dd < 0 ? dd = '0' + dd : null; 467 468 // get the year 469 var yyyy = date.getFullYear(); 470 471 // get the month 472 var mm = M[date.getMonth()]; 473 474 /** 475 * Human Readable Date String 476 * 477 * Set the human readable datestring to be passed back, ex. January 01, 2013 478 */ 479 var nextDatebyDayofWeek = mm + ' ' + dd + ', ' + yyyy; 480 return nextDatebyDayofWeek; 481 } 482 483}(jQuery));
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.