aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDi Peng2011-07-23 17:05:20 -0700
committerIgor Minar2011-07-26 14:16:57 -0700
commit31b59efa961e8729a0153d7d6ea5e300d7db17f2 (patch)
tree74088ab4040111710b7c55a1c6049801730fb654 /src
parent17251372b1dedb42d27b01375125cee4f5edcce7 (diff)
downloadangular.js-31b59efa961e8729a0153d7d6ea5e300d7db17f2.tar.bz2
feat(number/currency filter): format numbers and currency using pattern
both numbers and currency need to be formatted using a generic pattern which can be replaced for a different pattern when angular is working in a non en-US locale for now only en-US locale is supported, but that will change in the future
Diffstat (limited to 'src')
-rw-r--r--src/filters.js121
1 files changed, 86 insertions, 35 deletions
diff --git a/src/filters.js b/src/filters.js
index 8fac671d..40bf2157 100644
--- a/src/filters.js
+++ b/src/filters.js
@@ -35,9 +35,11 @@
* @function
*
* @description
- * Formats a number as a currency (ie $1,234.56).
+ * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
+ * symbol for current locale is used.
*
* @param {number} amount Input to filter.
+ * @param {string=} symbol Currency symbol or identifier to be displayed.
* @returns {string} Formated number.
*
* @css ng-format-negative
@@ -47,24 +49,28 @@
<doc:example>
<doc:source>
<input type="text" name="amount" value="1234.56"/> <br/>
- {{amount | currency}}
+ default currency symbol ($): {{amount | currency}}<br/>
+ custom currency identifier (USD$): {{amount | currency:"USD$"}}
</doc:source>
<doc:scenario>
it('should init with 1234.56', function(){
expect(binding('amount | currency')).toBe('$1,234.56');
+ expect(binding('amount | currency:"USD$"')).toBe('USD$1,234.56');
});
it('should update', function(){
input('amount').enter('-1234');
- expect(binding('amount | currency')).toBe('$-1,234.00');
+ expect(binding('amount | currency')).toBe('($1,234.00)');
+ expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)');
expect(element('.doc-example-live .ng-binding').attr('className')).
toMatch(/ng-format-negative/);
});
</doc:scenario>
</doc:example>
*/
-angularFilter.currency = function(amount){
+angularFilter.currency = function(amount, currencySymbol){
this.$element.toggleClass('ng-format-negative', amount < 0);
- return '$' + angularFilter.number.apply(this, [amount, 2]);
+ if (isUndefined(currencySymbol)) currencySymbol = NUMBER_FORMATS.CURRENCY_SYM;
+ return formatNumber(amount, 2, 1).replace(/\u00A4/g, currencySymbol);
};
/**
@@ -74,9 +80,9 @@ angularFilter.currency = function(amount){
* @function
*
* @description
- * Formats a number as text.
+ * Formats a number as text.
*
- * If the input is not a number empty string is returned.
+ * If the input is not a number empty string is returned.
*
* @param {number|string} number Number to format.
* @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to.
@@ -92,59 +98,104 @@ angularFilter.currency = function(amount){
</doc:source>
<doc:scenario>
it('should format numbers', function(){
- expect(binding('val | number')).toBe('1,234.57');
+ expect(binding('val | number')).toBe('1,234.568');
expect(binding('val | number:0')).toBe('1,235');
expect(binding('-val | number:4')).toBe('-1,234.5679');
});
it('should update', function(){
input('val').enter('3374.333');
- expect(binding('val | number')).toBe('3,374.33');
+ expect(binding('val | number')).toBe('3,374.333');
expect(binding('val | number:0')).toBe('3,374');
expect(binding('-val | number:4')).toBe('-3,374.3330');
});
</doc:scenario>
</doc:example>
*/
-angularFilter.number = function(number, fractionSize){
- if (isNaN(number) || !isFinite(number)) {
- return '';
- }
- fractionSize = isUndefined(fractionSize)? 2 : fractionSize;
+// PATTERNS[0] is an array for Decimal Pattern, PATTERNS[1] is an array Currency Pattern
+// Following is the order in each pattern array:
+// 0: minInteger,
+// 1: minFraction,
+// 2: maxFraction,
+// 3: positivePrefix,
+// 4: positiveSuffix,
+// 5: negativePrefix,
+// 6: negativeSuffix,
+// 7: groupSize,
+// 8: lastGroupSize
+var NUMBER_FORMATS = {
+ DECIMAL_SEP: '.',
+ GROUP_SEP: ',',
+ PATTERNS: [[1, 0, 3, '', '', '-', '', 3, 3],[1, 2, 2, '\u00A4', '', '(\u00A4', ')', 3, 3]],
+ CURRENCY_SYM: '$'
+};
+var DECIMAL_SEP = '.';
+
+angularFilter.number = function(number, fractionSize) {
+ if (isNaN(number) || !isFinite(number)) return '';
+ return formatNumber(number, fractionSize, 0);
+}
+
+function formatNumber(number, fractionSize, type) {
var isNegative = number < 0,
- pow = Math.pow(10, fractionSize),
- whole = '' + number,
+ type = type || 0, // 0 is decimal pattern, 1 is currency pattern
+ pattern = NUMBER_FORMATS.PATTERNS[type];
+
+ number = Math.abs(number);
+ var numStr = number + '',
formatedText = '',
- i, fraction;
+ parts = [];
- if (whole.indexOf('e') > -1) return whole;
+ if (numStr.indexOf('e') !== -1) {
+ var formatedText = numStr;
+ } else {
+ var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
- number = Math.round(number * pow) / pow;
- fraction = ('' + number).split('.');
- whole = fraction[0];
- fraction = fraction[1] || '';
- if (isNegative) {
- formatedText = '-';
- whole = whole.substring(1);
- }
+ //determine fractionSize if it is not specified
+ if (isUndefined(fractionSize)) {
+ fractionSize = Math.min(Math.max(pattern[1], fractionLen), pattern[2]);
+ }
+ var pow = Math.pow(10, fractionSize);
+ number = Math.round(number * pow) / pow;
+ var fraction = ('' + number).split(DECIMAL_SEP);
+ var whole = fraction[0];
+ fraction = fraction[1] || '';
+
+ var pos = 0,
+ lgroup = pattern[8],
+ group = pattern[7];
+
+ if (whole.length >= (lgroup + group)) {
+ pos = whole.length - lgroup;
+ for (var i = 0; i < pos; i++) {
+ if ((pos - i)%group === 0 && i !== 0) {
+ formatedText += NUMBER_FORMATS.GROUP_SEP;
+ }
+ formatedText += whole.charAt(i);
+ }
+ }
- for (i = 0; i < whole.length; i++) {
- if ((whole.length - i)%3 === 0 && i !== 0) {
- formatedText += ',';
+ for (i = pos; i < whole.length; i++) {
+ if ((whole.length - i)%lgroup === 0 && i !== 0) {
+ formatedText += NUMBER_FORMATS.GROUP_SEP;
+ }
+ formatedText += whole.charAt(i);
}
- formatedText += whole.charAt(i);
- }
- if (fractionSize) {
+
+ // format fraction part.
while(fraction.length < fractionSize) {
fraction += '0';
}
- formatedText += '.' + fraction.substring(0, fractionSize);
+ if (fractionSize) formatedText += NUMBER_FORMATS.DECIMAL_SEP + fraction.substr(0, fractionSize);
}
- return formatedText;
-};
+ parts.push(isNegative ? pattern[5] : pattern[3]);
+ parts.push(formatedText);
+ parts.push(isNegative ? pattern[6] : pattern[4]);
+ return parts.join('');
+}
function padNumber(num, digits, trim) {
var neg = '';