| 1 |
/** |
| 2 |
* Implements the "Imprecise Number" functionality of the Parse.ly dashboard. |
| 3 |
* |
| 4 |
* Note: This function is not made to process float numbers. |
| 5 |
* |
| 6 |
* @param {string} value The number to process. It can be formatted. |
| 7 |
* @param {number} fractionDigits The number of desired fraction digits. |
| 8 |
* @param {string} glue A string to put between the number and unit. |
| 9 |
* @return {string} The number formatted as an imprecise number. |
| 10 |
*/ |
| 11 |
export function formatToImpreciseNumber( value: string, fractionDigits = 1, glue = '' ): string { |
| 12 |
const number = parseInt( value.replace( /\D/g, '' ), 10 ); |
| 13 |
|
| 14 |
if ( number < 1000 ) { |
| 15 |
return value; |
| 16 |
} else if ( number < 10000 ) { |
| 17 |
fractionDigits = 1; |
| 18 |
} |
| 19 |
|
| 20 |
const unitNames: {[key:string]: string} = { |
| 21 |
1000: 'k', |
| 22 |
'1,000,000': 'M', |
| 23 |
'1,000,000,000': 'B', |
| 24 |
'1,000,000,000,000': 'T', |
| 25 |
'1,000,000,000,000,000': 'Q', |
| 26 |
}; |
| 27 |
let currentNumber = number; |
| 28 |
let currentNumberAsString = number.toString(); |
| 29 |
let unit = ''; |
| 30 |
let previousNumber = 0; |
| 31 |
|
| 32 |
Object.entries( unitNames ).forEach( ( [ thousands, suffix ] ) => { |
| 33 |
const thousandsInt = parseInt( thousands.replace( /\D/g, '' ), 10 ); |
| 34 |
|
| 35 |
if ( number >= thousandsInt ) { |
| 36 |
currentNumber = number / thousandsInt; |
| 37 |
let precision = fractionDigits; |
| 38 |
|
| 39 |
// For over 10 units, we reduce the precision to 1 fraction digit. |
| 40 |
if ( currentNumber % 1 > 1 / previousNumber ) { |
| 41 |
precision = currentNumber > 10 ? 1 : 2; |
| 42 |
} |
| 43 |
|
| 44 |
// Precision override, where we want to show 2 fraction digits. |
| 45 |
const zeroes = parseFloat( currentNumber.toFixed( 2 ) ) === parseFloat( currentNumber.toFixed( 0 ) ); |
| 46 |
precision = zeroes ? 0 : precision; |
| 47 |
currentNumberAsString = currentNumber.toFixed( precision ); |
| 48 |
unit = suffix; |
| 49 |
} |
| 50 |
|
| 51 |
previousNumber = thousandsInt; |
| 52 |
} ); |
| 53 |
|
| 54 |
return currentNumberAsString + glue + unit; |
| 55 |
} |
| 56 |
|