From 0353d8f50d4738c09548c408f04b6239542b38ae Mon Sep 17 00:00:00 2001 From: Jamie Perkins Date: Fri, 22 Apr 2016 17:58:34 -0600 Subject: [PATCH] remove redundant postFormatter (use optional formattingFn instead), fix bug, clean up code --- README.md | 36 ++++----- angular-countUp.js | 48 ++++++------ contributing.md | 26 ------- countUp.js | 142 ++++++++++++++---------------------- dist/angular-countUp.js | 48 ++++++------ dist/angular-countUp.min.js | 2 +- dist/countUp.js | 142 ++++++++++++++---------------------- dist/countUp.min.js | 9 +-- index.html | 9 ++- 9 files changed, 183 insertions(+), 279 deletions(-) delete mode 100644 contributing.md diff --git a/README.md b/README.md index e21cd3c..dfe16e6 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,10 @@ CountUp.js supports all browsers. Simply include the countUp.js file in your project or install via npm or bower using the package name `countup.js`. -To contribute, please [read more here](contributing.md). +Before making a pull request, please [read this](#contributing). MIT License. ## Angular directive -Included is an angular module. Use the count-up attribute to quickly create an animation. It also integrates nicely with the angular-scroll-spy directive. The Angular directive only requires an `end-val` attribute, but will also accept `start-val`, `duration`, and `decimals`. `id` is not needed. You must include both countUp.js and the module to use the angular directive. **[Check out the angular demo](http://inorganik.github.io/angular-scroll-spy).** +Included is an angular module. Use the count-up attribute to quickly create an animation. It also integrates nicely with the angular-scroll-spy directive. The Angular directive only requires an `end-val` attribute, but will also accept `start-val`, `duration`, `decimals`, and `options`. `id` is not needed. You must include both countUp.js and the module to use the angular directive. **[Check out the angular demo](http://inorganik.github.io/angular-scroll-spy).** ## WordPress plugin If you want a quick and easy way to use this on your WordPress site, try this plugin by [@4DMedia](https://twitter.com/4dMedia): [https://wordpress.org/plugins/countup-js/](https://wordpress.org/plugins/countup-js/) @@ -26,7 +26,7 @@ Params: - `endVal` = the value you want to arrive at - `decimals` = (optional) number of decimal places in number, default 0 - `duration` = (optional) duration in seconds, default 2 -- `options` = (see demo, optional) formatting/easing options object +- `options` = (optional, see demo) formatting/easing options object Decimals, duration, and options can be left out to use the default values. @@ -46,10 +46,10 @@ numAnim.start(function() { }) ``` #### Animating to large numbers -For large numbers, since the CountUp class has a long way to go in just a few seconds, the animation seems to abruptly stop. The solution is to subtract 100 from your endVal, then use the callback to invoke the `update` method which completes the animation with the same duration with a difference of only 100 to animate: +For large numbers, since CountUp has a long way to go in just a few seconds, the animation seems to abruptly stop. The solution is to subtract 100 from your `endVal`, then use the callback to invoke the `update` method which completes the animation with the same duration with a difference of only 100 to animate: ```js var endVal = 9645.72; -var numAnim = new CountUp("targetElem", 0, endVal - 100); +var numAnim = new CountUp("targetElem", 0, endVal - 100, duration/2); numAnim.start(function() { numAnim.update(endVal); }); @@ -64,7 +64,7 @@ Width angular-scroll-spy:

``` -## Other methods: +#### Other methods: Toggle pause/resume: ```js @@ -84,24 +84,20 @@ var someValue = 1337; numAnim.update(someValue); ``` -## Custom easing: +#### Custom easing: -You can apply your custom easing function, which will receive standard 4 parameters necessary -to calculate Bezier curve: +You can optionally apply your custom easing function, which will receive 4 parameters necessary to calculate a Bezier curve: - `t` (the current time); - `b` (the beginning value); -- `c` (the change between the beginning and destination value); +- `c` (the difference between the beginning and destination value); - `d` (the total time of the tween). -So, for instance, you could use bodies of easing functions from jQuery's [easing plugin](http://gsgd.co.uk/sandbox/jquery/easing/). -Pass in the body of the function and you're good to go :) +You could use any of Robert Penner's [easing functions](https://github.com/danro/jquery-easing/blob/master/jquery.easing.js). Just avoid using "bouncy" functions, because they cause counting in both directions -Just don't use any "bouncy" functions, as they tend to cause issues and are controlled not to exceed max value by the library. +If you don't specify a custom easing function, CountUp uses the default `easeOutExpo`. -If you don't specify a custom easing closure function, the plugin will fall back to the default `easeOutExpo`. - -#### Example: +Example: ```js var easeOutCubic = function(t, b, c, d) { @@ -116,5 +112,11 @@ var demo = new CountUp("myTargetElement", 24.02, 94.62, 2, 2.5, options); demo.start(); ``` +## Contributing + +Before you make a pull request, please be sure to follow these super simple instructions: -## MIT License +1. Do your work on the `countUp.js` and/or `angular-countUp.js` files in the root directory. +2. In Terminal, `cd` to the `countUp.js` directory. +3. Run `npm install`, which installs gulp and its dependencies. +4. Run `gulp`, which copies and minifies the .js files to the `dist` folder. diff --git a/angular-countUp.js b/angular-countUp.js index ee08bbb..f0e55bb 100644 --- a/angular-countUp.js +++ b/angular-countUp.js @@ -20,7 +20,7 @@ * count-up attribute directive * * @param {number} startVal - (optional) The value you want to begin at, default 0 - * @param {number} endVal - The value you want to arrive at + * @param {number} countUp - The value you want to arrive at * @param {number} duration - (optional) Duration in seconds, default 2. * @param {number} decimals - (optional) Number of decimal places in number, default 0 * @param {boolean} reanimateOnClick - (optional) Config if reanimate on click event, default true. @@ -32,27 +32,24 @@ return { restrict: 'A', scope: { - startVal: "=?", - endVal: "=", - duration: "=?", - decimals: "=?", - reanimateOnClick: "=?", + startVal: '=?', + endVal: '=?', + duration: '=?', + decimals: '=?', + reanimateOnClick: '=?', filter: '@', - options: "=?" + options: '=?' }, link: function ($scope, $el, $attrs) { - var filterFunction = null; + var options = {}; - if($scope.filter != null) { - filterFunction = createFilterFunction(); + if ($scope.filter) { + var filterFunction = createFilterFunction(); + options.formattingFn = filterFunction; } - var options = { - postFormatter: filterFunction - }; - - if ($scope.options != null) { + if ($scope.options) { angular.extend(options, $scope.options); } @@ -65,9 +62,9 @@ return function(value) { var filterCallParams = [value]; Array.prototype.push.apply(filterCallParams, filterParams); - var value = $filter(filterName).apply(null, filterCallParams) + value = $filter(filterName).apply(null, filterCallParams); return value; - } + }; } function createCountUp(sta, end, dec, dur) { @@ -75,7 +72,7 @@ if (isNaN(sta)) sta = Number(sta.match(/[\d\-\.]+/g).join('')); // strip non-numerical characters end = end || 0; if (isNaN(end)) end = Number(end.match(/[\d\-\.]+/g).join('')); // strip non-numerical characters - dur = Number(dur) || 2, + dur = Number(dur) || 2; dec = Number(dec) || 0; // construct countUp @@ -122,19 +119,18 @@ } $scope.$watch('endVal', function (newValue, oldValue) { - if (newValue == null || newValue === oldValue) { + if (newValue === null || newValue === oldValue) { return; } - if(countUp != null) { - countUp.update($scope.endVal); + if (countUp !== null) { + countUp.update($scope.endVal); } else { - countUp = createCountUp($scope.startVal, $scope.endVal, $scope.decimals, $scope.duration); - - animate(); + countUp = createCountUp($scope.startVal, $scope.endVal, $scope.decimals, $scope.duration); + animate(); } - }) + }); } - } + }; }]); })(angular); \ No newline at end of file diff --git a/contributing.md b/contributing.md deleted file mode 100644 index 41394a2..0000000 --- a/contributing.md +++ /dev/null @@ -1,26 +0,0 @@ -# Contributing -Whoa, if you've made it this far you must be committed to helping out! - -## Development -### Build System -GULP! Yes we use [Gulp][2] and yes we love [Node.js][0]. If you haven't installed Node & [Npm][1] please go ahead and do so. ... Great! You must be all setup with Node & Npm. Go ahead and clone down the repo. Once the repo is cloned down, enter the directory and run `npm install`. While we wait know this, after all the node modules have installed you are ready to start development. To build countUp run `gulp build`, to clean the `dist` directory run `gulp clean`. If you're lazy run `gulp` and it will clean and then build countUp. - -Please remember: -- Clean commit messages. -- Fork and then create a feature branch. Then create pull request into [inorganik/countUp.js/tree/master][3]. -- Re-build countUp and include it in your pull request. -- We aren't switching to Grunt, so don't suggest it. -- countUp.js probably should be inside a `lib` directory, but meh. - -#### Inspiration! -![Inspiration](http://ak-hdl.buzzfed.com/static/2014-03/enhanced/webdr03/31/11/enhanced-5041-1396278170-14.jpg) - -#### TLDR; -Deps: [Node.js][0] w/[Npm][1] - -Run `npm install`. Use `gulp` to clean and build countUp. - -[0]: [//nodejs.org] -[1]: [//npmjs.org] -[2]: [http://gulpjs.com] -[3]: [//github.com/inorganik/countUp.js/tree/master] diff --git a/countUp.js b/countUp.js index 157a62b..e79aee2 100644 --- a/countUp.js +++ b/countUp.js @@ -1,8 +1,7 @@ /* countUp.js - (c) 2014-2015 @inorganik - Licensed under the MIT license. + by @inorganik */ @@ -41,59 +40,69 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { }; } - // Robert Penner's easeOutExpo - this.easeOutExpo = function(t, b, c, d) { - return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b; - }; + var self = this; // default options - this.options = { + self.options = { useEasing : true, // toggle easing useGrouping : true, // 1,000,000 vs 1000000 separator : ',', // character to use as a separator decimal : '.', // character to use as a decimal - postFormatter: null, // post formatter to run after internal formatting - easingFn: null, // custom easing closure function, will default to Robert Penner's easeOutExpo - formattingFn: null // custom formatting closure function, in the scenario you need more control over the printed number + easingFn: null, // optional custom easing closure function, default is Robert Penner's easeOutExpo + formattingFn: null // optional custom formatting function, default is self.formatNumber below }; // extend default options with passed options object for (var key in options) { if (options.hasOwnProperty(key)) { - this.options[key] = options[key]; + self.options[key] = options[key]; } } - if (this.options.separator === '') this.options.useGrouping = false; - if (!this.options.prefix) this.options.prefix = ''; - if (!this.options.suffix) this.options.suffix = ''; - // establish easing function - this.options.easingFn = !this.options.easingFn - ? this.easeOutExpo - : this.options.easingFn; - - this.d = (typeof target === 'string') ? document.getElementById(target) : target; - this.startVal = Number(startVal); - this.endVal = Number(endVal); - this.countDown = (this.startVal > this.endVal); - this.frameVal = this.startVal; - this.decimals = Math.max(0, decimals || 0); - this.dec = Math.pow(10, this.decimals); - this.duration = Number(duration) * 1000 || 2000; - var self = this; + if (self.options.separator === '') { self.options.useGrouping = false; } + if (!self.options.prefix) self.options.prefix = ''; + if (!self.options.suffix) self.options.suffix = ''; + + self.d = (typeof target === 'string') ? document.getElementById(target) : target; + self.startVal = Number(startVal); + self.endVal = Number(endVal); + self.countDown = (self.startVal > self.endVal); + self.frameVal = self.startVal; + self.decimals = Math.max(0, decimals || 0); + self.dec = Math.pow(10, self.decimals); + self.duration = Number(duration) * 1000 || 2000; + + self.formatNumber = function(nStr) { + nStr = nStr.toFixed(self.decimals); + nStr += ''; + var x, x1, x2, rgx; + x = nStr.split('.'); + x1 = x[0]; + x2 = x.length > 1 ? self.options.decimal + x[1] : ''; + rgx = /(\d+)(\d{3})/; + if (self.options.useGrouping) { + while (rgx.test(x1)) { + x1 = x1.replace(rgx, '$1' + self.options.separator + '$2'); + } + } + return self.options.prefix + x1 + x2 + self.options.suffix; + }; + // Robert Penner's easeOutExpo + self.easeOutExpo = function(t, b, c, d) { + return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b; + }; + + self.easingFn = self.options.easingFn ? self.options.easingFn : self.easeOutExpo; + self.formattingFn = self.options.formattingFn ? self.options.formattingFn : self.formatNumber; - this.version = function () { return '1.7.0'; }; + self.version = function () { return '1.7.1'; }; // Print value to target - this.printValue = function(value) { - if(self.options.formattingFn) { - var result = self.options.formattingFn(value); - } else { - var result = (!isNaN(value)) ? self.formatNumber(value) : '--'; - } + self.printValue = function(value) { + var result = self.formattingFn(value); - if (self.d.tagName == 'INPUT') { + if (self.d.tagName === 'INPUT') { this.d.value = result; } - else if (self.d.tagName == 'text' || self.d.tagName == 'tspan') { + else if (self.d.tagName === 'text' || self.d.tagName === 'tspan') { this.d.textContent = result; } else { @@ -101,33 +110,20 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { } }; - this.count = function(timestamp) { + self.count = function(timestamp) { - if (!self.startTime) self.startTime = timestamp; + if (!self.startTime) { self.startTime = timestamp; } self.timestamp = timestamp; - var progress = timestamp - self.startTime; self.remaining = self.duration - progress; // to ease or not to ease if (self.options.useEasing) { if (self.countDown) { - self.frameVal = self.startVal - self.options.easingFn.call( - self, - progress, - 0, - self.startVal - self.endVal, - self.duration - ); + self.frameVal = self.startVal - self.easingFn(progress, 0, self.startVal - self.endVal, self.duration); } else { - self.frameVal = self.options.easingFn.call( - self, - progress, - self.startVal, - self.endVal - self.startVal, - self.duration - ); + self.frameVal = self.easingFn(progress, self.startVal, self.endVal - self.startVal, self.duration); } } else { if (self.countDown) { @@ -145,7 +141,7 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { } // decimal - self.frameVal = Math.floor(self.frameVal*self.dec)/self.dec; + self.frameVal = Math.round(self.frameVal*self.dec)/self.dec; // format and print value self.printValue(self.frameVal); @@ -154,17 +150,17 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { if (progress < self.duration) { self.rAF = requestAnimationFrame(self.count); } else { - if (self.callback) self.callback(); + if (self.callback) { self.callback(); } } }; // start your animation - this.start = function(callback) { + self.start = function(callback) { self.callback = callback; self.rAF = requestAnimationFrame(self.count); return false; }; // toggles pause/resume animation - this.pauseResume = function() { + self.pauseResume = function() { if (!self.paused) { self.paused = true; cancelAnimationFrame(self.rAF); @@ -177,7 +173,7 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { } }; // reset to startVal so animation can be run again - this.reset = function() { + self.reset = function() { self.paused = false; delete self.startTime; self.startVal = startVal; @@ -185,7 +181,7 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { self.printValue(self.startVal); }; // pass a new endVal and start animation - this.update = function (newEndVal) { + self.update = function (newEndVal) { cancelAnimationFrame(self.rAF); self.paused = false; delete self.startTime; @@ -194,33 +190,7 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { self.countDown = (self.startVal > self.endVal); self.rAF = requestAnimationFrame(self.count); }; - this.formatNumber = function(nStr) { - var nVal = nStr = nStr.toFixed(self.decimals); - nStr += ''; - var x, x1, x2, rgx; - x = nStr.split('.'); - x1 = x[0]; - x2 = x.length > 1 ? self.options.decimal + x[1] : ''; - rgx = /(\d+)(\d{3})/; - if (self.options.useGrouping) { - while (rgx.test(x1)) { - x1 = x1.replace(rgx, '$1' + self.options.separator + '$2'); - } - } - var value = self.options.prefix + x1 + x2 + self.options.suffix; - if (typeof self.options.postFormatter === 'function') { - value = self.options.postFormatter(value, nVal); - } - return value; - }; // format startVal on initialization self.printValue(self.startVal); }; - -// Example: -// var numAnim = new countUp("SomeElementYouWantToAnimate", 0, 99.99, 2, 2.5); -// numAnim.start(); -// numAnim.update(135); -// with optional callback: -// numAnim.start(someMethodToCallOnComplete); diff --git a/dist/angular-countUp.js b/dist/angular-countUp.js index ee08bbb..f0e55bb 100644 --- a/dist/angular-countUp.js +++ b/dist/angular-countUp.js @@ -20,7 +20,7 @@ * count-up attribute directive * * @param {number} startVal - (optional) The value you want to begin at, default 0 - * @param {number} endVal - The value you want to arrive at + * @param {number} countUp - The value you want to arrive at * @param {number} duration - (optional) Duration in seconds, default 2. * @param {number} decimals - (optional) Number of decimal places in number, default 0 * @param {boolean} reanimateOnClick - (optional) Config if reanimate on click event, default true. @@ -32,27 +32,24 @@ return { restrict: 'A', scope: { - startVal: "=?", - endVal: "=", - duration: "=?", - decimals: "=?", - reanimateOnClick: "=?", + startVal: '=?', + endVal: '=?', + duration: '=?', + decimals: '=?', + reanimateOnClick: '=?', filter: '@', - options: "=?" + options: '=?' }, link: function ($scope, $el, $attrs) { - var filterFunction = null; + var options = {}; - if($scope.filter != null) { - filterFunction = createFilterFunction(); + if ($scope.filter) { + var filterFunction = createFilterFunction(); + options.formattingFn = filterFunction; } - var options = { - postFormatter: filterFunction - }; - - if ($scope.options != null) { + if ($scope.options) { angular.extend(options, $scope.options); } @@ -65,9 +62,9 @@ return function(value) { var filterCallParams = [value]; Array.prototype.push.apply(filterCallParams, filterParams); - var value = $filter(filterName).apply(null, filterCallParams) + value = $filter(filterName).apply(null, filterCallParams); return value; - } + }; } function createCountUp(sta, end, dec, dur) { @@ -75,7 +72,7 @@ if (isNaN(sta)) sta = Number(sta.match(/[\d\-\.]+/g).join('')); // strip non-numerical characters end = end || 0; if (isNaN(end)) end = Number(end.match(/[\d\-\.]+/g).join('')); // strip non-numerical characters - dur = Number(dur) || 2, + dur = Number(dur) || 2; dec = Number(dec) || 0; // construct countUp @@ -122,19 +119,18 @@ } $scope.$watch('endVal', function (newValue, oldValue) { - if (newValue == null || newValue === oldValue) { + if (newValue === null || newValue === oldValue) { return; } - if(countUp != null) { - countUp.update($scope.endVal); + if (countUp !== null) { + countUp.update($scope.endVal); } else { - countUp = createCountUp($scope.startVal, $scope.endVal, $scope.decimals, $scope.duration); - - animate(); + countUp = createCountUp($scope.startVal, $scope.endVal, $scope.decimals, $scope.duration); + animate(); } - }) + }); } - } + }; }]); })(angular); \ No newline at end of file diff --git a/dist/angular-countUp.min.js b/dist/angular-countUp.min.js index 95a559b..e33a90f 100644 --- a/dist/angular-countUp.min.js +++ b/dist/angular-countUp.min.js @@ -1 +1 @@ -!function(n){"use strict";var t=n.module("countUpModule",[]);t.directive("countUp",["$filter",function(t){return{restrict:"A",scope:{startVal:"=?",endVal:"=",duration:"=?",decimals:"=?",reanimateOnClick:"=?",filter:"@",options:"=?"},link:function(a,e,r){function i(){var n=a.filter.split(":"),e=n.shift();return function(a){var r=[a];Array.prototype.push.apply(r,n);var a=t(e).apply(null,r);return a}}function l(n,t,a,r){n=n||0,isNaN(n)&&(n=Number(n.match(/[\d\-\.]+/g).join(""))),t=t||0,isNaN(t)&&(t=Number(t.match(/[\d\-\.]+/g).join(""))),r=Number(r)||2,a=Number(a)||0;var i=new CountUp(e[0],n,t,a,r,c);return t>999&&(i=new CountUp(e[0],n,t-100,a,r/2,c)),i}function u(){s.reset(),a.endVal>999?s.start(function(){s.update(a.endVal)}):s.start()}var o=null;null!=a.filter&&(o=i());var c={postFormatter:o};null!=a.options&&n.extend(c,a.options);var s=l(a.startVal,a.endVal,a.decimals,a.duration);r.scrollSpyEvent?a.$on(r.scrollSpyEvent,function(n,t){t===r.id&&u()}):u();var d=n.isDefined(a.reanimateOnClick)?a.reanimateOnClick:!0;d&&e.on("click",function(){u()}),a.$watch("endVal",function(n,t){null!=n&&n!==t&&(null!=s?s.update(a.endVal):(s=l(a.startVal,a.endVal,a.decimals,a.duration),u()))})}}}])}(angular); \ No newline at end of file +!function(n){"use strict";var t=n.module("countUpModule",[]);t.directive("countUp",["$filter",function(t){return{restrict:"A",scope:{startVal:"=?",endVal:"=?",duration:"=?",decimals:"=?",reanimateOnClick:"=?",filter:"@",options:"=?"},link:function(a,e,i){function r(){var n=a.filter.split(":"),e=n.shift();return function(a){var i=[a];return Array.prototype.push.apply(i,n),a=t(e).apply(null,i)}}function l(n,t,a,i){n=n||0,isNaN(n)&&(n=Number(n.match(/[\d\-\.]+/g).join(""))),t=t||0,isNaN(t)&&(t=Number(t.match(/[\d\-\.]+/g).join(""))),i=Number(i)||2,a=Number(a)||0;var r=new CountUp(e[0],n,t,a,i,u);return t>999&&(r=new CountUp(e[0],n,t-100,a,i/2,u)),r}function o(){s.reset(),a.endVal>999?s.start(function(){s.update(a.endVal)}):s.start()}var u={};if(a.filter){var c=r();u.formattingFn=c}a.options&&n.extend(u,a.options);var s=l(a.startVal,a.endVal,a.decimals,a.duration);i.scrollSpyEvent?a.$on(i.scrollSpyEvent,function(n,t){t===i.id&&o()}):o();var d=n.isDefined(a.reanimateOnClick)?a.reanimateOnClick:!0;d&&e.on("click",function(){o()}),a.$watch("endVal",function(n,t){null!==n&&n!==t&&(null!==s?s.update(a.endVal):(s=l(a.startVal,a.endVal,a.decimals,a.duration),o()))})}}}])}(angular); \ No newline at end of file diff --git a/dist/countUp.js b/dist/countUp.js index 350feac..1977917 100644 --- a/dist/countUp.js +++ b/dist/countUp.js @@ -12,8 +12,7 @@ /* countUp.js - (c) 2014-2015 @inorganik - Licensed under the MIT license. + by @inorganik */ @@ -52,59 +51,69 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { }; } - // Robert Penner's easeOutExpo - this.easeOutExpo = function(t, b, c, d) { - return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b; - }; + var self = this; // default options - this.options = { + self.options = { useEasing : true, // toggle easing useGrouping : true, // 1,000,000 vs 1000000 separator : ',', // character to use as a separator decimal : '.', // character to use as a decimal - postFormatter: null, // post formatter to run after internal formatting - easingFn: null, // custom easing closure function, will default to Robert Penner's easeOutExpo - formattingFn: null // custom formatting closure function, in the scenario you need more control over the printed number + easingFn: null, // optional custom easing closure function, default is Robert Penner's easeOutExpo + formattingFn: null // optional custom formatting function, default is self.formatNumber below }; // extend default options with passed options object for (var key in options) { if (options.hasOwnProperty(key)) { - this.options[key] = options[key]; + self.options[key] = options[key]; } } - if (this.options.separator === '') this.options.useGrouping = false; - if (!this.options.prefix) this.options.prefix = ''; - if (!this.options.suffix) this.options.suffix = ''; - // establish easing function - this.options.easingFn = !this.options.easingFn - ? this.easeOutExpo - : this.options.easingFn; - - this.d = (typeof target === 'string') ? document.getElementById(target) : target; - this.startVal = Number(startVal); - this.endVal = Number(endVal); - this.countDown = (this.startVal > this.endVal); - this.frameVal = this.startVal; - this.decimals = Math.max(0, decimals || 0); - this.dec = Math.pow(10, this.decimals); - this.duration = Number(duration) * 1000 || 2000; - var self = this; + if (self.options.separator === '') { self.options.useGrouping = false; } + if (!self.options.prefix) self.options.prefix = ''; + if (!self.options.suffix) self.options.suffix = ''; + + self.d = (typeof target === 'string') ? document.getElementById(target) : target; + self.startVal = Number(startVal); + self.endVal = Number(endVal); + self.countDown = (self.startVal > self.endVal); + self.frameVal = self.startVal; + self.decimals = Math.max(0, decimals || 0); + self.dec = Math.pow(10, self.decimals); + self.duration = Number(duration) * 1000 || 2000; + + self.formatNumber = function(nStr) { + nStr = nStr.toFixed(self.decimals); + nStr += ''; + var x, x1, x2, rgx; + x = nStr.split('.'); + x1 = x[0]; + x2 = x.length > 1 ? self.options.decimal + x[1] : ''; + rgx = /(\d+)(\d{3})/; + if (self.options.useGrouping) { + while (rgx.test(x1)) { + x1 = x1.replace(rgx, '$1' + self.options.separator + '$2'); + } + } + return self.options.prefix + x1 + x2 + self.options.suffix; + }; + // Robert Penner's easeOutExpo + self.easeOutExpo = function(t, b, c, d) { + return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b; + }; + + self.easingFn = self.options.easingFn ? self.options.easingFn : self.easeOutExpo; + self.formattingFn = self.options.formattingFn ? self.options.formattingFn : self.formatNumber; - this.version = function () { return '1.7.0'; }; + self.version = function () { return '1.7.1'; }; // Print value to target - this.printValue = function(value) { - if(self.options.formattingFn) { - var result = self.options.formattingFn(value); - } else { - var result = (!isNaN(value)) ? self.formatNumber(value) : '--'; - } + self.printValue = function(value) { + var result = self.formattingFn(value); - if (self.d.tagName == 'INPUT') { + if (self.d.tagName === 'INPUT') { this.d.value = result; } - else if (self.d.tagName == 'text' || self.d.tagName == 'tspan') { + else if (self.d.tagName === 'text' || self.d.tagName === 'tspan') { this.d.textContent = result; } else { @@ -112,33 +121,20 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { } }; - this.count = function(timestamp) { + self.count = function(timestamp) { - if (!self.startTime) self.startTime = timestamp; + if (!self.startTime) { self.startTime = timestamp; } self.timestamp = timestamp; - var progress = timestamp - self.startTime; self.remaining = self.duration - progress; // to ease or not to ease if (self.options.useEasing) { if (self.countDown) { - self.frameVal = self.startVal - self.options.easingFn.call( - self, - progress, - 0, - self.startVal - self.endVal, - self.duration - ); + self.frameVal = self.startVal - self.easingFn(progress, 0, self.startVal - self.endVal, self.duration); } else { - self.frameVal = self.options.easingFn.call( - self, - progress, - self.startVal, - self.endVal - self.startVal, - self.duration - ); + self.frameVal = self.easingFn(progress, self.startVal, self.endVal - self.startVal, self.duration); } } else { if (self.countDown) { @@ -156,7 +152,7 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { } // decimal - self.frameVal = Math.floor(self.frameVal*self.dec)/self.dec; + self.frameVal = Math.round(self.frameVal*self.dec)/self.dec; // format and print value self.printValue(self.frameVal); @@ -165,17 +161,17 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { if (progress < self.duration) { self.rAF = requestAnimationFrame(self.count); } else { - if (self.callback) self.callback(); + if (self.callback) { self.callback(); } } }; // start your animation - this.start = function(callback) { + self.start = function(callback) { self.callback = callback; self.rAF = requestAnimationFrame(self.count); return false; }; // toggles pause/resume animation - this.pauseResume = function() { + self.pauseResume = function() { if (!self.paused) { self.paused = true; cancelAnimationFrame(self.rAF); @@ -188,7 +184,7 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { } }; // reset to startVal so animation can be run again - this.reset = function() { + self.reset = function() { self.paused = false; delete self.startTime; self.startVal = startVal; @@ -196,7 +192,7 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { self.printValue(self.startVal); }; // pass a new endVal and start animation - this.update = function (newEndVal) { + self.update = function (newEndVal) { cancelAnimationFrame(self.rAF); self.paused = false; delete self.startTime; @@ -205,37 +201,11 @@ var CountUp = function(target, startVal, endVal, decimals, duration, options) { self.countDown = (self.startVal > self.endVal); self.rAF = requestAnimationFrame(self.count); }; - this.formatNumber = function(nStr) { - var nVal = nStr = nStr.toFixed(self.decimals); - nStr += ''; - var x, x1, x2, rgx; - x = nStr.split('.'); - x1 = x[0]; - x2 = x.length > 1 ? self.options.decimal + x[1] : ''; - rgx = /(\d+)(\d{3})/; - if (self.options.useGrouping) { - while (rgx.test(x1)) { - x1 = x1.replace(rgx, '$1' + self.options.separator + '$2'); - } - } - var value = self.options.prefix + x1 + x2 + self.options.suffix; - if (typeof self.options.postFormatter === 'function') { - value = self.options.postFormatter(value, nVal); - } - return value; - }; // format startVal on initialization self.printValue(self.startVal); }; -// Example: -// var numAnim = new countUp("SomeElementYouWantToAnimate", 0, 99.99, 2, 2.5); -// numAnim.start(); -// numAnim.update(135); -// with optional callback: -// numAnim.start(someMethodToCallOnComplete); - return CountUp; })); diff --git a/dist/countUp.min.js b/dist/countUp.min.js index 2781fac..447a0c8 100644 --- a/dist/countUp.min.js +++ b/dist/countUp.min.js @@ -1,8 +1 @@ -!function(t,a){"function"==typeof define&&define.amd?define(a):"object"==typeof exports?module.exports=a(require,exports,module):t.CountUp=a()}(this,function(t,a,n){/* - - countUp.js - (c) 2014-2015 @inorganik - Licensed under the MIT license. - -*/ -var e=function(t,a,n,e,i,o){for(var r=0,s=["webkit","moz","ms","o"],m=0;mthis.endVal,this.frameVal=this.startVal,this.decimals=Math.max(0,e||0),this.dec=Math.pow(10,this.decimals),this.duration=1e3*Number(i)||2e3;var l=this;this.version=function(){return"1.7.0"},this.printValue=function(t){if(l.options.formattingFn)var a=l.options.formattingFn(t);else var a=isNaN(t)?"--":l.formatNumber(t);"INPUT"==l.d.tagName?this.d.value=a:"text"==l.d.tagName||"tspan"==l.d.tagName?this.d.textContent=a:this.d.innerHTML=a},this.count=function(t){l.startTime||(l.startTime=t),l.timestamp=t;var a=t-l.startTime;l.remaining=l.duration-a,l.options.useEasing?l.countDown?l.frameVal=l.startVal-l.options.easingFn.call(l,a,0,l.startVal-l.endVal,l.duration):l.frameVal=l.options.easingFn.call(l,a,l.startVal,l.endVal-l.startVal,l.duration):l.countDown?l.frameVal=l.startVal-(l.startVal-l.endVal)*(a/l.duration):l.frameVal=l.startVal+(l.endVal-l.startVal)*(a/l.duration),l.countDown?l.frameVal=l.frameVall.endVal?l.endVal:l.frameVal,l.frameVal=Math.floor(l.frameVal*l.dec)/l.dec,l.printValue(l.frameVal),al.endVal,l.rAF=requestAnimationFrame(l.count)},this.formatNumber=function(t){var a=t=t.toFixed(l.decimals);t+="";var n,e,i,o;if(n=t.split("."),e=n[0],i=n.length>1?l.options.decimal+n[1]:"",o=/(\d+)(\d{3})/,l.options.useGrouping)for(;o.test(e);)e=e.replace(o,"$1"+l.options.separator+"$2");var r=l.options.prefix+e+i+l.options.suffix;return"function"==typeof l.options.postFormatter&&(r=l.options.postFormatter(r,a)),r},l.printValue(l.startVal)};return e}); \ No newline at end of file +!function(a,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t(require,exports,module):a.CountUp=t()}(this,function(a,t,n){var e=function(a,t,n,e,i,r){for(var o=0,s=["webkit","moz","ms","o"],m=0;mu.endVal,u.frameVal=u.startVal,u.decimals=Math.max(0,e||0),u.dec=Math.pow(10,u.decimals),u.duration=1e3*Number(i)||2e3,u.formatNumber=function(a){a=a.toFixed(u.decimals),a+="";var t,n,e,i;if(t=a.split("."),n=t[0],e=t.length>1?u.options.decimal+t[1]:"",i=/(\d+)(\d{3})/,u.options.useGrouping)for(;i.test(n);)n=n.replace(i,"$1"+u.options.separator+"$2");return u.options.prefix+n+e+u.options.suffix},u.easeOutExpo=function(a,t,n,e){return n*(-Math.pow(2,-10*a/e)+1)*1024/1023+t},u.easingFn=u.options.easingFn?u.options.easingFn:u.easeOutExpo,u.formattingFn=u.options.formattingFn?u.options.formattingFn:u.formatNumber,u.version=function(){return"1.7.1"},u.printValue=function(a){var t=u.formattingFn(a);"INPUT"===u.d.tagName?this.d.value=t:"text"===u.d.tagName||"tspan"===u.d.tagName?this.d.textContent=t:this.d.innerHTML=t},u.count=function(a){u.startTime||(u.startTime=a),u.timestamp=a;var t=a-u.startTime;u.remaining=u.duration-t,u.options.useEasing?u.countDown?u.frameVal=u.startVal-u.easingFn(t,0,u.startVal-u.endVal,u.duration):u.frameVal=u.easingFn(t,u.startVal,u.endVal-u.startVal,u.duration):u.countDown?u.frameVal=u.startVal-(u.startVal-u.endVal)*(t/u.duration):u.frameVal=u.startVal+(u.endVal-u.startVal)*(t/u.duration),u.countDown?u.frameVal=u.frameValu.endVal?u.endVal:u.frameVal,u.frameVal=Math.round(u.frameVal*u.dec)/u.dec,u.printValue(u.frameVal),tu.endVal,u.rAF=requestAnimationFrame(u.count)},u.printValue(u.startVal)};return e}); \ No newline at end of file diff --git a/index.html b/index.html index 4fdc4f7..c8e96dd 100644 --- a/index.html +++ b/index.html @@ -12,9 +12,12 @@ + + + + - - + Fork me on GitHub