Code content and download address
The Accounting.js code is as follows:
Copy Code code as follows:
/*!
* Accounting.js v0.3.2
* Copyright, Joss Crowcroft
*
* Freely distributable under the MIT license.
* Portions of Accounting.js are inspired or borrowed from Underscore.js
*
* Full details and Documentation:
* http://josscrowcroft.github.com/accounting.js/
*/
(function (root, undefined) {
/*---Setup---* *
Create The local library object, to be exported or referenced globally later
var lib = {};
Current version
lib.version = ' 0.3.2 ';
/*---EXPOSED settings---* *
The library ' s settings Configuration object. Contains Default parameters for
Currency and number formatting
Lib.settings = {
Currency: {
Symbol: "$",//default currency symbol is ' $ '
Format: "%s%v",//Controls output:%s = symbol,%v = value (can be object, click Docs)
Decimal: ".",//decimal point separator
Thousand: ",",//Thousands separator
Precision:2,//decimal places
Grouping:3//digit grouping (not implemented yet)
},
Number: {
precision:0,//default precision on numbers is 0
Grouping:3,//digit grouping (not implemented yet)
Thousand: ",",
Decimal: "."
}
};
/*---Internal Helper Methods---* *
Store reference to Possibly-available ECMAScript 5 methods for later
var nativemap = Array.prototype.map,
Nativeisarray = Array.isarray,
toString = Object.prototype.toString;
/**
* Tests whether supplied parameter is a string
* FROM Underscore.js
*/
function isstring (obj) {
Return!! (obj = = = ' | | (obj && obj.charcodeat && obj.substr));
}
/**
* Tests whether supplied parameter is a string
* FROM Underscore.js, delegates to ECMA5 ' s native array.isarray
*/
function IsArray (obj) {
Return Nativeisarray? Nativeisarray (obj): tostring.call (obj) = = ' [Object Array] ';
}
/**
* Tests whether supplied parameter is a true object
*/
function IsObject (obj) {
return obj && tostring.call (obj) = = ' [Object Object] ';
}
/**
* Extends an object and a defaults object, similar to underscore ' s _.defaults
*
* Used for abstracting parameter handling from API methods
*/
function defaults (object, defs) {
var key;
Object = Object | | {};
defs = Defs | | {};
Iterate over object Non-prototype properties:
For (key in defs) {
if (Defs.hasownproperty (key)) {
Replace values with defaults only if undefined (allow Empty/zero values):
if (object[key] = = null) Object[key] = Defs[key];
}
}
return object;
}
/**
* Implementation of ' array.map () ' for iteration loops
*
* Returns a new array as a result of calling ' iterator ' in each Array value.
* Defers to native Array.map if available
*/
function map (obj, iterator, context) {
var results = [], I, J;
if (!obj) return results;
Use Native. Map method if it exists:
if (nativemap && obj.map = = Nativemap) return Obj.map (iterator, context);
Fallback for native. Map:
for (i = 0, j = obj.length I < J; i++) {
Results[i] = Iterator.call (context, obj[i], I, obj);
}
return results;
}
/**
* Check and normalise the value of precision (must be positive integer)
*/
Function Checkprecision (val, base) {
val = Math.Round (Math.Abs (Val));
Return isNaN (val)? Base:val;
}
/**
* Parses a format string or object and returns format obj in rendering
*
* ' Format ' is either a string with the default (positive) format, or object
* containing ' POS ' (required), ' neg ' and ' zero ' values (or a function returning
* Either a string or object)
*
* Either string or Format.pos must contain "%v" (value) to be valid
*/
function Checkcurrencyformat (format) {
var defaults = Lib.settings.currency.format;
Allow function as format parameter (should return string or object):
if (typeof format = = = "function") format = Format ();
Format can is a string, in which case ' value ' ("%v") must to be present:
if (isstring (format) && format.match ("%v")) {
Create and return positive, negative and zero formats:
return {
Pos:format,
Neg:format.replace ("-", ""). Replace ("%v", "-%v"),
Zero:format
};
IF no format, or object is missing valid positive value, use defaults:
else if (!format | |!format.pos | |!format.pos.match ("%V")) {
If defaults is a string, casts it to the faster checking next time:
Return (!isstring (defaults))? Defaults:lib.settings.currency.format = {
Pos:defaults,
Neg:defaults.replace ("%v", "-%v"),
Zero:defaults
};
}
Otherwise, assume format was fine:
return format;
}
/*---API Methods---* *
/**
* Takes a string/array of strings, removes all formatting/cruft and returns the raw float value
* alias:accounting. ' Parse (String) '
*
* Decimal must is included in the regular expression to match floats (defaults to
* Accounting.settings.number.decimal), so if the number uses a non-standard decimal
* Separator, provide it as the second argument.
*
* Also matches bracketed negatives (eg. "$ (1.99)" =>-1.99)
*
* doesn ' t throw any errors (' NaN ' become 0) but the may change in future
*/
var unformat = Lib.unformat = Lib.parse = function (value, decimal) {
Recursively Unformat arrays:
if (IsArray (value)) {
return map (value, function (val) {
Return Unformat (Val, decimal);
});
}
Fails silently (need decent errors):
Value = value | | 0;
Return the value As-is if it ' s already a number:
if (typeof value = = = "Number") return value;
Default decimal point comes from settings, but could is set to eg. "," in opts:
decimal = Decimal | | Lib.settings.number.decimal;
Build regex to strip out everything except digits, decimal point and minus sign:
var regex = new RegExp ("[^0-9-" + decimal + "]", ["G"]),
Unformatted = parsefloat (
("" + value)
. replace (/\ (. *) \)/, "-$1")//replace bracketed values with negatives
. replace (regex, ')//strip out any cruft
. replace (decimal, '. ')//Make sure decimal point is standard
);
This is fail silently which may cause trouble, let's wait and a:
Return!isnan (unformatted)? unformatted:0;
};
/**
* Implementation of toFixed (), treats floats more like decimals
*
* Fixes binary rounding issues (eg. (0.615). toFixed (2) = = "0.61") that present
* Problems for Accounting-and finance-related software.
*/
var toFixed = lib.tofixed = function (value, precision) {
Precision = checkprecision (precision, lib.settings.number.precision);
var power = Math.pow (precision);
Multiply up by precision, round accurately, then divide and use native toFixed ():
Return (Math.Round (Lib.unformat (value) * Power)/power). toFixed (precision);
};
/**
* Format a number with comma-separated thousands and custom precision/decimal places
*
* Localise by overriding the precision and thousand/decimal separators
* 2nd parameter ' precision ' can be an object matching ' Settings.number '
*/
var FormatNumber = Lib.formatnumber = function (number, precision, thousand, decimal) {
resursively format Arrays:
if (IsArray (number)) {
return map (number, function (val) {
Return FormatNumber (Val, precision, Thousand, decimal);
});
}
Clean up number:
Number = Unformat (number);
Build Options object from second param (if object) or all params, extending defaults:
var opts = defaults (
(IsObject (precision)? Precision: {
Precision:precision,
Thousand:thousand,
Decimal:decimal
}),
Lib.settings.number
),
Clean up precision
Useprecision = Checkprecision (opts.precision),
Do some calc:
Negative = number < 0? "-" : "",
Base = parseint (ToFixed (math.abs (number | | 0), useprecision), 10) + "",
MoD = base.length > 3? Base.length% 3:0;
Format the number:
return negative + (mod base.substr (0, MoD) + Opts.thousand: "") + BASE.SUBSTR (mod). Replace (/(\d{3}) (? =\d)/g, "$" + opt S.thousand) + (useprecision Opts.decimal + toFixed (math.abs (number), useprecision). Split ('. ') [1]: "");
};
/**
* Format a number into currency
*
* Usage:accounting.formatMoney (number, symbol, precision, THOUSANDSSEP, DECIMALSEP, format)
* Defaults: (0, "$", 2, ",", ".", "%s%v")
*
* Localise by overriding the symbol, precision, thousand/decimal separators and format
* Second param can be a object matching ' settings.currency ' which is the easiest way.
*
* To do:tidy up the parameters
*/
var Formatmoney = Lib.formatmoney = function (number, symbol, precision, thousand, decimal, format) {
resursively format Arrays:
if (IsArray (number)) {
return map (number, function (val) {
Return Formatmoney (val, symbol, precision, thousand, decimal, format);
});
}
Clean up number:
Number = Unformat (number);
Build Options object from second param (if object) or all params, extending defaults:
var opts = defaults (
(IsObject (symbol)? symbol: {
Symbol:symbol,
Precision:precision,
Thousand:thousand,
Decimal:decimal,
Format:format
}),
Lib.settings.currency
),
Check format (returns object with POS, neg and zero):
formats = Checkcurrencyformat (Opts.format),
Choose which format to with this value:
UseFormat = number > 0? Formats.pos:number < 0? Formats.neg:formats.zero;
Return with currency symbol added:
Return Useformat.replace ('%s ', opts.symbol). Replace ('%v ', FormatNumber (math.abs (number), Checkprecision ( opts.precision), Opts.thousand, opts.decimal);
};
/**
* Format A list of numbers into the accounting column, padding with whitespace
* To line up currency symbols, thousand separators and decimals places
*
* List should is an array of numbers
* Second parameter can be a object containing keys that match the params
*
* Returns Array of accouting-formatted number strings of same length
*
* NB: ' white-space:pre ' CSS rule are required on the list container to prevent
* Browsers from collapsing to the whitespace in the output strings.
*/
Lib.formatcolumn = function (list, symbol, precision, thousand, decimal, format) {
if (!list) return [];
Build Options object from second param (if object) or all params, extending defaults:
var opts = defaults (
(IsObject (symbol)? symbol: {
Symbol:symbol,
Precision:precision,
Thousand:thousand,
Decimal:decimal,
Format:format
}),
Lib.settings.currency
),
Check format (returns object with POS, neg and zero), only need POS for now:
formats = Checkcurrencyformat (Opts.format),
Whether to pad at the start of string or after currency symbol:
Padaftersymbol = Formats.pos.indexOf ("%s") < Formats.pos.indexOf ("%v")? True:false,
Store value for the length of the longest string in the column:
MaxLength = 0,
Format the list according to options, store the length of the longest string:
formatted = map (list, function (val, i) {
if (IsArray (val)) {
Recursively format columns If list is a multi-dimensional array:
Return Lib.formatcolumn (Val, opts);
} else {
Clean up the value
val = Unformat (val);
Choose which format to with this value (pos, neg or zero):
var UseFormat = val > 0? Formats.pos:val < 0? Formats.neg:formats.zero,
Format this value, push into formatted list and save the length:
fval = Useformat.replace ('%s ', opts.symbol). Replace ('%v ', FormatNumber (Math.Abs (Val), Checkprecision (opts.precision ), Opts.thousand, opts.decimal);
if (Fval.length > maxLength) maxLength = fval.length;
return fval;
}
});
Pad each number in the list and send back the column of numbers:
Return map (formatted, function (val, i) {
Only if you are a string (not a nested array, which would have already been):
if (Isstring (val) && Val.length < maxLength) {
Depending on symbol position, pad after symbol or at index 0:
Return Padaftersymbol? Val.replace (Opts.symbol, opts.symbol+ (new Array (Maxlength-val.length + 1). Join ("")): (New Array (maxlength-val.lengt H + 1). Join ("")) + Val;
}
return Val;
});
};
/*---Module Definition---*/
Export accounting for Commonjs. If being loaded as an AMD module, define it as such.
Otherwise, just add ' accounting ' to the global object
if (typeof exports!== ' undefined ') {
if (typeof module!== ' undefined ' && module.exports) {
Exports = Module.exports = Lib;
}
Exports.accounting = Lib;
else if (typeof define = = ' function ' && define.amd) {
Return to the library as an AMD module:
define ([], function () {
Return lib;
});
} else {
Use accounting.noconflict to restore ' accounting ' back to its original value.
Returns a reference to the library ' s ' Accounting ' object;
e.g. ' var numbers = accounting.noconflict (); '
Lib.noconflict = (function (oldaccounting) {
return function () {
Reset the value of the root ' s ' Accounting ' variable:
root.accounting = oldaccounting;
Delete the Noconflict method:
lib.noconflict = undefined;
Return reference to the library to re-assign it:
Return lib;
};
}) (root.accounting);
Declare ' FX ' on the root (Global/window) object:
root[' accounting '] = lib;
}
Root would be ' windows ' in browser or ' global ' on the server:
} (this));
Official Download Address: Https://raw.github.com/josscrowcroft/accounting.js/master/accounting.js
Working with instances
Formatmoney
Copy Code code as follows:
Formatmoney
Default usage:
Accounting.formatmoney (12345678); $12,345,678.00
European Formatting (custom symbol and separators), could also use options object as second param:
Accounting.formatmoney (4999.99, "?", 2, ".", ","); ? 4.999,99
Negative values are formatted nicely, too:
Accounting.formatmoney (-500000, "£", 0); £-500,000
Simple ' format ' string allows control of symbol position [%V = value,%s = symbol]:
Accounting.formatmoney (5318008, {symbol: "GBP", Format: "%v%s"}); 5,318,008.00 GBP
FormatNumber
Copy Code code as follows:
Accounting.formatnumber (5318008); 5,318,008
Accounting.formatnumber (9876543.21, 3, ""); 9 876 543.210
Unformat
Copy Code code as follows:
Accounting.unformat ("£12,345,678.90 GBP"); 12345678.9
Official Demo Example: http://josscrowcroft.github.com/accounting.js/
Cloud Habitat Community Download address Accounting.js