| // numeral.js |
| // version : 1.4.7 |
| // author : Adam Draper |
| // license : MIT |
| // http://adamwdraper.github.com/Numeral-js/ |
| |
| (function () { |
| |
| /************************************ |
| Constants |
| ************************************/ |
| |
| var numeral, |
| VERSION = '1.4.7', |
| // internal storage for language config files |
| languages = {}, |
| currentLanguage = 'en', |
| zeroFormat = null, |
| // check for nodeJS |
| hasModule = (typeof module !== 'undefined' && module.exports); |
| |
| |
| /************************************ |
| Constructors |
| ************************************/ |
| |
| |
| // Numeral prototype object |
| function Numeral (number) { |
| this._n = number; |
| } |
| |
| /** |
| * Implementation of toFixed() that 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. |
| */ |
| function toFixed (value, precision, optionals) { |
| var power = Math.pow(10, precision), |
| output; |
| |
| // Multiply up by precision, round accurately, then divide and use native toFixed(): |
| output = (Math.round(value * power) / power).toFixed(precision); |
| |
| if (optionals) { |
| var optionalsRegExp = new RegExp('0{1,' + optionals + '}$'); |
| output = output.replace(optionalsRegExp, ''); |
| } |
| |
| return output; |
| } |
| |
| /************************************ |
| Formatting |
| ************************************/ |
| |
| // determine what type of formatting we need to do |
| function formatNumeral (n, format) { |
| var output; |
| |
| // figure out what kind of format we are dealing with |
| if (format.indexOf('$') > -1) { // currency!!!!! |
| output = formatCurrency(n, format); |
| } else if (format.indexOf('%') > -1) { // percentage |
| output = formatPercentage(n, format); |
| } else if (format.indexOf(':') > -1) { // time |
| output = formatTime(n, format); |
| } else { // plain ol' numbers or bytes |
| output = formatNumber(n, format); |
| } |
| |
| // return string |
| return output; |
| } |
| |
| // revert to number |
| function unformatNumeral (n, string) { |
| if (string.indexOf(':') > -1) { |
| n._n = unformatTime(string); |
| } else { |
| if (string === zeroFormat) { |
| n._n = 0; |
| } else { |
| var stringOriginal = string; |
| if (languages[currentLanguage].delimiters.decimal !== '.') { |
| string = string.replace(/\./g,'').replace(languages[currentLanguage].delimiters.decimal, '.'); |
| } |
| |
| // see if abbreviations are there so that we can multiply to the correct number |
| var thousandRegExp = new RegExp(languages[currentLanguage].abbreviations.thousand + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'), |
| millionRegExp = new RegExp(languages[currentLanguage].abbreviations.million + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'), |
| billionRegExp = new RegExp(languages[currentLanguage].abbreviations.billion + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'), |
| trillionRegExp = new RegExp(languages[currentLanguage].abbreviations.trillion + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'); |
| |
| // see if bytes are there so that we can multiply to the correct number |
| var prefixes = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], |
| bytesMultiplier = false; |
| |
| for (var power = 0; power <= prefixes.length; power++) { |
| bytesMultiplier = (string.indexOf(prefixes[power]) > -1) ? Math.pow(1024, power + 1) : false; |
| |
| if (bytesMultiplier) { |
| break; |
| } |
| } |
| |
| // do some math to create our number |
| n._n = ((bytesMultiplier) ? bytesMultiplier : 1) * ((stringOriginal.match(thousandRegExp)) ? Math.pow(10, 3) : 1) * ((stringOriginal.match(millionRegExp)) ? Math.pow(10, 6) : 1) * ((stringOriginal.match(billionRegExp)) ? Math.pow(10, 9) : 1) * ((stringOriginal.match(trillionRegExp)) ? Math.pow(10, 12) : 1) * ((string.indexOf('%') > -1) ? 0.01 : 1) * Number(((string.indexOf('(') > -1) ? '-' : '') + string.replace(/[^0-9\.-]+/g, '')); |
| |
| // round if we are talking about bytes |
| n._n = (bytesMultiplier) ? Math.ceil(n._n) : n._n; |
| } |
| } |
| return n._n; |
| } |
| |
| function formatCurrency (n, format) { |
| var prependSymbol = (format.indexOf('$') <= 1) ? true : false; |
| |
| // remove $ for the moment |
| var space = ''; |
| |
| // check for space before or after currency |
| if (format.indexOf(' $') > -1) { |
| space = ' '; |
| format = format.replace(' $', ''); |
| } else if (format.indexOf('$ ') > -1) { |
| space = ' '; |
| format = format.replace('$ ', ''); |
| } else { |
| format = format.replace('$', ''); |
| } |
| |
| // format the number |
| var output = formatNumeral(n, format); |
| |
| // position the symbol |
| if (prependSymbol) { |
| if (output.indexOf('(') > -1 || output.indexOf('-') > -1) { |
| output = output.split(''); |
| output.splice(1, 0, languages[currentLanguage].currency.symbol + space); |
| output = output.join(''); |
| } else { |
| output = languages[currentLanguage].currency.symbol + space + output; |
| } |
| } else { |
| if (output.indexOf(')') > -1) { |
| output = output.split(''); |
| output.splice(-1, 0, space + languages[currentLanguage].currency.symbol); |
| output = output.join(''); |
| } else { |
| output = output + space + languages[currentLanguage].currency.symbol; |
| } |
| } |
| |
| return output; |
| } |
| |
| function formatPercentage (n, format) { |
| var space = ''; |
| // check for space before % |
| if (format.indexOf(' %') > -1) { |
| space = ' '; |
| format = format.replace(' %', ''); |
| } else { |
| format = format.replace('%', ''); |
| } |
| |
| n._n = n._n * 100; |
| var output = formatNumeral(n, format); |
| if (output.indexOf(')') > -1 ) { |
| output = output.split(''); |
| output.splice(-1, 0, space + '%'); |
| output = output.join(''); |
| } else { |
| output = output + space + '%'; |
| } |
| return output; |
| } |
| |
| function formatTime (n, format) { |
| var hours = Math.floor(n._n/60/60), |
| minutes = Math.floor((n._n - (hours * 60 * 60))/60), |
| seconds = Math.round(n._n - (hours * 60 * 60) - (minutes * 60)); |
| return hours + ':' + ((minutes < 10) ? '0' + minutes : minutes) + ':' + ((seconds < 10) ? '0' + seconds : seconds); |
| } |
| |
| function unformatTime (string) { |
| var timeArray = string.split(':'), |
| seconds = 0; |
| // turn hours and minutes into seconds and add them all up |
| if (timeArray.length === 3) { |
| // hours |
| seconds = seconds + (Number(timeArray[0]) * 60 * 60); |
| // minutes |
| seconds = seconds + (Number(timeArray[1]) * 60); |
| // seconds |
| seconds = seconds + Number(timeArray[2]); |
| } else if (timeArray.lenght === 2) { |
| // minutes |
| seconds = seconds + (Number(timeArray[0]) * 60); |
| // seconds |
| seconds = seconds + Number(timeArray[1]); |
| } |
| return Number(seconds); |
| } |
| |
| function formatNumber (n, format) { |
| var negP = false, |
| optDec = false, |
| abbr = '', |
| bytes = '', |
| ord = '', |
| abs = Math.abs(n._n); |
| |
| // check if number is zero and a custom zero format has been set |
| if (n._n === 0 && zeroFormat !== null) { |
| return zeroFormat; |
| } else { |
| // see if we should use parentheses for negative number |
| if (format.indexOf('(') > -1) { |
| negP = true; |
| format = format.slice(1, -1); |
| } |
| |
| // see if abbreviation is wanted |
| if (format.indexOf('a') > -1) { |
| // check for space before abbreviation |
| if (format.indexOf(' a') > -1) { |
| abbr = ' '; |
| format = format.replace(' a', ''); |
| } else { |
| format = format.replace('a', ''); |
| } |
| |
| if (abs >= Math.pow(10, 12)) { |
| // trillion |
| abbr = abbr + languages[currentLanguage].abbreviations.trillion; |
| n._n = n._n / Math.pow(10, 12); |
| } else if (abs < Math.pow(10, 12) && abs >= Math.pow(10, 9)) { |
| // billion |
| abbr = abbr + languages[currentLanguage].abbreviations.billion; |
| n._n = n._n / Math.pow(10, 9); |
| } else if (abs < Math.pow(10, 9) && abs >= Math.pow(10, 6)) { |
| // million |
| abbr = abbr + languages[currentLanguage].abbreviations.million; |
| n._n = n._n / Math.pow(10, 6); |
| } else if (abs < Math.pow(10, 6) && abs >= Math.pow(10, 3)) { |
| // thousand |
| abbr = abbr + languages[currentLanguage].abbreviations.thousand; |
| n._n = n._n / Math.pow(10, 3); |
| } |
| } |
| |
| // see if we are formatting bytes |
| if (format.indexOf('b') > -1) { |
| // check for space before |
| if (format.indexOf(' b') > -1) { |
| bytes = ' '; |
| format = format.replace(' b', ''); |
| } else { |
| format = format.replace('b', ''); |
| } |
| |
| var prefixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], |
| min, |
| max; |
| |
| for (var power = 0; power <= prefixes.length; power++) { |
| min = Math.pow(1024, power); |
| max = Math.pow(1024, power+1); |
| |
| if (n._n >= min && n._n < max) { |
| bytes = bytes + prefixes[power]; |
| if (min > 0) { |
| n._n = n._n / min; |
| } |
| break; |
| } |
| } |
| } |
| |
| // see if ordinal is wanted |
| if (format.indexOf('o') > -1) { |
| // check for space before |
| if (format.indexOf(' o') > -1) { |
| ord = ' '; |
| format = format.replace(' o', ''); |
| } else { |
| format = format.replace('o', ''); |
| } |
| |
| ord = ord + languages[currentLanguage].ordinal(n._n); |
| } |
| |
| if (format.indexOf('[.]') > -1) { |
| optDec = true; |
| format = format.replace('[.]', '.'); |
| } |
| |
| var w = n._n.toString().split('.')[0], |
| precision = format.split('.')[1], |
| thousands = format.indexOf(','), |
| d = '', |
| neg = false; |
| |
| if (precision) { |
| if (precision.indexOf('[') > -1) { |
| precision = precision.replace(']', ''); |
| precision = precision.split('['); |
| d = toFixed(n._n, (precision[0].length + precision[1].length), precision[1].length); |
| } else { |
| d = toFixed(n._n, precision.length); |
| } |
| |
| w = d.split('.')[0]; |
| |
| if (d.split('.')[1].length) { |
| d = languages[currentLanguage].delimiters.decimal + d.split('.')[1]; |
| } else { |
| d = ''; |
| } |
| |
| if (optDec && Number(d) === 0) { |
| d = ''; |
| } |
| } else { |
| w = toFixed(n._n, null); |
| } |
| |
| // format number |
| if (w.indexOf('-') > -1) { |
| w = w.slice(1); |
| neg = true; |
| } |
| |
| if (thousands > -1) { |
| w = w.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + languages[currentLanguage].delimiters.thousands); |
| } |
| |
| if (format.indexOf('.') === 0) { |
| w = ''; |
| } |
| |
| return ((negP && neg) ? '(' : '') + ((!negP && neg) ? '-' : '') + w + d + ((ord) ? ord : '') + ((abbr) ? abbr : '') + ((bytes) ? bytes : '') + ((negP && neg) ? ')' : ''); |
| } |
| } |
| |
| /************************************ |
| Top Level Functions |
| ************************************/ |
| |
| numeral = function (input) { |
| if (numeral.isNumeral(input)) { |
| input = input.value(); |
| } else if (!Number(input)) { |
| input = 0; |
| } |
| |
| return new Numeral(Number(input)); |
| }; |
| |
| // version number |
| numeral.version = VERSION; |
| |
| // compare numeral object |
| numeral.isNumeral = function (obj) { |
| return obj instanceof Numeral; |
| }; |
| |
| // This function will load languages and then set the global language. If |
| // no arguments are passed in, it will simply return the current global |
| // language key. |
| numeral.language = function (key, values) { |
| if (!key) { |
| return currentLanguage; |
| } |
| |
| if (key && !values) { |
| currentLanguage = key; |
| } |
| |
| if (values || !languages[key]) { |
| loadLanguage(key, values); |
| } |
| |
| return numeral; |
| }; |
| |
| numeral.language('en', { |
| delimiters: { |
| thousands: ',', |
| decimal: '.' |
| }, |
| abbreviations: { |
| thousand: 'k', |
| million: 'm', |
| billion: 'b', |
| trillion: 't' |
| }, |
| ordinal: function (number) { |
| var b = number % 10; |
| return (~~ (number % 100 / 10) === 1) ? 'th' : |
| (b === 1) ? 'st' : |
| (b === 2) ? 'nd' : |
| (b === 3) ? 'rd' : 'th'; |
| }, |
| currency: { |
| symbol: '$' |
| } |
| }); |
| |
| numeral.zeroFormat = function (format) { |
| if (typeof(format) === 'string') { |
| zeroFormat = format; |
| } else { |
| zeroFormat = null; |
| } |
| }; |
| |
| /************************************ |
| Helpers |
| ************************************/ |
| |
| function loadLanguage(key, values) { |
| languages[key] = values; |
| } |
| |
| |
| /************************************ |
| Numeral Prototype |
| ************************************/ |
| |
| |
| numeral.fn = Numeral.prototype = { |
| |
| clone : function () { |
| return numeral(this); |
| }, |
| |
| format : function (inputString) { |
| return formatNumeral(this, inputString ? inputString : numeral.defaultFormat); |
| }, |
| |
| unformat : function (inputString) { |
| return unformatNumeral(this, inputString ? inputString : numeral.defaultFormat); |
| }, |
| |
| value : function () { |
| return this._n; |
| }, |
| |
| valueOf : function () { |
| return this._n; |
| }, |
| |
| set : function (value) { |
| this._n = Number(value); |
| return this; |
| }, |
| |
| add : function (value) { |
| this._n = this._n + Number(value); |
| return this; |
| }, |
| |
| subtract : function (value) { |
| this._n = this._n - Number(value); |
| return this; |
| }, |
| |
| multiply : function (value) { |
| this._n = this._n * Number(value); |
| return this; |
| }, |
| |
| divide : function (value) { |
| this._n = this._n / Number(value); |
| return this; |
| }, |
| |
| difference : function (value) { |
| var difference = this._n - Number(value); |
| |
| if (difference < 0) { |
| difference = -difference; |
| } |
| |
| return difference; |
| } |
| |
| }; |
| |
| /************************************ |
| Exposing Numeral |
| ************************************/ |
| |
| // CommonJS module is defined |
| if (hasModule) { |
| module.exports = numeral; |
| } |
| |
| /*global ender:false */ |
| if (typeof ender === 'undefined') { |
| // here, `this` means `window` in the browser, or `global` on the server |
| // add `numeral` as a global object via a string identifier, |
| // for Closure Compiler 'advanced' mode |
| this['numeral'] = numeral; |
| } |
| |
| /*global define:false */ |
| if (typeof define === 'function' && define.amd) { |
| define([], function () { |
| return numeral; |
| }); |
| } |
| }).call(this); |