├── LICENSE.txt ├── bower.json ├── example.html ├── jquery.countTo.js ├── package.json ├── readme.md └── test ├── index.html └── tests.js /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2014 Matt Huggins 2 | 3 | ----------------------------------------------------------------------- 4 | 5 | The MIT License 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-countTo", 3 | "version": "1.2.0", 4 | "homepage": "https://github.com/mhuggins/jquery-countTo", 5 | "authors": [ 6 | "Matt Huggins " 7 | ], 8 | "description": "A jQuery plugin that will count up (or down) to a target number at a specified speed.", 9 | "main": "jquery.countTo.js", 10 | "keywords": [ 11 | "jQuery", 12 | "counter", 13 | "count", 14 | "increment", 15 | "decrement" 16 | ], 17 | "license": "MIT", 18 | "ignore": [ 19 | "**/.*", 20 | "node_modules", 21 | "bower_components", 22 | "test", 23 | "tests" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | jQuery countTo Example 4 | 5 | 34 | 35 | 36 | 37 |

jQuery countTo Example

38 |

39 | This is a simple example of the 40 | jQuery countTo plugin 41 | created by Matt Huggins. Refer to 42 | the full documentation for more usage information. 43 |

44 | 45 |
46 |

47 | How many licks to the center of a Tootsie Pop? 48 | 49 |

50 |

51 |
52 | 53 |
54 |

55 | What is Earth's radius? 56 | 57 |

58 |

miles

59 |
60 | 61 |
62 |

63 | Start the countdown... 64 | 65 |

66 |

Lift-off in

67 |
68 | 69 |
70 |

71 | Earth's Gravity 72 | 73 |

74 |

m/s2

75 |
76 | 77 |
78 |

79 | To infinity...and beyond! 80 | 81 |

82 |

83 |
84 | 85 | 86 | 87 | 88 | 131 | 132 | -------------------------------------------------------------------------------- /jquery.countTo.js: -------------------------------------------------------------------------------- 1 | (function (factory) { 2 | if (typeof define === 'function' && define.amd) { 3 | // AMD 4 | define(['jquery'], factory); 5 | } else if (typeof exports === 'object') { 6 | // CommonJS 7 | factory(require('jquery')); 8 | } else { 9 | // Browser globals 10 | factory(jQuery); 11 | } 12 | }(function ($) { 13 | var CountTo = function (element, options) { 14 | this.$element = $(element); 15 | this.options = $.extend({}, CountTo.DEFAULTS, this.dataOptions(), options); 16 | this.init(); 17 | }; 18 | 19 | CountTo.DEFAULTS = { 20 | from: 0, // the number the element should start at 21 | to: 0, // the number the element should end at 22 | speed: 1000, // how long it should take to count between the target numbers 23 | refreshInterval: 100, // how often the element should be updated 24 | decimals: 0, // the number of decimal places to show 25 | formatter: formatter, // handler for formatting the value before rendering 26 | onUpdate: null, // callback method for every time the element is updated 27 | onComplete: null // callback method for when the element finishes updating 28 | }; 29 | 30 | CountTo.prototype.init = function () { 31 | this.value = this.options.from; 32 | this.loops = Math.ceil(this.options.speed / this.options.refreshInterval); 33 | this.loopCount = 0; 34 | this.increment = (this.options.to - this.options.from) / this.loops; 35 | }; 36 | 37 | CountTo.prototype.dataOptions = function () { 38 | var options = { 39 | from: this.$element.data('from'), 40 | to: this.$element.data('to'), 41 | speed: this.$element.data('speed'), 42 | refreshInterval: this.$element.data('refresh-interval'), 43 | decimals: this.$element.data('decimals') 44 | }; 45 | 46 | var keys = Object.keys(options); 47 | 48 | for (var i in keys) { 49 | var key = keys[i]; 50 | 51 | if (typeof(options[key]) === 'undefined') { 52 | delete options[key]; 53 | } 54 | } 55 | 56 | return options; 57 | }; 58 | 59 | CountTo.prototype.update = function () { 60 | this.value += this.increment; 61 | this.loopCount++; 62 | 63 | this.render(); 64 | 65 | if (typeof(this.options.onUpdate) == 'function') { 66 | this.options.onUpdate.call(this.$element, this.value); 67 | } 68 | 69 | if (this.loopCount >= this.loops) { 70 | clearInterval(this.interval); 71 | this.value = this.options.to; 72 | 73 | if (typeof(this.options.onComplete) == 'function') { 74 | this.options.onComplete.call(this.$element, this.value); 75 | } 76 | } 77 | }; 78 | 79 | CountTo.prototype.render = function () { 80 | var formattedValue = this.options.formatter.call(this.$element, this.value, this.options); 81 | this.$element.text(formattedValue); 82 | }; 83 | 84 | CountTo.prototype.restart = function () { 85 | this.stop(); 86 | this.init(); 87 | this.start(); 88 | }; 89 | 90 | CountTo.prototype.start = function () { 91 | this.stop(); 92 | this.render(); 93 | this.interval = setInterval(this.update.bind(this), this.options.refreshInterval); 94 | }; 95 | 96 | CountTo.prototype.stop = function () { 97 | if (this.interval) { 98 | clearInterval(this.interval); 99 | } 100 | }; 101 | 102 | CountTo.prototype.toggle = function () { 103 | if (this.interval) { 104 | this.stop(); 105 | } else { 106 | this.start(); 107 | } 108 | }; 109 | 110 | function formatter(value, options) { 111 | return value.toFixed(options.decimals); 112 | } 113 | 114 | $.fn.countTo = function (option) { 115 | return this.each(function () { 116 | var $this = $(this); 117 | var data = $this.data('countTo'); 118 | var init = !data || typeof(option) === 'object'; 119 | var options = typeof(option) === 'object' ? option : {}; 120 | var method = typeof(option) === 'string' ? option : 'start'; 121 | 122 | if (init) { 123 | if (data) data.stop(); 124 | $this.data('countTo', data = new CountTo(this, options)); 125 | } 126 | 127 | data[method].call(data); 128 | }); 129 | }; 130 | })); 131 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-countto", 3 | "version": "1.2.0", 4 | "description": "A jQuery plugin that will count up (or down) to a target number at a specified speed.", 5 | "main": "jquery.countTo.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/mhuggins/jquery-countTo.git" 15 | }, 16 | "keywords": [ 17 | "jQuery", 18 | "counter", 19 | "count", 20 | "increment", 21 | "decrement" 22 | ], 23 | "author": "Matt Huggins ", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/mhuggins/jquery-countTo/issues" 27 | }, 28 | "homepage": "https://github.com/mhuggins/jquery-countTo#readme" 29 | } 30 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | jQuery countTo Plugin 2 | ===================== 3 | [jQuery countTo](https://github.com/mhuggins/jquery-countTo) is a 4 | [jQuery](http://jquery.com) plugin that will count up (or down) to a target 5 | number at a specified speed, rendered within an HTML DOM element. 6 | 7 | Requirements: 8 | ------------- 9 | [jQuery countTo](https://github.com/mhuggins/jquery-countTo) requires the 10 | latest version of [jQuery](http://jquery.com). 11 | 12 | Usage: 13 | ------ 14 | There are two main approaches to using this plugin: through data attributes on 15 | DOM nodes, and through JS options explicitly passed to the `countTo` function. 16 | 17 | These two methods can be mixed and matched as well. Data attributes takes 18 | precedence over JS options. 19 | 20 | ### Data Attributes 21 | 22 | This approach allows you to define `data-*` attributes on whatever DOM element 23 | will act as a container for your counter. This is useful when you already know 24 | the values at the time that you are constructing the DOM. 25 | 26 | 27 | 28 | 31 | 32 | A more detailed example that demonstrates all possible options being used is as 33 | follows. 34 | 35 | 37 | 38 | 41 | 42 | Refer to the **Options** section below for more info on the various options 43 | available. 44 | 45 | ### JavaScript Options 46 | 47 | This approach allows you to pass values to the `countTo` function. This is 48 | useful when you don't know the values at the time the DOM is being rendered. 49 | 50 | 51 | 52 | 55 | 56 | A more detailed example that demonstrates all possible options being used is as 57 | follows. 58 | 59 | 60 | 61 | 78 | 79 | Refer to the **Options** section below for more info on the various options 80 | available. 81 | 82 | Options: 83 | -------- 84 | A complete listing of the options that can be passed to the `countTo` method is 85 | below. 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 108 | 109 | 110 | 111 | 112 | 114 | 115 | 116 | 117 | 118 | 120 | 121 | 122 | 123 | 128 | 129 | 130 | 131 | 135 | 136 | 137 | 138 | 141 | 142 |
OptionData AttributeDescription
fromdata-fromThe number to start counting from. (default: 0)
todata-toThe number to stop counting at. (default: 100)
speeddata-speedThe number of milliseconds it should take to finish counting. 107 | (default: 1000)
refreshIntervaldata-refresh-intervalThe number of milliseconds to wait between refreshing the counter. 113 | (default: 100)
decimalsdata-decimalsThe number of decimal places to show when using the default 119 | formatter. (default: 0)
formatter (value, options)A handler that is used to format the current value before rendering to 124 | the DOM. The true current value and options set is passed to the 125 | function, and it is run in the context of the DOM element. It must 126 | return the formatted value. (default: 127 | value.toFixed(options.decimals))
onUpdate (value)A callback function that is triggered for every iteration that the 132 | counter updates. The currently rendered value is passed to the 133 | function, and it is called in the context of the DOM element. 134 | (default: null)
onComplete (value)A callback function that is triggered when counting finishes. The 139 | final rendered value is passed to the function, and it is called in the 140 | context of the DOM element. (default: null)
143 | 144 | Functions: 145 | ---------- 146 | This plugin also supports functions, primarily for changing state. Functions are 147 | called by passing the name as a string to the `countTo` jQuery function, e.g.: 148 | `$('#timer').countTo('stop')`. 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 |
startResumes the timer if it is stopped.
stopStops (pauses) the timer if it is running.
toggleStarts or stops the timer based upon its current state.
restartRestarts the timer at its initial "from" value.
168 | 169 | Created By: 170 | ----------- 171 | [Matt Huggins](http://matthuggins.com) 172 | 173 | License: 174 | -------- 175 | jQuery-countTo is released under the 176 | [MIT license](http://www.opensource.org/licenses/MIT). 177 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jQuery-countTo Test Suite 6 | 7 | 8 | 9 |
10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/tests.js: -------------------------------------------------------------------------------- 1 | var timer; 2 | 3 | // test to ensure DOM options are respected 4 | module('DOM options'); 5 | timer = $('
'); 6 | runTests(timer); 7 | 8 | // test to ensure JS options are respected 9 | module('JS options'); 10 | timer = $('
'); 11 | runTests(timer, { 12 | from: 1, 13 | to: 3, 14 | speed: 3000, 15 | refreshInterval: 1000 16 | }); 17 | 18 | // test to ensure JS options override DOM options 19 | module('DOM and JS options'); 20 | timer = $('
'); 21 | runTests(timer, { 22 | from: 1, 23 | to: 3, 24 | speed: 3000, 25 | refreshInterval: 1000 26 | }); 27 | 28 | function runTests(element, options) { 29 | element = $(element); 30 | options = options || {}; 31 | 32 | asyncTest('onComplete is called when counting completes', 4, function () { 33 | element.countTo($.extend({}, options, { 34 | onComplete: function (value) { 35 | ok(true, 'onComplete was called'); 36 | ok(this[0] === element[0], 'this is the updated dom element'); 37 | ok(value === 3, 'value matches data-to'); 38 | ok(this[0].innerText === "3", 'innerText matches data-to'); 39 | start(); 40 | } 41 | })); 42 | }); 43 | 44 | asyncTest('onUpdate is called once per refresh', 3, function () { 45 | element.countTo($.extend({}, options, { 46 | onUpdate: function () { 47 | ok(true, 'onUpdate was called'); 48 | }, 49 | onComplete: function () { 50 | start(); 51 | } 52 | })); 53 | }); 54 | 55 | asyncTest('custom formatter is called', 1, function () { 56 | element.countTo($.extend({}, options, { 57 | formatter: function () { 58 | return 'foobar'; 59 | }, 60 | onComplete: function () { 61 | ok(this[0].innerText === 'foobar', 'innerText matches formatted value'); 62 | start(); 63 | } 64 | })); 65 | }); 66 | } 67 | --------------------------------------------------------------------------------