Skip to content

Commit

Permalink
Number: Add support for compact option (short/long) (1/2)
Browse files Browse the repository at this point in the history
  • Loading branch information
sieverk authored and rxaviers committed Aug 22, 2017
1 parent 7fe1fc7 commit 93b9470
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 21 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,9 +458,13 @@ Return a function that formats a number according to the given options or locale
.numberFormatter({ minimumFractionDigits: 2 })( 10000 )
// > "10,000.00"

<<<<<<< HEAD
.numberFormatter({ style: "percent" })( 0.5 )
// > "50%"
```
.numberFormatter({ compact: "short", maximumFractionDigits: 0 })( 14305 )
// > "14K"
```
[Read more...](doc/api/number/number-formatter.md)
Expand Down
8 changes: 8 additions & 0 deletions doc/api/currency/currency-formatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ formatter = Globalize.currencyFormatter( "USD", {

formatter( 1.491 );
// > "$1.50"

formatter = Globalize.currencyFormatter( "USD", {
maximumFractionDigits: 0,
compact: "short"
});

formatter( 12830000000 );
// > "$13B"
```

For improved performance on iterations, first create the formatter. Then, reuse it on each loop.
Expand Down
28 changes: 28 additions & 0 deletions doc/api/number/number-formatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ Optional. String with rounding method `ceil`, `floor`, `round` (default), or `tr

Optional. Boolean (default is true) value indicating whether a grouping separator should be used.

#### options.compact

Optional. String `short` or `long` indicating which compact number format should be used to represent the number.

### Examples

#### Static Formatter
Expand Down Expand Up @@ -139,6 +143,30 @@ frFormatter( 0.0005 );
// > "0,05 %"
```

#### Formatting Compact Numbers

Long numbers can be represented in a compact format, with `short` using abbreviated units and `long` using the full unit name.

```javascript
var shortFormatter = Globalize( "en" ).numberFormatter({
compact: "short",
maximumFractionDigits: 0,
style: "decimal"
});

var longFormatter = Globalize( "en" ).numberFormatter({
compact: "long",
maximumFractionDigits: 0,
style: "decimal"
});

shortFormatter( 27588910 );
// > "28M"

longFormatter( 27588910 );
// > "28 million"
```

#### Configuring Rounding

Numbers with a decreased amount of decimal places can be rounded up, rounded down, rounded arithmetically, or truncated by setting the `round` option to `ceil`, `floor`, `round` (default), or `truncate`.
Expand Down
13 changes: 9 additions & 4 deletions src/number.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function validateDigits( properties ) {
*/
Globalize.numberFormatter =
Globalize.prototype.numberFormatter = function( options ) {
var args, cldr, pattern, properties, returnFn;
var args, cldr, pattern, pluralGenerator, properties, returnFn;

validateParameterTypePlainObject( options, "options" );

Expand All @@ -93,9 +93,14 @@ Globalize.prototype.numberFormatter = function( options ) {

validateDigits( properties );

returnFn = numberFormatterFn( properties );

runtimeBind( args, cldr, returnFn, [ properties ] );
if ( options.compact ) {
pluralGenerator = this.pluralGenerator();
returnFn = numberFormatterFn( properties, pluralGenerator );
runtimeBind( args, cldr, returnFn, [ properties, pluralGenerator ] );
} else {
returnFn = numberFormatterFn( properties );
runtimeBind( args, cldr, returnFn, [ properties ] );
}

return returnFn;
};
Expand Down
22 changes: 22 additions & 0 deletions src/number/compact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
define([
"./numbering-system"
], function( numberNumberingSystem ) {

/**
* Compact( name, cldr )
*
* @compactType [String] Compact mode, `short` or `long`.
*
* @cldr [Cldr instance].
*
* Return the localized compact map for the given compact mode.
*/
return function( compactType, cldr ) {
return cldr.main([
"numbers/decimalFormats-numberSystem-" + numberNumberingSystem( cldr ),
compactType,
"decimalFormat"
]);
};

});
10 changes: 8 additions & 2 deletions src/number/format-properties.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
define([
"./compact",
"./numbering-system-digits-map",
"./pattern-properties",
"./symbol",
"./symbol/map",
"./symbol/name",
"../util/number/round"
], function( numberNumberingSystemDigitsMap, numberPatternProperties, numberSymbol, numberSymbolMap,
numberSymbolName, numberRound ) {
], function( numberCompact, numberNumberingSystemDigitsMap, numberPatternProperties, numberSymbol,
numberSymbolMap, numberSymbolName, numberRound ) {

/**
* formatProperties( pattern, cldr [, options] )
Expand Down Expand Up @@ -63,6 +64,10 @@ return function( pattern, cldr, options ) {
numberNumberingSystemDigitsMap( cldr )
]);

if ( options.compact ) {
properties[20] = numberCompact( options.compact, cldr );
}

getOptions( "minimumIntegerDigits", 2 );
getOptions( "minimumFractionDigits", 3 );
getOptions( "maximumFractionDigits", 4 );
Expand Down Expand Up @@ -98,6 +103,7 @@ return function( pattern, cldr, options ) {
// 17: @nanSymbol [String] NaN symbol.
// 18: @symbolMap [Object] A bunch of other symbols.
// 19: @nuDigitsMap [Array] Digits map if numbering system is different than `latn`.
// 20: @compactMap [Object] Map of per-digit-count format patterns for specified compact mode.
return properties;
};

Expand Down
60 changes: 52 additions & 8 deletions src/number/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ define([
"./format/grouping-separator",
"./format/integer-fraction-digits",
"./format/significant-digits",
"./pattern-re",
"../util/remove-literal-quotes"
], function( numberFormatGroupingSeparator, numberFormatIntegerFractionDigits,
numberFormatSignificantDigits, removeLiteralQuotes ) {
numberFormatSignificantDigits, numberPatternRe, removeLiteralQuotes ) {

/**
* format( number, properties )
Expand All @@ -16,11 +17,11 @@ define([
* Return the formatted number.
* ref: http://www.unicode.org/reports/tr35/tr35-numbers.html
*/
return function( number, properties ) {
var infinitySymbol, maximumFractionDigits, maximumSignificantDigits, minimumFractionDigits,
minimumIntegerDigits, minimumSignificantDigits, nanSymbol, nuDigitsMap, padding, prefix,
primaryGroupingSize, pattern, ret, round, roundIncrement, secondaryGroupingSize, suffix,
symbolMap;
return function( number, properties, pluralGenerator ) {
var compactMap, infinitySymbol, maximumFractionDigits, maximumSignificantDigits,
minimumFractionDigits, minimumIntegerDigits, minimumSignificantDigits, nanSymbol, nuDigitsMap,
padding, prefix, primaryGroupingSize, pattern, ret, round, roundIncrement,
secondaryGroupingSize, suffix, symbolMap;

padding = properties[ 1 ];
minimumIntegerDigits = properties[ 2 ];
Expand All @@ -36,6 +37,7 @@ return function( number, properties ) {
nanSymbol = properties[ 17 ];
symbolMap = properties[ 18 ];
nuDigitsMap = properties[ 19 ];
compactMap = properties[ 20 ];

// NaN
if ( isNaN( number ) ) {
Expand All @@ -57,8 +59,6 @@ return function( number, properties ) {
return prefix + infinitySymbol + suffix;
}

ret = prefix;

// Percent
if ( pattern.indexOf( "%" ) !== -1 ) {
number *= 100;
Expand All @@ -68,6 +68,32 @@ return function( number, properties ) {
number *= 1000;
}

var compactPattern, compactDigits, compactProperties, divisor, pluralForm, zeroes,
originalNumber;

// Compact mode: initial number digit processing
if ( compactMap ) {
originalNumber = number;
zeroes = Array( Math.floor( number ).toString().length ).join( "0" );
if ( zeroes.length >= 3 ) {

// use default plural form to perform initial decimal shift
compactPattern = compactMap[ "1" + zeroes + "-count-other" ];

if ( compactPattern ) {
compactDigits = compactPattern.split( "0" ).length - 1;
divisor = zeroes.length - ( compactDigits - 1 );
number = number / Math.pow( 10, divisor );

// Some languages specify no pattern for certain digit lengths, represented as "0".
// If no pattern, original number should remain uncompacted.
if ( compactPattern === "0" ) {
number = originalNumber;
}
}
}
}

// Significant digit format
if ( !isNaN( minimumSignificantDigits * maximumSignificantDigits ) ) {
number = numberFormatSignificantDigits( number, minimumSignificantDigits,
Expand All @@ -79,6 +105,22 @@ return function( number, properties ) {
minimumFractionDigits, maximumFractionDigits, round, roundIncrement );
}

// Compact mode: apply formatting
if ( compactMap && compactPattern ) {
pluralForm = pluralGenerator ? pluralGenerator( number ) : "other";
compactPattern = compactMap[ "1" + zeroes + "-count-" + pluralForm ] || compactPattern;

// Some languages specify no pattern for certain digit lengths, represented as "0".
// Only apply compact pattern if one is specified.
if ( compactPattern !== "0" ) {
compactProperties = compactPattern.match( numberPatternRe );

// update prefix/suffix with compact prefix/suffix
prefix += compactProperties[ 1 ];
suffix = compactProperties[ 11 ] + suffix;
}
}

// Remove the possible number minus sign
number = number.replace( /^-/, "" );

Expand All @@ -88,6 +130,8 @@ return function( number, properties ) {
secondaryGroupingSize );
}

ret = prefix;

ret += number;

// Scientific notation
Expand Down
4 changes: 2 additions & 2 deletions src/number/formatter-fn.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ define([
"./format"
], function( validateParameterPresence, validateParameterTypeNumber, numberFormat ) {

return function( properties ) {
return function( properties, pluralGenerator ) {
return function numberFormatter( value ) {
validateParameterPresence( value, "value" );
validateParameterTypeNumber( value, "value" );

return numberFormat( value, properties );
return numberFormat( value, properties, pluralGenerator );
};
};

Expand Down
4 changes: 2 additions & 2 deletions src/number/pattern-re.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ define(function() {
*
* suffix = non_number_stuff
*
* non_number_stuff = regexp(('[^']+'|''|[^*#@0,.E])*)
* non_number_stuff = regexp(.*?)
*
*
* Regexp groups:
Expand All @@ -45,6 +45,6 @@ define(function() {
* 11: suffix
* 12: -
*/
return ( /^(('([^']|'')*'|[^*#@0,.E])*)(\*.)?((([#,]*[0,]*0+)(\.0*[0-9]*#*)?)|([#,]*@+#*))(E\+?0+)?(('[^']+'|''|[^*#@0,.E])*)$/ );
return ( /^(('([^']|'')*'|[^*#@0,.E])*)(\*.)?((([#,]*[0,]*0+)(\.0*[0-9]*#*)?)|([#,]*@+#*))(E\+?0+)?(.*?)$/ );

});
Loading

0 comments on commit 93b9470

Please sign in to comment.