UNPKG

numformat.js

Version:

number, decimal, integer, money and currency formatting library, with two way custom format/unformat symbols and patterns

279 lines (230 loc) 8.6 kB
(function(factory) { // Establish the root object, `window` (`self`) in the browser, or `global` on the server. // We use `self` instead of `window` for `WebWorker` support. var root = (typeof self == 'object' && self.self == self && self) || (typeof global == 'object' && global.global == global && global); // Set up nf appropriately for the environment. Start with AMD. if (typeof define === 'function' && define.amd) { define(['exports'], function(exports) { // Export global even in AMD case in case this script is loaded with // others that may still expect a global nf. root.nf = factory(root, exports); }); // Next for Node.js or CommonJS. jQuery may not be needed as a module. } else if (typeof exports !== 'undefined') { factory(root, exports); // Finally, as a browser global. } else { root.nf = factory(root, {}); } }(function(root, nf) { //--utilities function clone(o) { var out, v, key; out = Array.isArray(o) ? [] : {}; for (key in o) { v = o[key]; out[key] = (typeof v === "object") ? clone(v) : v; } return out; } function extend(o, ox) { if(!ox) return o; for(var key in ox) { if(ox[key] != null) o[key] = ox[key]; } return o; } function escapeRegexp(s) { return String(s).replace(/[\\^$*+?.()|[\]{}]/g, '\\$&'); } //--from //https://github.com/component/pad function pad(str, len, c) { c = c || ' '; if (str.length >= len) return str; len = len - str.length; var left = new Array(Math.ceil(len / 2) + 1).join(c); var right = new Array(Math.floor(len / 2) + 1).join(c); return left + str + right; } function padLeft(str, len, c){ c = c || ' '; if (str.length >= len) return str; return new Array(len - str.length + 1).join(c) + str; } function padRight(str, len, c){ c = c || ' '; if (str.length >= len) return str; return str + new Array(len - str.length + 1).join(c); } //-- var defaultLanguageSettings = { integer: { decimalPlaces: 0, //%d decimalSeparator: '.', //%s thousandSeparator: ',', currencySymbol: '', //%c negativeSymbol: '-', //%n pattern: '%n%i%s%d%c', emptyValue: '', toFixed: true }, number: { decimalPlaces: 2, decimalSeparator: '.', thousandSeparator: ',', currencySymbol: '', negativeSymbol: '-', pattern: '%n%i%s%d%c', emptyValue: '', toFixed: true }, currency: { decimalPlaces: 2, decimalSeparator: '.', thousandSeparator: ',', currencySymbol: '$', negativeSymbol: '-', pattern: '%n%i%s%d%c', emptyValue: '', toFixed: true } }; nf.languages = {}; nf.loadLanguage = function(language, languageSettings) { var currentLanguage = extendSettings(cloneSettings(defaultLanguageSettings), nf.languages[language] || {}); nf.languages[language] = extendSettings(currentLanguage, languageSettings); nf.language = language; }; nf.loadLanguage('en', {}); function cloneSettings(settings) { return { integer: clone(settings.integer), number: clone(settings.number), currency: clone(settings.currency) }; } function extendSettings(settings, xsettings) { extend(settings.integer, xsettings.integer); extend(settings.number, xsettings.number); extend(settings.currency, xsettings.currency); return settings; } function getOptions(type, language) { var currentLanguage = language ? language : nf.language; if(nf.languages[currentLanguage] instanceof Object) { return clone(nf.languages[currentLanguage][type]); } else { return cloneSettings(defaultLanguageSettings); } } function toFixedValue(value, decimalPlaces) { return (value < 0 ? -1 : 1) * parseFloat(Math.round(Math.abs(value) * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces)) } nf.formatNumber = function(value, options) { var opts = getOptions('number'); extend(opts, options); value += ''; //handling ".123" if(value.charAt(0) == '.') value = '0' + value; //handling "-.123" if(value.charAt(0) == '-' && value.charAt(1) == '.' ) { value.replace('.','0.'); } value = parseFloat(value); //rounding decimals if(opts.toFixed) value = toFixedValue(value, opts.decimalPlaces); if(isNaN(value) || value === 0) { return opts.emptyValue; } value += ''; var sign = ''; if(value.indexOf('-') >= 0) { sign = opts.negativeSymbol; value = value.replace(/-/g,''); } var leftPart = ''; var valueArray = value.split('.'); var left = valueArray[0]; var right = valueArray[1] ? valueArray[1] : ''; var decimalSeparator = ''; if(opts.decimalPlaces > 0) { decimalSeparator = opts.decimalSeparator; if(opts.toFixed) right = padRight(right, opts.decimalPlaces, '0'); else if(right.length == 0) decimalSeparator = ''; //remove decimalSeparator when handling integer without toFixed } if(opts.thousandSeparator != null && opts.thousandSeparator !== '') { while (left.length > 3) { var l = left.substr(0, left.length-3); var r = left.substr(left.length-3, left.length-1); left = l + opts.thousandSeparator + r; leftPart = opts.thousandSeparator + r + leftPart; left = left.substr(0, left.indexOf(opts.thousandSeparator)).toString(); } } else { leftPart = ''; } leftPart = left + leftPart; value = opts.pattern .replace(new RegExp('%n'), sign) .replace(new RegExp('%i'), leftPart) .replace(new RegExp('%s'), decimalSeparator) .replace(new RegExp('%d'), right) .replace(new RegExp('%c'), opts.currencySymbol); // value = ((leftPart != '') ? leftPart : left )+ right; return value; }; nf.unformatNumber = function(value, options, toFixed) { //TODO use options.pattern to unformat? var opts = getOptions('number'); extend(opts, options); value += ''; value = value.replace(new RegExp(escapeRegexp(opts.thousandSeparator), 'g'), '') .replace(new RegExp(escapeRegexp(opts.currencySymbol), 'g'), '') .replace(new RegExp(escapeRegexp(opts.decimalSeparator), 'g'), '.') .replace(new RegExp(escapeRegexp(opts.negativeSymbol)), '-') .replace(/[\s]/g, ''); var floatValue = parseFloat(value); if(isNaN(floatValue)) { if(value.match(new RegExp(escapeRegexp(opts.emptyValue)))) { return 0; } else { return null; } } else if(toFixed == true) { return toFixedValue(floatValue, opts.decimalPlaces); } else { return parseFloat(floatValue); } }; nf.formatInteger = function(value, options) { var opts = getOptions('integer'); extend(opts, options); return nf.formatNumber(value, opts); }; nf.unformatInteger = function(value, options) { var opts = getOptions('integer'); extend(opts, options); value = parseInt(nf.unformatNumber(value, opts), 10); if(isNaN(value)) return 0; else return value; }; nf.formatCurrency = function (value, options) { var opts = getOptions('currency'); extend(opts, options); return nf.formatNumber(value, opts); }; nf.unformatCurrency = nf.parseCurrency = function (value, options, toFixed) { var opts = getOptions('currency'); extend(opts, options); return nf.unformatNumber(value, opts, toFixed); }; return nf; }));