jquery.countTo.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. (function (factory) {
  2. if (typeof define === 'function' && define.amd) {
  3. // AMD
  4. define(['jquery'], factory);
  5. } else if (typeof exports === 'object') {
  6. // CommonJS
  7. factory(require('jquery'));
  8. } else {
  9. // Browser globals
  10. factory(jQuery);
  11. }
  12. }(function ($) {
  13. var CountTo = function (element, options) {
  14. this.$element = $(element);
  15. this.options = $.extend({}, CountTo.DEFAULTS, this.dataOptions(), options);
  16. this.init();
  17. };
  18. CountTo.DEFAULTS = {
  19. from: 0, // the number the element should start at
  20. to: 0, // the number the element should end at
  21. speed: 1000, // how long it should take to count between the target numbers
  22. refreshInterval: 100, // how often the element should be updated
  23. decimals: 0, // the number of decimal places to show
  24. formatter: formatter, // handler for formatting the value before rendering
  25. onUpdate: null, // callback method for every time the element is updated
  26. onComplete: null // callback method for when the element finishes updating
  27. };
  28. CountTo.prototype.init = function () {
  29. this.value = this.options.from;
  30. this.loops = Math.ceil(this.options.speed / this.options.refreshInterval);
  31. this.loopCount = 0;
  32. this.increment = (this.options.to - this.options.from) / this.loops;
  33. };
  34. CountTo.prototype.dataOptions = function () {
  35. var options = {
  36. from: this.$element.data('from'),
  37. to: this.$element.data('to'),
  38. speed: this.$element.data('speed'),
  39. refreshInterval: this.$element.data('refresh-interval'),
  40. decimals: this.$element.data('decimals')
  41. };
  42. var keys = Object.keys(options);
  43. for (var i in keys) {
  44. var key = keys[i];
  45. if (typeof(options[key]) === 'undefined') {
  46. delete options[key];
  47. }
  48. }
  49. return options;
  50. };
  51. CountTo.prototype.update = function () {
  52. this.value += this.increment;
  53. this.loopCount++;
  54. this.render();
  55. if (typeof(this.options.onUpdate) == 'function') {
  56. this.options.onUpdate.call(this.$element, this.value);
  57. }
  58. if (this.loopCount >= this.loops) {
  59. clearInterval(this.interval);
  60. this.value = this.options.to;
  61. if (typeof(this.options.onComplete) == 'function') {
  62. this.options.onComplete.call(this.$element, this.value);
  63. }
  64. }
  65. };
  66. CountTo.prototype.render = function () {
  67. var formattedValue = this.options.formatter.call(this.$element, this.value, this.options);
  68. this.$element.text(formattedValue);
  69. };
  70. CountTo.prototype.restart = function () {
  71. this.stop();
  72. this.init();
  73. this.start();
  74. };
  75. CountTo.prototype.start = function () {
  76. this.stop();
  77. this.render();
  78. this.interval = setInterval(this.update.bind(this), this.options.refreshInterval);
  79. };
  80. CountTo.prototype.stop = function () {
  81. if (this.interval) {
  82. clearInterval(this.interval);
  83. }
  84. };
  85. CountTo.prototype.toggle = function () {
  86. if (this.interval) {
  87. this.stop();
  88. } else {
  89. this.start();
  90. }
  91. };
  92. function formatter(value, options) {
  93. return value.toFixed(options.decimals);
  94. }
  95. $.fn.countTo = function (option) {
  96. return this.each(function () {
  97. var $this = $(this);
  98. var data = $this.data('countTo');
  99. var init = !data || typeof(option) === 'object';
  100. var options = typeof(option) === 'object' ? option : {};
  101. var method = typeof(option) === 'string' ? option : 'start';
  102. if (init) {
  103. if (data) data.stop();
  104. $this.data('countTo', data = new CountTo(this, options));
  105. }
  106. data[method].call(data);
  107. });
  108. };
  109. }));