numeral
Version:
Format and manipulate numbers.
304 lines (245 loc) • 8.67 kB
JavaScript
// numeral.js
// version : 1.0.4
// author : Adam Draper
// license : MIT
// http://adamwdraper.github.com/Numeral-js/
(function () {
/************************************
Constants
************************************/
var numeral,
VERSION = '1.0.4',
round = Math.round, i,
// 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) {
var power = Math.pow(10, precision);
// Multiply up by precision, round accurately, then divide and use native toFixed():
return (Math.round(value * power) / power).toFixed(precision);
}
/************************************
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) { // money!!!!!
output = formatMoney(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' number
output = formatNumber(n, format);
}
// return string
return output;
}
// revert to number
function unformatNumeral (n, string) {
if (string.indexOf(':') > -1) {
n._n = unformatTime(string);
} else {
n._n = ((string.indexOf('k') > -1) ? 1000 : 1) * ((string.indexOf('m') > -1) ? 1000000 : 1) * ((string.indexOf('%') > -1) ? 0.01 : 1) * Number(((string.indexOf('(') > -1) ? '-' : '') + string.replace(/\$|,|%|k|m|th|st|nd|rd|\(|\)*/ig, ''));
}
return n._n;
}
function formatMoney (n, format) {
format = format.replace('$', '');
var output = formatNumeral(n, format);
if (output.indexOf('(') > -1 || output.indexOf('-') > -1) {
output = output.split('');
output.splice(1, 0, '$');
output = output.join('');
} else {
output = '$' + output;
}
return output;
}
function formatPercentage (n, format) {
format = format.replace('%', '');
n._n = n._n * 100;
var output = formatNumeral(n, format);
if (output.indexOf(')') > -1 ) {
output = output.split('');
output.splice(-1, 0, '%');
output = output.join('');
} else {
output = output + '%';
}
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,
abbr = false,
ord = false;
// 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) {
format = format.replace('a', '');
if (n._n > 1000000) {
abbr = 'm';
n._n = n._n / 1000000;
} else {
abbr = 'k';
n._n = n._n / 1000;
}
}
// see if ordinal is wanted
if (format.indexOf('o') > -1) {
format = format.replace('o', '');
var r = n._n % 100,
suffix = ['th', 'st', 'nd', 'rd', 'th'];
ord = r < 21 ? (r < 4 ? suffix[r] : suffix[0]) : (r % 10 > 4 ? suffix[0] : suffix[r % 10]);
}
var w = n._n.toString().split('.')[0],
precision = format.split('.')[1],
thousands = format.indexOf(','),
d = '',
neg = false;
// format number
if (n._n < 0) {
w = w.slice(1);
neg = true;
}
if (thousands > -1) {
w = w.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
}
if (format.indexOf('.') === 0) {
w = '';
}
if (precision) {
// do to fixed
d = '.' + toFixed(n._n, precision.length).split('.')[1];
}
if (abbr) {
}
return ((negP && neg) ? '(' : '') + ((!negP && neg) ? '-' : '') + w + d + ((ord) ? ord : '') + ((abbr) ? abbr : '') + ((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));
};
// compare numeral object
numeral.isNumeral = function (obj) {
console.log(obj);
return obj instanceof Numeral;
};
// version number
numeral.version = VERSION;
// compare numeral object
numeral.isNumeral = function (obj) {
return obj instanceof Numeral;
};
/************************************
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;
},
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) {
return this._n - Number(value);
}
};
/************************************
Exposing Numeral
************************************/
// Commenting out common js and global variable
// // 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);