Blame view

js/jquery.countTo.js 3.67 KB
4569bbd1   liuqimichale   init website
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  (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);
      });
    };
  }));