jquery.countTo.js 3.4 KB

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