@@ -19,8 +19,10 @@ export const DEFAULT_OPTIONS = {
19
19
20
20
export class CurrencyInput {
21
21
private readonly el : HTMLInputElement
22
+ private readonly onInput : ( value : CurrencyInputValue ) => void
23
+ private readonly onChange : ( value : CurrencyInputValue ) => void
24
+ private numberValue ! : number | null
22
25
private options ! : CurrencyInputOptions
23
- private numberValue : number | null
24
26
private currencyFormat ! : CurrencyFormat
25
27
private decimalSymbolInsertedAt ?: number
26
28
private numberMask ! : InputMask
@@ -31,12 +33,17 @@ export class CurrencyInput {
31
33
private valueScaling : number | undefined
32
34
private valueScalingFractionDigits ! : number
33
35
34
- constructor ( el : HTMLInputElement , options : CurrencyInputOptions ) {
35
- this . el = el
36
- this . numberValue = null
36
+ constructor ( args : {
37
+ el : HTMLInputElement
38
+ options : CurrencyInputOptions
39
+ onInput : ( value : CurrencyInputValue ) => void
40
+ onChange : ( value : CurrencyInputValue ) => void
41
+ } ) {
42
+ this . el = args . el
43
+ this . onInput = args . onInput
44
+ this . onChange = args . onChange
37
45
this . addEventListener ( )
38
- this . init ( options )
39
- this . setValue ( this . currencyFormat . parse ( this . el . value ) )
46
+ this . init ( args . options )
40
47
}
41
48
42
49
setOptions ( options : CurrencyInputOptions ) : void {
@@ -56,10 +63,6 @@ export class CurrencyInput {
56
63
}
57
64
}
58
65
59
- private dispatchEvent ( eventName : string ) {
60
- this . el . dispatchEvent ( new CustomEvent ( eventName , { detail : this . getValue ( ) } ) )
61
- }
62
-
63
66
private init ( options : CurrencyInputOptions ) {
64
67
this . options = {
65
68
...DEFAULT_OPTIONS ,
@@ -124,7 +127,7 @@ export class CurrencyInput {
124
127
private applyFixedFractionFormat ( number : number | null , forcedChange = false ) {
125
128
this . format ( this . currencyFormat . format ( this . validateValueRange ( number ) ) )
126
129
if ( number !== this . numberValue || forcedChange ) {
127
- this . dispatchEvent ( 'change' )
130
+ this . onChange ( this . getValue ( ) )
128
131
}
129
132
}
130
133
@@ -178,65 +181,53 @@ export class CurrencyInput {
178
181
this . numberValue = null
179
182
}
180
183
this . formattedValue = this . el . value
181
- this . dispatchEvent ( 'input' )
184
+ this . onInput ( this . getValue ( ) )
182
185
}
183
186
184
187
private addEventListener ( ) : void {
185
- this . el . addEventListener (
186
- 'input' ,
187
- ( e : Event ) => {
188
- if ( ! ( e as CustomEvent ) . detail ) {
189
- const { value, selectionStart } = this . el
190
- const inputEvent = e as InputEvent
191
- if ( selectionStart && inputEvent . data && DECIMAL_SEPARATORS . includes ( inputEvent . data ) ) {
192
- this . decimalSymbolInsertedAt = selectionStart - 1
188
+ this . el . addEventListener ( 'input' , ( e : Event ) => {
189
+ const { value, selectionStart } = this . el
190
+ const inputEvent = e as InputEvent
191
+ if ( selectionStart && inputEvent . data && DECIMAL_SEPARATORS . includes ( inputEvent . data ) ) {
192
+ this . decimalSymbolInsertedAt = selectionStart - 1
193
+ }
194
+ this . format ( value )
195
+ if ( this . focus && selectionStart != null ) {
196
+ const getCaretPositionAfterFormat = ( ) => {
197
+ const { prefix, suffix, decimalSymbol, maximumFractionDigits, groupingSymbol } = this . currencyFormat
198
+ let caretPositionFromLeft = value . length - selectionStart
199
+ const newValueLength = this . formattedValue . length
200
+ if ( this . currencyFormat . minusSign === undefined && ( value . startsWith ( '(' ) || value . startsWith ( '-' ) ) && ! value . endsWith ( ')' ) ) {
201
+ return newValueLength - this . currencyFormat . negativeSuffix . length > 1 ? this . formattedValue . substring ( selectionStart ) . length : 1
193
202
}
194
- this . format ( value )
195
- if ( this . focus && selectionStart != null ) {
196
- const getCaretPositionAfterFormat = ( ) => {
197
- const { prefix, suffix, decimalSymbol, maximumFractionDigits, groupingSymbol } = this . currencyFormat
198
-
199
- let caretPositionFromLeft = value . length - selectionStart
200
- const newValueLength = this . formattedValue . length
201
-
202
- if ( this . currencyFormat . minusSign === undefined && ( value . startsWith ( '(' ) || value . startsWith ( '-' ) ) && ! value . endsWith ( ')' ) ) {
203
- return newValueLength - this . currencyFormat . negativeSuffix . length > 1 ? this . formattedValue . substring ( selectionStart ) . length : 1
204
- }
205
-
206
- if (
207
- this . formattedValue . substr ( selectionStart , 1 ) === groupingSymbol &&
208
- count ( this . formattedValue , groupingSymbol ) === count ( value , groupingSymbol ) + 1
209
- ) {
210
- return newValueLength - caretPositionFromLeft - 1
211
- }
212
-
213
- if ( newValueLength < caretPositionFromLeft ) {
214
- return selectionStart
215
- }
216
-
217
- if ( decimalSymbol !== undefined && value . indexOf ( decimalSymbol ) !== - 1 ) {
218
- const decimalSymbolPosition = value . indexOf ( decimalSymbol ) + 1
219
- if ( Math . abs ( newValueLength - value . length ) > 1 && selectionStart <= decimalSymbolPosition ) {
220
- return this . formattedValue . indexOf ( decimalSymbol ) + 1
221
- } else {
222
- if ( ! this . options . autoDecimalDigits && selectionStart > decimalSymbolPosition ) {
223
- if ( this . currencyFormat . onlyDigits ( value . substr ( decimalSymbolPosition ) ) . length - 1 === maximumFractionDigits ) {
224
- caretPositionFromLeft -= 1
225
- }
226
- }
203
+ if (
204
+ this . formattedValue . substr ( selectionStart , 1 ) === groupingSymbol &&
205
+ count ( this . formattedValue , groupingSymbol ) === count ( value , groupingSymbol ) + 1
206
+ ) {
207
+ return newValueLength - caretPositionFromLeft - 1
208
+ }
209
+ if ( newValueLength < caretPositionFromLeft ) {
210
+ return selectionStart
211
+ }
212
+ if ( decimalSymbol !== undefined && value . indexOf ( decimalSymbol ) !== - 1 ) {
213
+ const decimalSymbolPosition = value . indexOf ( decimalSymbol ) + 1
214
+ if ( Math . abs ( newValueLength - value . length ) > 1 && selectionStart <= decimalSymbolPosition ) {
215
+ return this . formattedValue . indexOf ( decimalSymbol ) + 1
216
+ } else {
217
+ if ( ! this . options . autoDecimalDigits && selectionStart > decimalSymbolPosition ) {
218
+ if ( this . currencyFormat . onlyDigits ( value . substr ( decimalSymbolPosition ) ) . length - 1 === maximumFractionDigits ) {
219
+ caretPositionFromLeft -= 1
227
220
}
228
221
}
229
-
230
- return this . options . hideCurrencySymbolOnFocus || this . options . currencyDisplay === CurrencyDisplay . hidden
231
- ? newValueLength - caretPositionFromLeft
232
- : Math . max ( newValueLength - Math . max ( caretPositionFromLeft , suffix . length ) , prefix . length )
233
222
}
234
- this . setCaretPosition ( getCaretPositionAfterFormat ( ) )
235
223
}
224
+ return this . options . hideCurrencySymbolOnFocus || this . options . currencyDisplay === CurrencyDisplay . hidden
225
+ ? newValueLength - caretPositionFromLeft
226
+ : Math . max ( newValueLength - Math . max ( caretPositionFromLeft , suffix . length ) , prefix . length )
236
227
}
237
- } ,
238
- { capture : true }
239
- )
228
+ this . setCaretPosition ( getCaretPositionAfterFormat ( ) )
229
+ }
230
+ } )
240
231
241
232
this . el . addEventListener ( 'focus' , ( ) => {
242
233
this . focus = true
@@ -257,15 +248,9 @@ export class CurrencyInput {
257
248
this . applyFixedFractionFormat ( this . numberValue )
258
249
} )
259
250
260
- this . el . addEventListener (
261
- 'change' ,
262
- ( e : Event ) => {
263
- if ( ! ( e as CustomEvent ) . detail ) {
264
- this . dispatchEvent ( 'change' )
265
- }
266
- } ,
267
- { capture : true }
268
- )
251
+ this . el . addEventListener ( 'change' , ( ) => {
252
+ this . onChange ( this . getValue ( ) )
253
+ } )
269
254
}
270
255
271
256
private getCaretPositionOnFocus ( value : string , selectionStart : number ) {
0 commit comments