1- // Developed and distributed by OSREC (http://osrec.co.uk)
2- // Version: 0.1
3- // Date: 27 Sept 2016
1+ // CurrencyFormatter.js
2+ // ---------------------------------------------------------------------
3+ // Version: 2.0
4+ // Release Date: 9 Jan 2018
5+ // Created by the Bx team at OSREC Technologies (https://osrec.co.uk)
6+ //
7+ // Check out Bx @ https://usebx.com for free invoicing, expenses & project management
8+ // If you use this library in a commercial project, we appreciate a link back to https://osrec.co.uk :)
49
510var OSREC = OSREC || { } ;
611
@@ -1041,122 +1046,74 @@ OSREC.CurrencyFormatter =
10411046 zu_ZA : { h : 'zu' } ,
10421047 } ,
10431048
1044- getFormatter : function ( p )
1049+ getFormatDetails : function ( p )
10451050 {
10461051 var locales = OSREC . CurrencyFormatter . locales ;
10471052 var defaultLocales = OSREC . CurrencyFormatter . defaultLocales ;
10481053 var symbols = OSREC . CurrencyFormatter . symbols ;
10491054
10501055 var locale , currency , symbol , pattern , decimal , group ;
10511056
1052- // Helper Functions
1053-
1054- var isUndefined = function ( o )
1055- {
1056- return ( typeof o === 'undefined' ) ;
1057- } ;
1058-
1059- var toFixed = function ( n , precision )
1060- {
1061- return ( + ( Math . round ( + ( n + 'e' + precision ) ) + 'e' + - precision ) ) . toFixed ( precision ) ;
1062- } ;
1063-
10641057 // Perform checks on inputs and set up defaults as needed (defaults to en, USD)
10651058
1066- if ( isUndefined ( p ) ) { p = { } ; }
1067-
1068- currency = isUndefined ( p . currency ) ? 'USD' : p . currency . toUpperCase ( ) ;
1069- locale = isUndefined ( p . locale ) ? locales [ defaultLocales [ currency ] ] : locales [ p . locale ] ;
1059+ p = p || { } ;
10701060
1071- if ( ! isUndefined ( locale . h ) ) locale = locales [ locale . h ] ; // Locale inheritance
1061+ currency = ( p . currency || 'USD' ) . toUpperCase ( ) ;
1062+ locale = locales [ p . locale || defaultLocales [ currency ] ] ;
10721063
1073- symbol = isUndefined ( p . symbol ) ? symbols [ currency ] : p . symbol ;
1064+ if ( typeof locale . h !== 'undefined' ) { locale = locales [ locale . h ] ; } // Locale inheritance
10741065
1075- if ( isUndefined ( symbol ) ) symbol = currency ; // In case we don't have the symbol, just use the ccy code
1066+ symbol = ( p . symbol || symbols [ currency ] ) || currency ;
1067+ pattern = p . pattern || locale . p ;
1068+ decimal = p . decimal || locale . d ;
1069+ group = p . group || locale . g ;
1070+
1071+ return { pattern : pattern , decimal : decimal , group : group , symbol : symbol } ;
10761072
1077- pattern = isUndefined ( p . pattern ) ? locale . p : p . pattern ;
1078- decimal = isUndefined ( p . decimal ) ? locale . d : p . decimal ;
1079- group = isUndefined ( p . group ) ? locale . g : p . group ;
1073+ } ,
10801074
1081- //console.log(locale);
1075+ toFixed : function ( n , precision )
1076+ {
1077+ return ( Math . round ( Number ( n ) * Math . pow ( 10 , precision ) ) / Math . pow ( 10 , precision ) ) . toFixed ( precision ) ;
1078+ } ,
10821079
1080+ getFormatter : function ( p )
1081+ {
1082+ var formatDetails = OSREC . CurrencyFormatter . getFormatDetails ( p ) ;
1083+
1084+ var pattern = formatDetails . pattern ;
1085+ var decimal = formatDetails . decimal ;
1086+ var group = formatDetails . group ;
1087+ var symbol = formatDetails . symbol ;
1088+
10831089 // encodePattern Function - returns a few simple characteristics of the pattern provided
1084-
1090+
10851091 var encodePattern = function ( pattern )
10861092 {
1087- var decimalPlaces = 0 ;
1088- var frontPadding = '' ;
1089- var backPadding = '' ;
1090- var groupLengths = [ ] ;
1091-
1092- //console.log(pattern);
1093-
1094- var patternStarted = false ;
1095- var decimalsStarted = false ;
1096- var patternEnded = false ;
1097-
1098-
1099- var currentGroupLength = 0 ;
1100- var zeroLength = 0 ;
1101-
1102- for ( var i = 0 ; i < pattern . length ; ++ i )
1103- {
1104- var c = pattern [ i ] ;
1105-
1106- if ( ! patternStarted && [ '#' , '0' , ',' , '.' ] . indexOf ( c ) > - 1 )
1107- {
1108- patternStarted = true ;
1109- }
1110-
1111- if ( ! patternStarted ) { frontPadding += c ; }
1112-
1113- switch ( c )
1114- {
1115- case '#' :
1116- ++ currentGroupLength ;
1117- break ;
1118-
1119- case '0' :
1120- if ( decimalsStarted ) { ++ decimalPlaces ; }
1121- else { ++ currentGroupLength ; ++ zeroLength ; }
1122- break ;
1123-
1124- case ',' :
1125- groupLengths . push ( currentGroupLength ) ;
1126- currentGroupLength = 0 ;
1127- break ;
1128-
1129- case '.' :
1130- groupLengths . push ( currentGroupLength ) ;
1131- decimalsStarted = true ;
1132- break ;
1133- }
1134-
1135- if ( patternStarted && ! ( [ '#' , '0' , ',' , '.' ] . indexOf ( c ) > - 1 ) )
1136- {
1137- patternEnded = true ;
1138-
1139- if ( ! decimalsStarted )
1140- {
1141- groupLengths . push ( currentGroupLength ) ;
1142- }
1143-
1144- }
1145-
1146- if ( patternEnded ) { backPadding += c ; }
1147- }
1148-
1093+ var numberFormatPattern = pattern . trim ( ) . match ( / [ # 0 , \. ] + / ) [ 0 ] ;
1094+
1095+ var split = numberFormatPattern . split ( '.' ) ;
1096+ var c = split [ 0 ] ; // Decimal chars
1097+ var m = split [ 1 ] ; // Decimal mantissa
1098+
1099+ var groups = c . split ( ',' ) ;
1100+ var groupLengths = groups . map ( function ( g ) { return g . length ; } ) ;
1101+ var zeroLength = ( groups [ groups . length - 1 ] . match ( / 0 / g) || [ ] ) . length ;
1102+ var decimalPlaces = typeof m === 'undefined' ? 0 : m . length ;
1103+ var paddingSplit = pattern . split ( numberFormatPattern ) ;
1104+
11491105 var encodedPattern =
11501106 {
1107+ pattern : pattern ,
11511108 decimalPlaces : decimalPlaces ,
1152- frontPadding : frontPadding ,
1153- backPadding : backPadding ,
1109+ frontPadding : paddingSplit [ 0 ] ,
1110+ backPadding : paddingSplit [ 1 ] ,
11541111 groupLengths : groupLengths ,
11551112 zeroLength : zeroLength
11561113 } ;
11571114
11581115 return encodedPattern ;
1159- } ;
1116+ }
11601117
11611118 // Zero Padding helper function
11621119
@@ -1170,21 +1127,23 @@ OSREC.CurrencyFormatter =
11701127
11711128 var format = function ( n , f )
11721129 {
1173- var formattedNumber = toFixed ( Math . abs ( n ) , f . decimalPlaces ) ;
1130+ var formattedNumber = OSREC . CurrencyFormatter . toFixed ( Math . abs ( n ) , f . decimalPlaces ) ;
11741131
11751132 var splitNumber = formattedNumber . split ( "." ) ;
11761133
1177- if ( f . groupLengths . length > 1 ) // i.e. we actually have some sort of grouping in the values
1178- {
1179- var segment = "" ;
1134+ var segment = "" ;
1135+
1136+ var cursor = splitNumber [ 0 ] . length ;
11801137
1181- var cursor = splitNumber [ 0 ] . length ;
1138+ var maxGroupIndex = f . groupLengths . length - 1 ;
11821139
1183- var groupIndex = f . groupLengths . length - 1 ;
1140+ var groupIndex = maxGroupIndex ;
11841141
1142+ if ( maxGroupIndex > 0 )
1143+ {
11851144 while ( cursor > 0 )
11861145 {
1187- if ( groupIndex <= 0 ) { groupIndex = 1 ; } // Always reset to the first group length if the number is big
1146+ if ( groupIndex < 1 ) { groupIndex = 1 ; } // Always reset to the last group length (useful for big numbers)
11881147
11891148 var currentGroupLength = f . groupLengths [ groupIndex ] ;
11901149
@@ -1196,16 +1155,19 @@ OSREC.CurrencyFormatter =
11961155
11971156 -- groupIndex ;
11981157 }
1199-
1158+
12001159 segment = segment . substring ( 0 , segment . length - 1 ) ;
1201- //console.log(segment);
1160+ }
1161+ else
1162+ {
1163+ segment = splitNumber [ 0 ] ;
12021164 }
12031165
12041166 if ( segment . length < f . zeroLength ) { segment = pad ( segment , f . zeroLength ) ; }
12051167
1206- var formattedNumber = f . frontPadding + segment + ( isUndefined ( splitNumber [ 1 ] ) ? '' : ( f . decimal + splitNumber [ 1 ] ) ) + f . backPadding ;
1168+ var formattedNumber = f . frontPadding + segment + ( typeof splitNumber [ 1 ] === 'undefined' ? '' : ( f . decimal + splitNumber [ 1 ] ) ) + f . backPadding ;
12071169
1208- return formattedNumber . replace ( '!' , symbol ) ;
1170+ return formattedNumber . replace ( / \! / g , symbol ) ;
12091171
12101172 } ;
12111173
@@ -1219,13 +1181,13 @@ OSREC.CurrencyFormatter =
12191181 positiveFormat . decimal = decimal ;
12201182 positiveFormat . group = group ;
12211183
1222- var negativeFormat = isUndefined ( patternArray [ 1 ] ) ? encodePattern ( "-" + patternArray [ 0 ] ) : encodePattern ( patternArray [ 1 ] ) ;
1184+ var negativeFormat = typeof patternArray [ 1 ] === 'undefined' ? encodePattern ( "-" + patternArray [ 0 ] ) : encodePattern ( patternArray [ 1 ] ) ;
12231185
12241186 negativeFormat . symbol = symbol ;
12251187 negativeFormat . decimal = decimal ;
12261188 negativeFormat . group = group ;
12271189
1228- var zero = isUndefined ( patternArray [ 2 ] ) ? format ( 0 , positiveFormat ) : patternArray [ 2 ] ;
1190+ var zero = typeof patternArray [ 2 ] === 'undefined' ? format ( 0 , positiveFormat ) : patternArray [ 2 ] ;
12291191
12301192 return function ( n )
12311193 {
@@ -1285,11 +1247,17 @@ OSREC.CurrencyFormatter =
12851247 var formatterFunction = OSREC . CurrencyFormatter . getFormatter ( p ) ;
12861248
12871249 return formatterFunction ( n ) ;
1250+ } ,
1251+
1252+ parse : function ( str , p )
1253+ {
1254+ var decimal = OSREC . CurrencyFormatter . getFormatDetails ( p ) . decimal ;
1255+ var mult = str . indexOf ( '-' ) >= 0 ? - 1 : 1 ;
1256+ return Math . abs ( Number ( str . replace ( new RegExp ( `[^0-9${ decimal } ]` , 'g' ) , '' ) . replace ( decimal , '.' ) ) ) * mult ;
12881257 }
12891258} ;
12901259
12911260
1292-
12931261var hasDefine = typeof define === 'function' ;
12941262var hasExports = typeof module !== 'undefined' && module . exports ;
12951263var root = ( typeof window === 'undefined' ) ? global : window ;
0 commit comments