Template:Shenzhen SFLS/js/jquery.countTo

(function (factory) {

   if (typeof define === 'function' && define.amd) {
       // AMD
       define(['jquery'], factory);
   } else if (typeof exports === 'object') {
       // CommonJS
       factory(require('jquery'));
   } else {
       // Browser globals
       factory(jQuery);
   }

}(function ($) {

 var CountTo = function (element, options) {
   this.$element = $(element);
   this.options  = $.extend({}, CountTo.DEFAULTS, this.dataOptions(), options);
   this.init();
 };
 CountTo.DEFAULTS = {
   from: 0,               // the number the element should start at
   to: 0,                 // the number the element should end at
   speed: 1000,           // how long it should take to count between the target numbers
   refreshInterval: 100,  // how often the element should be updated
   decimals: 0,           // the number of decimal places to show
   formatter: formatter,  // handler for formatting the value before rendering
   onUpdate: null,        // callback method for every time the element is updated
   onComplete: null       // callback method for when the element finishes updating
 };
 CountTo.prototype.init = function () {
   this.value     = this.options.from;
   this.loops     = Math.ceil(this.options.speed / this.options.refreshInterval);
   this.loopCount = 0;
   this.increment = (this.options.to - this.options.from) / this.loops;
 };
 CountTo.prototype.dataOptions = function () {
   var options = {
     from:            this.$element.data('from'),
     to:              this.$element.data('to'),
     speed:           this.$element.data('speed'),
     refreshInterval: this.$element.data('refresh-interval'),
     decimals:        this.$element.data('decimals')
   };
   var keys = Object.keys(options);
   for (var i in keys) {
     var key = keys[i];
     if (typeof(options[key]) === 'undefined') {
       delete options[key];
     }
   }
   return options;
 };
 CountTo.prototype.update = function () {
   this.value += this.increment;
   this.loopCount++;
   this.render();
   if (typeof(this.options.onUpdate) == 'function') {
     this.options.onUpdate.call(this.$element, this.value);
   }
   if (this.loopCount >= this.loops) {
     clearInterval(this.interval);
     this.value = this.options.to;
     if (typeof(this.options.onComplete) == 'function') {
       this.options.onComplete.call(this.$element, this.value);
     }
   }
 };
 CountTo.prototype.render = function () {
   var formattedValue = this.options.formatter.call(this.$element, this.value, this.options);
   this.$element.text(formattedValue);
 };
 CountTo.prototype.restart = function () {
   this.stop();
   this.init();
   this.start();
 };
 CountTo.prototype.start = function () {
   this.stop();
   this.render();
   this.interval = setInterval(this.update.bind(this), this.options.refreshInterval);
 };
 CountTo.prototype.stop = function () {
   if (this.interval) {
     clearInterval(this.interval);
   }
 };
 CountTo.prototype.toggle = function () {
   if (this.interval) {
     this.stop();
   } else {
     this.start();
   }
 };
 function formatter(value, options) {
   return value.toFixed(options.decimals);
 }
 $.fn.countTo = function (option) {
   return this.each(function () {
     var $this   = $(this);
     var data    = $this.data('countTo');
     var init    = !data || typeof(option) === 'object';
     var options = typeof(option) === 'object' ? option : {};
     var method  = typeof(option) === 'string' ? option : 'start';
     if (init) {
       if (data) data.stop();
       $this.data('countTo', data = new CountTo(this, options));
     }
     data[method].call(data);
   });
 };

}));