countdown.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. (function (global) {
  2. "use strict";
  3. // Vanilla JS alternative to $.extend
  4. global.extend = function (obj, extObj) {
  5. obj = obj || {};
  6. if (arguments.length > 2) {
  7. for (var a = 1; a < arguments.length; a++) {
  8. global.extend(obj, arguments[a]);
  9. }
  10. } else {
  11. for (var i in extObj) {
  12. obj[i] = extObj[i];
  13. }
  14. }
  15. return obj;
  16. };
  17. // Countdown constructor
  18. var Countdown = function (conf) {
  19. this.conf = global.extend({
  20. // Dates
  21. dateStart: new Date(),
  22. dateEnd: new Date(new Date().getTime() + (24 * 60 * 60 * 1000)),
  23. // Default elements
  24. selector: ".timer",
  25. // Messages
  26. msgBefore: "倒计时未开始",
  27. msgAfter: "倒计时结束!",
  28. msgPattern: "{days} 天, {hours}:{minutes}:{seconds}",
  29. // Callbacks
  30. onStart: null,
  31. onEnd: null
  32. }, conf);
  33. // Private variables
  34. this.selector = document.querySelectorAll(this.conf.selector);
  35. this.interval = 1000;
  36. this.now = new Date();
  37. this.patterns = [
  38. { pattern: "{years}", secs: 31536000 },
  39. { pattern: "{months}", secs: 2628000 },
  40. { pattern: "{weeks}", secs: 604800 },
  41. { pattern: "{days}", secs: 86400 },
  42. { pattern: "{hours}", secs: 3600 },
  43. { pattern: "{minutes}", secs: 60 },
  44. { pattern: "{seconds}", secs: 1 }
  45. ];
  46. // Doing all the things!
  47. this.init();
  48. };
  49. // Initializing the instance
  50. Countdown.prototype.init = function () {
  51. this.defineInterval();
  52. if (this.now < this.conf.dateEnd && this.now >= this.conf.dateStart) {
  53. this.run();
  54. this.callback("start");
  55. } else {
  56. this.outOfInterval();
  57. }
  58. };
  59. // Running the countdown
  60. Countdown.prototype.run = function () {
  61. var now = this.now.valueOf() / 1000,
  62. tar = this.conf.dateEnd.valueOf() / 1000,
  63. sec = Math.abs(tar - now);
  64. // Vanilla JS alternative to $.proxy
  65. var that = this;
  66. var timer = global.setInterval(function () {
  67. sec--;
  68. if (sec > 0) {
  69. that.display(sec);
  70. } else {
  71. clearInterval(timer);
  72. that.outOfInterval();
  73. that.callback("end");
  74. }
  75. }, this.interval);
  76. this.display(sec);
  77. };
  78. // Displaying the countdown
  79. Countdown.prototype.display = function (sec) {
  80. var output = this.conf.msgPattern;
  81. for (var b = 0; b < this.patterns.length; b++) {
  82. var currentPattern = this.patterns[b];
  83. if (this.conf.msgPattern.indexOf(currentPattern.pattern) !== -1) {
  84. var number = Math.floor(sec / currentPattern.secs);
  85. sec -= number * currentPattern.secs;
  86. var str = (number + "").length === 1 ? ("0" + number) : number + "";
  87. output = output.replace(currentPattern.pattern, str);
  88. }
  89. }
  90. for (var c = 0; c < this.selector.length; c++) {
  91. this.selector[c].innerHTML = output;
  92. }
  93. };
  94. // Defining the interval to be used for refresh
  95. Countdown.prototype.defineInterval = function () {
  96. for (var e = this.patterns.length; e > 0; e--) {
  97. var currentPattern = this.patterns[e - 1];
  98. if (this.conf.msgPattern.indexOf(currentPattern.pattern) !== -1) {
  99. this.interval = currentPattern.secs * 1000;
  100. return;
  101. }
  102. }
  103. };
  104. // Canceling the countdown in case it's over
  105. Countdown.prototype.outOfInterval = function () {
  106. var message = this.now < this.conf.dateStart ? this.conf.msgBefore : this.conf.msgAfter;
  107. for (var d = 0; d < this.selector.length; d++) {
  108. this.selector[d].innerHTML = message;
  109. }
  110. };
  111. // Dealing with events and callbacks
  112. Countdown.prototype.callback = function (event) {
  113. event = event.capitalize();
  114. // onStart callback
  115. if (typeof this.conf["on" + event] === "function") {
  116. this.conf["on" + event]();
  117. }
  118. // Triggering a jQuery event if jQuery is loaded
  119. if (typeof global.jQuery !== "undefined") {
  120. global.jQuery(this.conf.selector).trigger("countdown" + event);
  121. }
  122. };
  123. // Adding a capitalize method to String
  124. String.prototype.capitalize = function () {
  125. return this.charAt(0).toUpperCase() + this.slice(1);
  126. };
  127. global.Countdown = Countdown;
  128. }(window));
  129. //// Initializing two countdowns
  130. //var tomorrow = new Countdown(); // All defaults
  131. //var happyNewYear = new Countdown({ // Custom
  132. // selector: '.new-year',
  133. // dateEnd: new Date('2025/01/01'),
  134. // msgPattern: 'Happy new year in {days} days, {hours} hours, {minutes} minutes !',
  135. // onStart: function () {
  136. // console.log('Starting countdown');
  137. // },
  138. // onEnd: function () {
  139. // console.log('Ending countdown');
  140. // }
  141. //});