forked from aishek/jquery-animateNumber
-
Notifications
You must be signed in to change notification settings - Fork 0
/
jquery.animateNumber.js
164 lines (138 loc) · 4.78 KB
/
jquery.animateNumber.js
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/** @preserve jQuery animateNumber plugin v0.0.9
* (c) 2013, Alexandr Borisov.
* https://github.com/aishek/jquery-animateNumber
*/
// ['...'] notation using to avoid names minification by Google Closure Compiler
(function($) {
var reverse = function(value) {
return value.split('').reverse().join('');
};
var defaults = {
numberStep: function(now, tween) {
var floored_number = Math.floor(now),
target = $(tween.elem);
target.text(floored_number);
}
};
var handle = function( tween ) {
var elem = tween.elem;
if ( elem.nodeType && elem.parentNode ) {
var handler = elem._animateNumberSetter;
if (!handler) {
handler = defaults.numberStep;
}
handler(tween.now, tween);
}
};
if (!$.Tween || !$.Tween.propHooks) {
$.fx.step.number = handle;
} else {
$.Tween.propHooks.number = {
set: handle
};
}
var extract_number_parts = function(separated_number, group_length) {
var numbers = separated_number.split('').reverse(),
number_parts = [],
current_number_part,
current_index,
q;
for(var i = 0, l = Math.ceil(separated_number.length / group_length); i < l; i++) {
current_number_part = '';
for(q = 0; q < group_length; q++) {
current_index = i * group_length + q;
if (current_index === separated_number.length) {
break;
}
current_number_part = current_number_part + numbers[current_index];
}
number_parts.push(current_number_part);
}
return number_parts;
};
var remove_precending_zeros = function(number_parts) {
var last_index = number_parts.length - 1,
last = reverse(number_parts[last_index]);
number_parts[last_index] = reverse(parseInt(last, 10).toString());
};
$.animateNumber = {
numberStepFactories: {
/**
* Creates numberStep handler, which appends string to floored animated number on each step.
*
* @example
* // will animate to 100 with "1 %", "2 %", "3 %", ...
* $('#someid').animateNumber({
* number: 100,
* numberStep: $.animateNumber.numberStepFactories.append(' %')
* });
*
* @params {String} suffix string to append to animated number
* @returns {Function} numberStep-compatible function for use in animateNumber's parameters
*/
append: function(suffix) {
return function(now, tween) {
var floored_number = Math.floor(now),
target = $(tween.elem);
target.prop('number', now).text(floored_number + suffix);
};
},
/**
* Creates numberStep handler, which format floored numbers by separating them to groups.
*
* @example
* // will animate with 1 ... 217,980 ... 95,217,980 ... 7,095,217,980
* $('#world-population').animateNumber({
* number: 7095217980,
* numberStep: $.animateNumber.numberStepFactories.separator(',')
* });
*
* @params {String} [separator=' '] string to separate number groups
* @params {String} [group_length=3] number group length
* @returns {Function} numberStep-compatible function for use in animateNumber's parameters
*/
separator: function(separator, group_length) {
separator = separator || ' ';
group_length = group_length || 3;
return function(now, tween) {
var floored_number = Math.floor(now),
separated_number = floored_number.toString(),
target = $(tween.elem);
if (separated_number.length > group_length) {
var number_parts = extract_number_parts(separated_number, group_length);
separated_number = remove_precending_zeros(number_parts).join(separator);
separated_number = reverse(separated_number);
}
target.prop('number', now).text(separated_number);
};
}
}
};
$.fn.animateNumber = function() {
var options = arguments[0],
settings = $.extend({}, defaults, options),
target = $(this),
args = [settings];
for(var i = 1, l = arguments.length; i < l; i++) {
args.push(arguments[i]);
}
// needs of custom step function usage
if (options.numberStep) {
// assigns custom step functions
var items = this.each(function(){
this._animateNumberSetter = options.numberStep;
});
// cleanup of custom step functions after animation
var generic_complete = settings.complete;
settings.complete = function() {
items.each(function(){
delete this._animateNumberSetter;
});
if ( generic_complete ) {
generic_complete.apply(this, arguments);
}
};
}
return target.animate.apply(target, args);
};
}(jQuery));