PageSourceSearch

https://inhope.org/assets/scripts/countUp.js

js inhope.org collected 2026-09-24 08:27:20 UTC 7,545 bytes, 246 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.