Skip to content

Commit 1b47e48

Browse files
committed
[Fix] Reverse fill issue
1 parent 0fd4459 commit 1b47e48

File tree

3 files changed

+61
-46
lines changed

3 files changed

+61
-46
lines changed

src/core.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export function updateCursor(el: HTMLInputElement, position: number) {
8080
}
8181
setSelectionRange()
8282
// Android Fix
83-
setTimeout(setSelectionRange(), 1)
83+
setTimeout(setSelectionRange, 1)
8484
}
8585

8686
/**
@@ -93,21 +93,22 @@ export function updateCursor(el: HTMLInputElement, position: number) {
9393
*/
9494
export function updateValue(el: CustomInputElement, vnode: VNode | null, { emit = true, force = false, clean = false } = {}) {
9595
const { options, oldValue } = el
96+
const { reverseFill, max, min } = options
9697
const currentValue = vnode?.props?.value || el.value
9798

9899
if (force || oldValue !== currentValue) {
99-
const number = new NumberFormat(options).clean(clean && !options.reverseFill)
100+
const number = new NumberFormat(options).clean(clean && !reverseFill)
100101
let masked = number.format(currentValue)
101-
let unmasked = number.clean(options && !options.reverseFill).unformat(currentValue)
102+
let unmasked = number.clean(!reverseFill).unformat(currentValue)
102103

103104
// check value with in range max and min value
104105
if (clean) {
105-
if (Number(options.max) === options.max && Number(unmasked) > options.max) {
106-
masked = number.format(options.max)
107-
unmasked = number.unformat(options.max)
108-
} else if (Number(options.min) === options.min && Number(unmasked) < options.min) {
109-
masked = number.format(options.min)
110-
unmasked = number.unformat(options.min)
106+
if (Number(max) === max && Number(unmasked) > max) {
107+
masked = number.format(max)
108+
unmasked = number.unformat(max)
109+
} else if (Number(min) === min && Number(unmasked) < min) {
110+
masked = number.format(min)
111+
unmasked = number.unformat(min)
111112
}
112113
}
113114

src/directive.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
import { DirectiveBinding, VNode } from 'vue'
22
import * as core from './core'
33
import defaultOptions from './options'
4-
4+
import NumberFormat from './number-format'
55
export default {
66
beforeMount: (el: core.CustomInputElement, { value, modifiers }: DirectiveBinding, vnode: VNode) => {
77
el = core.getInputElement(el)
88
const options = Object.assign(core.cloneDeep(defaultOptions), value, modifiers)
9+
const { reverseFill, precision } = options
910
el.options = options
11+
if (reverseFill && el.value) {
12+
el.value = parseFloat(new NumberFormat({ ...options, reverseFill: false }).unformat(el.value)).toFixed(precision)
13+
if (vnode?.props?.value) {
14+
vnode.props.value = el.value
15+
}
16+
}
1017
// set initial value
1118
core.updateValue(el, vnode, { force: options.prefill, clean: true, emit: false })
1219
},

src/number-format.ts

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ function fixed(precision: number) {
2424
return between(0, precision, 20)
2525
}
2626

27-
function toFixed(numbers: string, precision: number) {
28-
const exp = Math.pow(10, precision)
29-
const float = parseFloat(numbers) / exp || 0
30-
return float.toFixed(fixed(precision))
31-
}
32-
3327
/**
3428
* Number format class
3529
* @param {Options} config
@@ -46,12 +40,11 @@ export default class NumberFormat {
4640

4741
constructor(config?: Options) {
4842
this.options = Object.assign(defaultOptions, config)
43+
const { prefix, suffix, decimal, reverseFill } = this.options
4944

5045
this.input = ''
5146
this.number = ''
52-
this.isClean = true
53-
54-
const { prefix, suffix, decimal } = this.options
47+
this.isClean = !reverseFill
5548

5649
this.preSurRegExp = new RegExp(`${prefix}|${suffix}`, 'g')
5750
this.numberRegExp = new RegExp(`[^0-9\\${decimal}]+`, 'gi')
@@ -60,10 +53,7 @@ export default class NumberFormat {
6053
}
6154

6255
isNull() {
63-
if (this.isClean) {
64-
return !this.numberOnly(this.input, this.cleanRegExp)
65-
}
66-
return !this.numberOnly(this.input, this.negativeRegExp)
56+
return !this.numberOnly(this.isClean ? this.cleanRegExp : this.negativeRegExp)
6757
}
6858

6959
clean(clean = false) {
@@ -82,38 +72,52 @@ export default class NumberFormat {
8272
return hasMinus ? '-' : ''
8373
}
8474

75+
toFixed() {
76+
const exp = Math.pow(10, this.options.precision)
77+
const float = parseFloat(this.numberOnly(/\D+/g)) / exp || 0
78+
return float.toFixed(fixed(this.options.precision))
79+
}
80+
8581
toNumber(str: Input) {
8682
return Number(str)
8783
}
8884

89-
numberOnly(str: Input, regExp: RegExp) {
90-
return str?.toString().replace(regExp, '')
85+
numberOnly(regExp?: RegExp) {
86+
return this.input
87+
?.toString()
88+
.replace(this.preSurRegExp, '')
89+
.replace(regExp || this.numberRegExp, '')
9190
}
9291

9392
isNegative() {
9493
return this.sign() === '-'
9594
}
9695

9796
numbers() {
98-
if (this.options.reverseFill) {
99-
this.number = toFixed(this.numberOnly(this.input, /\D+/g), this.options.precision).replace('.', this.options.decimal)
97+
const { reverseFill, decimal } = this.options
98+
if (reverseFill) {
99+
this.number = this.toFixed().replace('.', decimal)
100100
} else if (typeof this.input === 'number') {
101-
this.number = this.parts(this.input.toString().replace('-', ''), '.').join(this.options.decimal)
101+
this.number = this.parts(this.input.toString().replace('-', ''), '.').join(decimal)
102+
} else if (!isNaN(this.toNumber(this.input))) {
103+
this.number = this.parts(this.input.replace('-', ''), '.').join(decimal)
102104
} else {
103-
const input = this.input.replace(this.preSurRegExp, '')
104-
this.number = this.numberOnly(input, this.numberRegExp)
105-
this.number = this.parts(this.number).join(this.options.decimal)
105+
this.number = this.parts(this.numberOnly()).join(decimal)
106106
}
107107
return this.number
108108
}
109109

110+
unformatNumber(): string {
111+
return this.numbers().toString().replace(this.options.decimal, '.')
112+
}
113+
110114
realNumber(): number {
111-
return parseFloat(this.numbers().toString().replace(this.options.decimal, '.'))
115+
return parseFloat(this.unformatNumber())
112116
}
113117

114118
parts(num: Input, separator?: string) {
115-
const decimal = separator || this.options.decimal
116-
let parts: Input[] = num.toString().split(decimal)
119+
const { precision, minimumFractionDigits, decimal } = this.options
120+
let parts: Input[] = num.toString().split(separator || decimal)
117121

118122
if (parts.length > 1) {
119123
parts[0] = this.toNumber(parts[0]) || 0
@@ -122,10 +126,10 @@ export default class NumberFormat {
122126
}
123127

124128
if (this.isClean) {
125-
const newNumber = this.toNumber(parts.join('.')).toFixed(this.options.precision)
129+
const newNumber = this.toNumber(parts.join('.')).toFixed(precision)
126130
const cleanNumber = this.toNumber(newNumber)
127-
const minimumDigits = cleanNumber.toFixed(this.options.minimumFractionDigits)
128-
const hasMinFraction = this.options.minimumFractionDigits >= 0 && cleanNumber.toString().length < minimumDigits.length
131+
const minimumDigits = cleanNumber.toFixed(minimumFractionDigits)
132+
const hasMinFraction = minimumFractionDigits >= 0 && cleanNumber.toString().length < minimumDigits.length
129133

130134
if (hasMinFraction) {
131135
parts = minimumDigits.toString().split('.')
@@ -138,9 +142,10 @@ export default class NumberFormat {
138142
}
139143

140144
addSeparator() {
141-
const parts: Input[] = this.numbers().split(this.options.decimal)
142-
parts[0] = parts[0].toString().replace(/(\d)(?=(?:\d{3})+\b)/gm, `$1${this.options.separator}`)
143-
return parts.join(this.options.decimal)
145+
const { decimal, separator } = this.options
146+
const parts: Input[] = this.numbers().split(decimal)
147+
parts[0] = parts[0].toString().replace(/(\d)(?=(?:\d{3})+\b)/gm, `$1${separator}`)
148+
return parts.join(decimal)
144149
}
145150

146151
/**
@@ -150,10 +155,11 @@ export default class NumberFormat {
150155
*/
151156
format(input: Input): string {
152157
this.input = input
153-
if (this.isNull() && !this.options.reverseFill) {
154-
return this.options.nullValue
158+
const { reverseFill, nullValue, prefix, suffix } = this.options
159+
if (this.isNull() && !reverseFill) {
160+
return nullValue
155161
}
156-
return this.sign() + this.options.prefix + this.addSeparator() + this.options.suffix
162+
return this.sign() + prefix + this.addSeparator() + suffix
157163
}
158164

159165
/**
@@ -163,11 +169,12 @@ export default class NumberFormat {
163169
*/
164170
unformat(input: Input): string {
165171
this.input = input
172+
const { reverseFill, nullValue } = this.options
166173
if (this.isNull()) {
167-
return this.options.nullValue
174+
return nullValue
168175
}
169-
if (this.options.reverseFill && this.realNumber() === 0) {
170-
return this.options.nullValue
176+
if (reverseFill && this.realNumber() === 0) {
177+
return nullValue
171178
}
172179
return this.sign() + this.realNumber()
173180
}

0 commit comments

Comments
 (0)