1
1
'use strict' ;
2
2
3
+ var MAX_DIGITS = 22 ;
4
+ var DECIMAL_SEP = '.' ;
5
+ var ZERO_CHAR = '0' ;
6
+
3
7
/**
4
8
* @ngdoc filter
5
9
* @name currency
@@ -137,10 +141,16 @@ function numberFilter($locale) {
137
141
} ;
138
142
}
139
143
140
- var MAX_DIGITS = 22 ;
141
- var DECIMAL_SEP = '.' ;
142
- var ZERO_CHAR = '0' ;
143
-
144
+ /**
145
+ * parse a number (as a string) into three components that can be used
146
+ * for formatting the number
147
+ * @param {string } numStr The number to parse
148
+ * @return {object } An object describing this number, containing the following keys:
149
+ * - d : an array of digits containing leading zeros as necessary
150
+ * - i : the number of the digits in `d` that are to the left of the decimal point
151
+ * - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d`
152
+ *
153
+ */
144
154
function parse ( numStr ) {
145
155
var exponent = 0 , digits , integerLen ;
146
156
var e , i , j , zeros ;
@@ -184,47 +194,48 @@ function parse(numStr) {
184
194
integerLen = 1 ;
185
195
}
186
196
187
- return { digits : digits , exponent : exponent , integerLen : integerLen } ;
197
+ return { d : digits , e : exponent , i : integerLen } ;
188
198
}
189
199
200
+ /**
201
+ * Round the parsed number to the specified number of decimal places
202
+ * This function changed the parsedNumber in-place
203
+ */
190
204
function roundNumber ( parsedNumber , fractionSize , minFrac , maxFrac ) {
191
- var digit = 0 ;
192
- var digits = parsedNumber . digits ;
193
- var fractionLen = digits . length - parsedNumber . integerLen ;
205
+ var digits = parsedNumber . d ;
206
+ var fractionLen = digits . length - parsedNumber . i ;
194
207
195
- // determine fractionSize if it is not specified
196
- if ( isUndefined ( fractionSize ) ) {
197
- fractionSize = Math . min ( Math . max ( minFrac , fractionLen ) , maxFrac ) ;
198
- }
208
+ // determine fractionSize if it is not specified; `+fractionSize` converts it to a number
209
+ fractionSize = ( isUndefined ( fractionSize ) ) ? Math . min ( Math . max ( minFrac , fractionLen ) , maxFrac ) : + fractionSize ;
199
210
200
- // Cut off unwanted digits with rounding
201
- for ( ; fractionLen > fractionSize && digits . length ; fractionLen -- ) {
202
- digit = digits . pop ( ) ;
203
- // Round up if necessary
204
- if ( digit >= 5 ) digits [ digits . length - 1 ] ++ ;
205
- }
211
+ // The indec of the digit to where rounding is to occur
212
+ var roundAt = fractionSize + parsedNumber . i ;
213
+ var digit = digits [ roundAt ] ;
206
214
207
- if ( ! digits . length ) {
215
+ if ( roundAt > 0 ) {
216
+ digits . splice ( roundAt ) ;
217
+ } else {
208
218
// We rounded to zero so reset the parsedNumber
209
- parsedNumber . integerLen = 1 ;
210
- // If the last removed digit was >= 5 then we need to round up
211
- if ( digit >= 5 ) digits . push ( 1 ) ;
212
- // Pad out with the necessary zeros
213
- while ( digits . length <= fractionSize ) digits . unshift ( 0 ) ;
219
+ parsedNumber . i = 1 ;
220
+ digits . length = roundAt = fractionSize + 1 ;
221
+ for ( var i = 0 ; i < roundAt ; i ++ ) digits [ i ] = 0 ;
214
222
}
215
223
224
+ if ( digit >= 5 ) digits [ roundAt - 1 ] ++ ;
225
+
216
226
// Pad out with zeros to get the required fraction length
217
- for ( ; fractionLen < fractionSize ; fractionLen ++ ) digits . push ( 0 ) ;
227
+ for ( ; fractionLen < fractionSize ; fractionLen ++ ) digits . push ( 0 ) ;
228
+
218
229
219
- // Do a final clear of any carrying, e.g. the last digit was rounded up to 10
230
+ // Do any carrying, e.g. a digit was rounded up to 10
220
231
var carry = digits . reduceRight ( function ( carry , d , i , digits ) {
221
232
d = d + carry ;
222
233
digits [ i ] = d % 10 ;
223
234
return Math . floor ( d / 10 ) ;
224
235
} , 0 ) ;
225
236
if ( carry ) {
226
237
digits . unshift ( carry ) ;
227
- parsedNumber . integerLen ++ ;
238
+ parsedNumber . i ++ ;
228
239
}
229
240
}
230
241
@@ -248,16 +259,11 @@ function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {
248
259
*/
249
260
function formatNumber ( number , pattern , groupSep , decimalSep , fractionSize ) {
250
261
251
- if ( isObject ( number ) ) return '' ;
252
-
253
- var isNegative = number < 0 ;
254
- number = Math . abs ( number ) ;
255
-
256
- var isInfinity = number === Infinity ;
257
- if ( ! isInfinity && ! isFinite ( number ) ) return '' ;
262
+ if ( ! ( isString ( number ) || isNumber ( number ) ) || isNaN ( number ) ) return '' ;
258
263
264
+ var isInfinity = ! isFinite ( number ) ;
259
265
var isZero = false ;
260
- var numStr = number + '' ,
266
+ var numStr = Math . abs ( number ) + '' ,
261
267
formattedText = '' ,
262
268
parsedNumber ;
263
269
@@ -268,8 +274,9 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
268
274
269
275
roundNumber ( parsedNumber , fractionSize , pattern . minFrac , pattern . maxFrac ) ;
270
276
271
- var digits = parsedNumber . digits ;
272
- var integerLen = parsedNumber . integerLen ;
277
+ var digits = parsedNumber . d ;
278
+ var integerLen = parsedNumber . i ;
279
+ var exponent = parsedNumber . e ;
273
280
var decimals = [ ] ;
274
281
isZero = digits . reduce ( function ( isZero , d ) { return isZero && ! d ; } , true ) ;
275
282
@@ -305,11 +312,11 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
305
312
formattedText += decimalSep + decimals . join ( '' ) ;
306
313
}
307
314
308
- if ( parsedNumber . exponent ) {
309
- formattedText += 'e+' + parsedNumber . exponent ;
315
+ if ( exponent ) {
316
+ formattedText += 'e+' + exponent ;
310
317
}
311
318
}
312
- if ( isNegative && ! isZero ) {
319
+ if ( number < 0 && ! isZero ) {
313
320
return pattern . negPre + formattedText + pattern . negSuf ;
314
321
} else {
315
322
return pattern . posPre + formattedText + pattern . posSuf ;
0 commit comments