PageSourceSearch

https://www.materik-m.ru/local/templates/materik_2024/scripts/accounting.js?174219740113471

js materik-m.ru collected 2026-09-25 09:58:21 UTC 13,471 bytes, 413 lines download raw bytes

1/*!
2 * accounting.js v0.4.1
3 * Copyright 2014 Open Exchange Rates
4 *
5 * Freely distributable under the MIT license.
6 * Portions of accounting.js are inspired or borrowed from underscore.js
7 *
8 * Full details and documentation:
9 * http://openexchangerates.github.io/accounting.js/
10 */
11
12(function(root, undefined) {
13
14	/* --- Setup --- */
15
16	// Create the local library object, to be exported or referenced globally later
17	var lib = {};
18
19	// Current version
20	lib.version = '0.4.1';
21
22
23	/* --- Exposed settings --- */
24
25	// The library's settings configuration object. Contains default parameters for
26	// currency and number formatting
27	lib.settings = {
28		currency: {
29			symbol : "$",		// default currency symbol is '$'
30			format : "%s%v",	// controls output: %s = symbol, %v = value (can be object, see docs)
31			decimal : ".",		// decimal point separator
32			thousand : ",",		// thousands separator
33			precision : 2,		// decimal places
34			grouping : 3		// digit grouping (not implemented yet)
35		},
36		number: {
37			precision : 0,		// default precision on numbers is 0
38			grouping : 3,		// digit grouping (not implemented yet)
39			thousand : ",",
40			decimal : "."
41		}
42	};
43
44
45	/* --- Internal Helper Methods --- */
46
47	// Store reference to possibly-available ECMAScript 5 methods for later
48	var nativeMap = Array.prototype.map,
49		nativeIsArray = Array.isArray,
50		toString = Object.prototype.toString;
51
52	/**
53	 * Tests whether supplied parameter is a string
54	 * from underscore.js
55	 */
56	function isString(obj) {
57		return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
58	}
59
60	/**
61	 * Tests whether supplied parameter is a string
62	 * from underscore.js, delegates to ECMA5's native Array.isArray
63	 */
64	function isArray(obj) {
65		return nativeIsArray ? nativeIsArray(obj) : toString.call(obj) === '[object Array]';
66	}
67
68	/**
69	 * Tests whether supplied parameter is a true object
70	 */
71	function isObject(obj) {
72		return obj && toString.call(obj) === '[object Object]';
73	}
74
75	/**
76	 * Extends an object with a defaults object, similar to underscore's _.defaults
77	 *
78	 * Used for abstracting parameter handling from API methods
79	 */
80	function defaults(object, defs) {
81		var key;
82		object = object || {};
83		defs = defs || {};
84		// Iterate over object non-prototype properties:
85		for (key in defs) {
86			if (defs.hasOwnProperty(key)) {
87				// Replace values with defaults only if undefined (allow empty/zero values):
88				if (object[key] == null) object[key] = defs[key];
89			}
90		}
91		return object;
92	}
93
94	/**
95	 * Implementation of `Array.map()` for iteration loops
96	 *
97	 * Returns a new Array as a result of calling `iterator` on each array value.
98	 * Defers to native Array.map if available
99	 */
100	function map(obj, iterator, context) {
101		var results = [], i, j;
102
103		if (!obj) return results;
104
105		// Use native .map method if it exists:
106		if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
107
108		// Fallback for native .map:
109		for (i = 0, j = obj.length; i < j; i++ ) {
110			results[i] = iterator.call(context, obj[i], i, obj);
111		}
112		return results;
113	}
114
115	/**
116	 * Check and normalise the value of precision (must be positive integer)
117	 */
118	function checkPrecision(val, base) {
119		val = Math.round(Math.abs(val));
120		return isNaN(val)? base : val;
121	}
122
123
124	/**
125	 * Parses a format string or object and returns format obj for use in rendering
126	 *
127	 * `format` is either a string with the default (positive) format, or object
128	 * containing `pos` (required), `neg` and `zero` values (or a function returning
129	 * either a string or object)
130	 *
131	 * Either string or format.pos must contain "%v" (value) to be valid
132	 */
133	function checkCurrencyFormat(format) {
134		var defaults = lib.settings.currency.format;
135
136		// Allow function as format parameter (should return string or object):
137		if ( typeof format === "function" ) format = format();
138
139		// Format can be a string, in which case `value` ("%v") must be present:
140		if ( isString( format ) && format.match("%v") ) {
141
142			// Create and return positive, negative and zero formats:
143			return {
144				pos : format,
145				neg : format.replace("-", "").replace("%v", "-%v"),
146				zero : format
147			};
148
149		// If no format, or object is missing valid positive value, use defaults:
150		} else if ( !format || !format.pos || !format.pos.match("%v") ) {
151
152			// If defaults is a string, casts it to an object for faster checking next time:
153			return ( !isString( defaults ) ) ? defaults : lib.settings.currency.format = {
154				pos : defaults,
155				neg : defaults.replace("%v", "-%v"),
156				zero : defaults
157			};
158
159		}
160		// Otherwise, assume format was fine:
161		return format;
162	}
163
164
165	/* --- API Methods --- */
166
167	/**
168	 * Takes a string/array of strings, removes all formatting/cruft and returns the raw float value
169	 * Alias: `accounting.parse(string)`
170	 *
171	 * Decimal must be included in the regular expression to match floats (defaults to
172	 * accounting.settings.number.decimal), so if the number uses a non-standard decimal 
173	 * separator, provide it as the second argument.
174	 *
175	 * Also matches bracketed negatives (eg. "$ (1.99)" => -1.99)
176	 *
177	 * Doesn't throw any errors (`NaN`s become 0) but this may change in future
178	 */
179	var unformat = lib.unformat = lib.parse = function(value, decimal) {
180		// Recursively unformat arrays:
181		if (isArray(value)) {
182			return map(value, function(val) {
183				return unformat(val, decimal);
184			});
185		}
186
187		// Fails silently (need decent errors):
188		value = value || 0;
189
190		// Return the value as-is if it's already a number:
191		if (typeof value === "number") return value;
192
193		// Default decimal point comes from settings, but could be set to eg. "," in opts:
194		decimal = decimal || lib.settings.number.decimal;
195
196		 // Build regex to strip out everything except digits, decimal point and minus sign:
197		var regex = new RegExp("[^0-9-" + decimal + "]", ["g"]),
198			unformatted = parseFloat(
199				("" + value)
200				.replace(/\((.*)\)/, "-$1") // replace bracketed values with negatives
201				.replace(regex, '')         // strip out any cruft
202				.replace(decimal, '.')      // make sure decimal point is standard
203			);
204
205		// This will fail silently which may cause trouble, let's wait and see:
206		return !isNaN(unformatted) ? unformatted : 0;
207	};
208
209
210	/**
211	 * Implementation of toFixed() that treats floats more like decimals
212	 *
213	 * Fixes binary rounding issues (eg. (0.615).toFixed(2) === "0.61") that present
214	 * problems for accounting- and finance-related software.
215	 */
216	var toFixed = lib.toFixed = function(value, precision) {
217		precision = checkPrecision(precision, lib.settings.number.precision);
218		var power = Math.pow(10, precision);
219
220		// Multiply up by precision, round accurately, then divide and use native toFixed():
221		return (Math.round(lib.unformat(value) * power) / power).toFixed(precision);
222	};
223
224
225	/**
226	 * Format a number, with comma-separated thousands and custom precision/decimal places
227	 * Alias: `accounting.format()`
228	 *
229	 * Localise by overriding the precision and thousand / decimal separators
230	 * 2nd parameter `precision` can be an object matching `settings.number`
231	 */
232	var formatNumber = lib.formatNumber = lib.format = function(number, precision, thousand, decimal) {
233		// Resursively format arrays:
234		if (isArray(number)) {
235			return map(number, function(val) {
236				return formatNumber(val, precision, thousand, decimal);
237			});
238		}
239
240		// Clean up number:
241		number = unformat(number);
242
243		// Build options object from second param (if object) or all params, extending defaults:
244		var opts = defaults(
245				(isObject(precision) ? precision : {
246					precision : precision,
247					thousand : thousand,
248					decimal : decimal
249				}),
250				lib.settings.number
251			),
252
253			// Clean up precision
254			usePrecision = checkPrecision(opts.precision),
255
256			// Do some calc:
257			negative = number < 0 ? "-" : "",
258			base = parseInt(toFixed(Math.abs(number || 0), usePrecision), 10) + "",
259			mod = base.length > 3 ? base.length % 3 : 0;
260
261		// Format the number:
262		return negative + (mod ? base.substr(0, mod) + opts.thousand : "") + base.substr(mod).replace(/(\d{3})(?=\d)/g, "$1" + opts.thousand) + (usePrecision ? opts.decimal + toFixed(Math.abs(number), usePrecision).split('.')[1] : "");
263	};
264
265
266	/**
267	 * Format a number into currency
268	 *
269	 * Usage: accounting.formatMoney(number, symbol, precision, thousandsSep, decimalSep, format)
270	 * defaults: (0, "$", 2, ",", ".", "%s%v")
271	 *
272	 * Localise by overriding the symbol, precision, thousand / decimal separators and format
273	 * Second param can be an object matching `settings.currency` which is the easiest way.
274	 *
275	 * To do: tidy up the parameters
276	 */
277	var formatMoney = lib.formatMoney = function(number, symbol, precision, thousand, decimal, format) {
278		// Resursively format arrays:
279		if (isArray(number)) {
280			return map(number, function(val){
281				return formatMoney(val, symbol, precision, thousand, decimal, format);
282			});
283		}
284
285		// Clean up number:
286		number = unformat(number);
287
288		// Build options object from second param (if object) or all params, extending defaults:
289		var opts = defaults(
290				(isObject(symbol) ? symbol : {
291					symbol : symbol,
292					precision : precision,
293					thousand : thousand,
294					decimal : decimal,
295					format : format
296				}),
297				lib.settings.currency
298			),
299
300			// Check format (returns object with pos, neg and zero):
301			formats = checkCurrencyFormat(opts.format),
302
303			// Choose which format to use for this value:
304			useFormat = number > 0 ? formats.pos : number < 0 ? formats.neg : formats.zero;
305
306		// Return with currency symbol added:
307		return useFormat.replace('%s', opts.symbol).replace('%v', formatNumber(Math.abs(number), checkPrecision(opts.precision), opts.thousand, opts.decimal));
308	};
309
310
311	/**
312	 * Format a list of numbers into an accounting column, padding with whitespace
313	 * to line up currency symbols, thousand separators and decimals places
314	 *
315	 * List should be an array of numbers
316	 * Second parameter can be an object containing keys that match the params
317	 *
318	 * Returns array of accouting-formatted number strings of same length
319	 *
320	 * NB: `white-space:pre` CSS rule is required on the list container to prevent
321	 * browsers from collapsing the whitespace in the output strings.
322	 */
323	lib.formatColumn = function(list, symbol, precision, thousand, decimal, format) {
324		if (!list) return [];
325
326		// Build options object from second param (if object) or all params, extending defaults:
327		var opts = defaults(
328				(isObject(symbol) ? symbol : {
329					symbol : symbol,
330					precision : precision,
331					thousand : thousand,
332					decimal : decimal,
333					format : format
334				}),
335				lib.settings.currency
336			),
337
338			// Check format (returns object with pos, neg and zero), only need pos for now:
339			formats = checkCurrencyFormat(opts.format),
340
341			// Whether to pad at start of string or after currency symbol:
342			padAfterSymbol = formats.pos.indexOf("%s") < formats.pos.indexOf("%v") ? true : false,
343
344			// Store value for the length of the longest string in the column:
345			maxLength = 0,
346
347			// Format the list according to options, store the length of the longest string:
348			formatted = map(list, function(val, i) {
349				if (isArray(val)) {
350					// Recursively format columns if list is a multi-dimensional array:
351					return lib.formatColumn(val, opts);
352				} else {
353					// Clean up the value
354					val = unformat(val);
355
356					// Choose which format to use for this value (pos, neg or zero):
357					var useFormat = val > 0 ? formats.pos : val < 0 ? formats.neg : formats.zero,
358
359						// Format this value, push into formatted list and save the length:
360						fVal = useFormat.replace('%s', opts.symbol).replace('%v', formatNumber(Math.abs(val), checkPrecision(opts.precision), opts.thousand, opts.decimal));
361
362					if (fVal.length > maxLength) maxLength = fVal.length;
363					return fVal;
364				}
365			});
366
367		// Pad each number in the list and send back the column of numbers:
368		return map(formatted, function(val, i) {
369			// Only if this is a string (not a nested array, which would have already been padded):
370			if (isString(val) && val.length < maxLength) {
371				// Depending on symbol position, pad after symbol or at index 0:
372				return padAfterSymbol ? val.replace(opts.symbol, opts.symbol+(new Array(maxLength - val.length + 1).join(" "))) : (new Array(maxLength - val.length + 1).join(" ")) + val;
373			}
374			return val;
375		});
376	};
377
378
379	/* --- Module Definition --- */
380
381	// Export accounting for CommonJS. If being loaded as an AMD module, define it as such.
382	// Otherwise, just add `accounting` to the global object
383	if (typeof exports !== 'undefined') {
384		if (typeof module !== 'undefined' && module.exports) {
385			exports = module.exports = lib;
386		}
387		exports.accounting = lib;
388	} else if (typeof define === 'function' && define.amd) {
389		// Return the library as an AMD module:
390		define([], function() {
391			return lib;
392		});
393	} else {
394		// Use accounting.noConflict to restore `accounting` back to its original value.
395		// Returns a reference to the library's `accounting` object;
396		// e.g. `var numbers = accounting.noConflict();`
397		lib.noConflict = (function(oldAccounting) {
398			return function() {
399				// Reset the value of the root's `accounting` variable:
400				root.accounting = oldAccounting;
401				// Delete the noConflict method:
402				lib.noConflict = undefined;
403				// Return reference to the library to re-assign it:
404				return lib;
405			};
406		})(root.accounting);
407
408		// Declare `fx` on the root (global/window) object:
409		root['accounting'] = lib;
410	}
411
412	// Root will be `window` in browser or `global` on the server:
413}(this));

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.