ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

countup.js (10516B)


      1 (function (root, factory) {
      2     if (typeof define === 'function' && define.amd) {
      3         define(factory);
      4     } else if (typeof exports === 'object') {
      5         module.exports = factory(require, exports, module);
      6     } else {
      7         root.CountUp = factory();
      8     }
      9 }(this, function (require, exports, module) {
     10 
     11     /*
     12 
     13         countUp.js
     14         by @inorganik
     15 
     16     */
     17 
     18 // target = id of html element or var of previously selected html element where counting occurs
     19 // startVal = the value you want to begin at
     20 // endVal = the value you want to arrive at
     21 // decimals = number of decimal places, default 0
     22 // duration = duration of animation in seconds, default 2
     23 // options = optional object of options (see below)
     24 
     25     var CountUp = function (target, startVal, endVal, decimals, duration, options) {
     26 
     27         var self = this;
     28         self.version = function () {
     29             return '1.9.1';
     30         };
     31 
     32         // default options
     33         self.options = {
     34             useEasing: true, // toggle easing
     35             useGrouping: true, // 1,000,000 vs 1000000
     36             separator: ',', // character to use as a separator
     37             decimal: '.', // character to use as a decimal
     38             easingFn: easeOutExpo, // optional custom easing function, default is Robert Penner's easeOutExpo
     39             formattingFn: formatNumber, // optional custom formatting function, default is formatNumber above
     40             prefix: '', // optional text before the result
     41             suffix: '', // optional text after the result
     42             numerals: [], // optionally pass an array of custom numerals for 0-9
     43             onUpdate: false
     44         };
     45 
     46         // extend default options with passed options object
     47         if (options && typeof options === 'object') {
     48             for (var key in self.options) {
     49                 if (options.hasOwnProperty(key) && options[key] !== null) {
     50                     self.options[key] = options[key];
     51                 }
     52             }
     53         }
     54 
     55         if (self.options.separator === '') self.options.useGrouping = false;
     56 
     57         // make sure requestAnimationFrame and cancelAnimationFrame are defined
     58         // polyfill for browsers without native support
     59         // by Opera engineer Erik Möller
     60         var lastTime = 0;
     61         var vendors = ['webkit', 'moz', 'ms', 'o'];
     62         for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
     63             window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
     64             window.cancelAnimationFrame =
     65                 window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
     66         }
     67         if (!window.requestAnimationFrame) {
     68             window.requestAnimationFrame = function (callback, element) {
     69                 var currTime = new Date().getTime();
     70                 var timeToCall = Math.max(0, 16 - (currTime - lastTime));
     71                 var id = window.setTimeout(function () {
     72                         callback(currTime + timeToCall);
     73                     },
     74                     timeToCall);
     75                 lastTime = currTime + timeToCall;
     76                 return id;
     77             };
     78         }
     79         if (!window.cancelAnimationFrame) {
     80             window.cancelAnimationFrame = function (id) {
     81                 clearTimeout(id);
     82             };
     83         }
     84 
     85         function formatNumber(num) {
     86             num = num.toFixed(self.decimals);
     87             num += '';
     88             var x, x1, x2, rgx;
     89             x = num.split('.');
     90             x1 = x[0];
     91             x2 = x.length > 1 ? self.options.decimal + x[1] : '';
     92             rgx = /(\d+)(\d{3})/;
     93             if (self.options.useGrouping) {
     94                 while (rgx.test(x1)) {
     95                     x1 = x1.replace(rgx, '$1' + self.options.separator + '$2');
     96                 }
     97             }
     98             // optional numeral substitution
     99             if (self.options.numerals.length) {
    100                 x1 = x1.replace(/[0-9]/g, function (w) {
    101                     return self.options.numerals[+w];
    102                 })
    103                 x2 = x2.replace(/[0-9]/g, function (w) {
    104                     return self.options.numerals[+w];
    105                 })
    106             }
    107             return self.options.prefix + x1 + x2 + self.options.suffix;
    108         }
    109 
    110         // Robert Penner's easeOutExpo
    111         function easeOutExpo(t, b, c, d) {
    112             return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
    113         }
    114 
    115         function ensureNumber(n) {
    116             return (typeof n === 'number' && !isNaN(n));
    117         }
    118 
    119         self.initialize = function () {
    120             if (self.initialized) return true;
    121 
    122             self.error = '';
    123             self.d = (typeof target === 'string') ? document.getElementById(target) : target;
    124             if (!self.d) {
    125                 self.error = '[CountUp] target is null or undefined'
    126                 return false;
    127             }
    128             self.startVal = Number(startVal);
    129             self.endVal = Number(endVal);
    130             // error checks
    131             if (ensureNumber(self.startVal) && ensureNumber(self.endVal)) {
    132                 self.decimals = Math.max(0, decimals || 0);
    133                 self.dec = Math.pow(10, self.decimals);
    134                 self.duration = Number(duration) * 1000 || 4000;
    135                 self.countDown = (self.startVal > self.endVal);
    136                 self.frameVal = self.startVal;
    137                 self.initialized = true;
    138                 return true;
    139             }
    140             else {
    141                 self.error = '[CountUp] startVal (' + startVal + ') or endVal (' + endVal + ') is not a number';
    142                 return false;
    143             }
    144         };
    145 
    146         // Print value to target
    147         self.printValue = function (value) {
    148             var result = self.options.formattingFn(value);
    149             // var sizeKeeper = self.options.formattingFn(endVal);
    150 
    151             // sizeKeeper = '<span style="visibility: hidden;display: block;line-height: 0px;height: 0px;overflow: hidden;">'+sizeKeeper+'</span>';
    152 
    153             // result = sizeKeeper+result;
    154 
    155             if (self.d.tagName === 'INPUT') {
    156                 this.d.value = result;
    157             }
    158             else if (self.d.tagName === 'text' || self.d.tagName === 'tspan') {
    159                 this.d.textContent = result;
    160             }
    161             else {
    162                 this.d.innerHTML = result;
    163             }
    164         };
    165 
    166         self.count = function (timestamp) {
    167 
    168             if (!self.startTime) {
    169                 self.startTime = timestamp;
    170             }
    171 
    172             self.timestamp = timestamp;
    173             var progress = timestamp - self.startTime;
    174             self.remaining = self.duration - progress;
    175 
    176             // to ease or not to ease
    177             if (self.options.useEasing) {
    178                 if (self.countDown) {
    179                     self.frameVal = self.startVal - self.options.easingFn(progress, 0, self.startVal - self.endVal, self.duration);
    180                 } else {
    181                     self.frameVal = self.options.easingFn(progress, self.startVal, self.endVal - self.startVal, self.duration);
    182                 }
    183             } else {
    184                 if (self.countDown) {
    185                     self.frameVal = self.startVal - ((self.startVal - self.endVal) * (progress / self.duration));
    186                 } else {
    187                     self.frameVal = self.startVal + (self.endVal - self.startVal) * (progress / self.duration);
    188                 }
    189             }
    190 
    191             // don't go past endVal since progress can exceed duration in the last frame
    192             if (self.countDown) {
    193                 self.frameVal = (self.frameVal < self.endVal) ? self.endVal : self.frameVal;
    194             } else {
    195                 self.frameVal = (self.frameVal > self.endVal) ? self.endVal : self.frameVal;
    196             }
    197 
    198             // decimal
    199             self.frameVal = Math.round(self.frameVal * self.dec) / self.dec;
    200 
    201             // format and print value
    202             self.printValue(self.frameVal);
    203 
    204             if (self.options.onUpdate) {
    205                 self.options.onUpdate(self.frameVal);
    206             }
    207 
    208             // whether to continue
    209             if (progress < self.duration) {
    210                 self.rAF = requestAnimationFrame(self.count);
    211             } else {
    212                 if (self.callback) self.callback();
    213             }
    214         };
    215         // start your animation
    216         self.start = function (callback) {
    217             if (!self.initialize()) return;
    218             self.callback = callback;
    219             self.rAF = requestAnimationFrame(self.count);
    220         };
    221         // toggles pause/resume animation
    222         self.pauseResume = function () {
    223             if (!self.paused) {
    224                 self.paused = true;
    225                 cancelAnimationFrame(self.rAF);
    226             } else {
    227                 self.paused = false;
    228                 delete self.startTime;
    229                 self.duration = self.remaining;
    230                 self.startVal = self.frameVal;
    231                 requestAnimationFrame(self.count);
    232             }
    233         };
    234         // reset to startVal so animation can be run again
    235         self.reset = function () {
    236             self.paused = false;
    237             delete self.startTime;
    238             self.initialized = false;
    239             if (self.initialize()) {
    240                 cancelAnimationFrame(self.rAF);
    241                 self.printValue(self.startVal);
    242             }
    243         };
    244         // pass a new endVal and start animation
    245         self.update = function (newEndVal) {
    246             if (!self.initialize()) return;
    247             newEndVal = Number(newEndVal);
    248             if (!ensureNumber(newEndVal)) {
    249                 self.error = '[CountUp] update() - new endVal is not a number: ' + newEndVal;
    250                 return;
    251             }
    252             self.error = '';
    253             if (newEndVal === self.frameVal) return;
    254             cancelAnimationFrame(self.rAF);
    255             self.paused = false;
    256             delete self.startTime;
    257             self.startVal = self.frameVal;
    258             self.endVal = newEndVal;
    259             self.countDown = (self.startVal > self.endVal);
    260             self.rAF = requestAnimationFrame(self.count);
    261         };
    262 
    263         // format startVal on initialization
    264         if (self.initialize()) self.printValue(self.startVal);
    265     };
    266 
    267     return CountUp;
    268 
    269 }));