From f417d648fb6ed4763e7c760d6acc277037cbbd94 Mon Sep 17 00:00:00 2001 From: Dipak Sarkar Date: Sun, 17 Oct 2021 08:48:52 +0530 Subject: [PATCH] fix some bugs --- src/component.vue | 2 +- src/core.js | 7 -- src/directive.js | 6 +- src/number-format.js | 32 +++++-- tests/unit/number-format.custom.spec.js | 106 +++++++++++------------ tests/unit/number-format.default.spec.js | 94 ++++++++++---------- 6 files changed, 129 insertions(+), 118 deletions(-) diff --git a/src/component.vue b/src/component.vue index 39e8f71..64e9118 100644 --- a/src/component.vue +++ b/src/component.vue @@ -58,7 +58,7 @@ export default { emits: ['update:modelValue'], data() { return { - maskedValue: null, + maskedValue: this.modelValue, unmaskedValue: null } }, diff --git a/src/core.js b/src/core.js index 124d2ea..1b4fb16 100644 --- a/src/core.js +++ b/src/core.js @@ -112,13 +112,6 @@ export function inputHandler(event) { positionFromEnd = Math.max(positionFromEnd, config.suffix.length) positionFromEnd = target.value.length - positionFromEnd positionFromEnd = Math.max(positionFromEnd, config.prefix.length + 1) - const decimalPosition = target.value.indexOf(config.decimal) - const diff = positionFromEnd - decimalPosition - const maxLength = target.value.length - config.suffix.length - const positionAfterDecimal = positionFromEnd + 1 - if (decimalPosition > 0 && diff > 0 && positionAfterDecimal <= maxLength) { - positionFromEnd = positionAfterDecimal - } updateCursor(target, positionFromEnd) if (oldValue !== target.value) { diff --git a/src/directive.js b/src/directive.js index 4d9b8b8..5d2e5d6 100644 --- a/src/directive.js +++ b/src/directive.js @@ -9,7 +9,7 @@ export default { const config = Object.assign({}, defaults, value, modifiers) el[CONFIG_KEY] = { config } // set initial value - core.updateValue(el, vnode, { force: config.prefill }) + core.updateValue(el, vnode, { force: config.prefill, clean: true }) }, mounted: (el) => { @@ -30,11 +30,13 @@ export default { // check decimal key and insert to current element // updated cursor position after format the value el.onkeydown = (e) => { - if ([110, 190].includes(e.keyCode) || e.key === config.decimal) { + if (([110, 190].includes(e.keyCode) || e.key === config.decimal) && !el.value.includes(config.decimal)) { e.preventDefault() el.setRangeText(config.decimal) el.dispatchEvent(new Event('input')) core.updateCursor(el, el.value.indexOf(config.decimal) + 1) + } else if (([110, 190].includes(e.keyCode) || e.key === config.decimal) && el.value.includes(config.decimal)) { + e.preventDefault() } } diff --git a/src/number-format.js b/src/number-format.js index d13765e..7203194 100644 --- a/src/number-format.js +++ b/src/number-format.js @@ -9,67 +9,82 @@ export default function NumberFormat(config = options) { this.input = '' this.number = '' this.isClean = false + this.isNull = (input = this.input) => !this.numberOnly(input, new RegExp('[^0-9]+', 'gi')) + this.clean = (clean = false) => { this.isClean = clean return this } + this.sign = () => { const sign = (this.input.toString().indexOf('-') >= 0 && this.realNumber() > 0) ? '-' : '' return sign } + function between(min, n, max) { return Math.max(min, Math.min(n, max)) } + // Uncaught RangeError: toFixed() digits argument must be between 0 and 20 at Number.toFixed function fixed(precision) { return between(0, precision, 20) } + function toFixed(numbers, precision) { // eslint-disable-next-line no-restricted-properties var exp = Math.pow(10, precision) var float = parseFloat(numbers) / exp return float.toFixed(fixed(precision)) } + this.toNumber = (string) => Number(string) + this.numberOnly = (string, regExp) => string.toString().replace(regExp, '') + this.isNegative = this.sign() === '-' + this.numbers = () => { if (this.options.reverseFill) { this.number = toFixed(this.numberOnly(this.input, /\D+/g), this.options.precision).replace('.', this.options.decimal) } else if (typeof this.input === 'number') { - this.number = this.toNumber(this.input.toFixed(this.options.precision)).toString().replace('-', '').replace('.', this.options.decimal) - // eslint-disable-next-line no-restricted-globals - } else if (!isNaN(this.toNumber(this.input))) { - this.number = this.input.replace('-', '').replace('.', this.options.decimal) + if (this.isClean) { + this.number = this.toNumber(this.input.toFixed(this.options.precision)).toString().replace('-', '').replace('.', this.options.decimal) + } else { + this.number = this.toNumber(this.input).toString().replace('-', '').replace('.', this.options.decimal) + } } else { this.number = this.numberOnly(this.input, new RegExp(`[^0-9\\${this.options.decimal}]+`, 'gi')) this.number = this.parts(this.number).join(this.options.decimal) } return this.number } + this.realNumber = () => this.toNumber(this.numbers().toString().replace(this.options.decimal, '.')) + this.parts = (number = '', decimal = this.options.decimal) => { var parts = number.toString().split(decimal) parts[0] = this.toNumber(parts[0]) || 0 if (parts.length > 1) { parts[1] = parts.slice(1, parts.length).join('') parts = parts.slice(0, 2) - if (parts[1].length > this.options.precision) { + if (this.isClean && parts[1].length > this.options.precision) { parts[1] = this.toNumber(`.${parts[1]}`).toFixed(this.options.precision).toString().replace('0.', '') } } return parts.slice(0, 2) } + this.addSeparator = () => { var parts = this.numbers().split(this.options.decimal) parts[0] = parts[0].toString().replace(/(\d)(?=(?:\d{3})+\b)/gm, `$1${this.options.separator}`) if (this.isClean) { parts[1] = this.toNumber(`.${parts[1]}`).toString().replace('0.', '') - return parts[1] && parts[1] > 0 ? parts.join(this.options.decimal) : parts[0] + return parts[1] && parts[1] >= 0 ? parts.join(this.options.decimal) : parts[0] } return parts.join(this.options.decimal) } + /** * Format the input with default config if there is no constructor config * @param {Number, String} input @@ -77,10 +92,11 @@ export default function NumberFormat(config = options) { */ this.format = (input) => { if (input === '') return this.options.null_value - this.input = input + this.input = input || this.options.null_value if (this.isNull()) return this.options.null_value return this.sign() + this.options.prefix + this.addSeparator() + this.options.suffix } + /** * Unformat the input with default config if there is no constructor config * @param {Number, String} input @@ -88,7 +104,7 @@ export default function NumberFormat(config = options) { */ this.unformat = (input) => { if (input === '') return this.options.null_value - this.input = input + this.input = input || this.options.null_value if (this.isNull()) return this.options.null_value return this.toNumber(this.sign() + this.realNumber()) } diff --git a/tests/unit/number-format.custom.spec.js b/tests/unit/number-format.custom.spec.js index c0e85e8..90f670e 100644 --- a/tests/unit/number-format.custom.spec.js +++ b/tests/unit/number-format.custom.spec.js @@ -24,19 +24,19 @@ describe('when the value is invalid with custom config', () => { expect(numberFormat.format('!@#$%^&*()')).toEqual('') }) it('should return as follows', () => { - expect(numberFormat.clean().format('')).toEqual('') - expect(numberFormat.clean().format('foo')).toEqual('') - expect(numberFormat.clean().format('-foo')).toEqual('') - expect(numberFormat.clean().format('-fo.o-')).toEqual('') - expect(numberFormat.clean().format('-fo,o-')).toEqual('') - expect(numberFormat.clean().format('!@#$%^&*()')).toEqual('') + expect(numberFormat.clean(true).format('')).toEqual('') + expect(numberFormat.clean(true).format('foo')).toEqual('') + expect(numberFormat.clean(true).format('-foo')).toEqual('') + expect(numberFormat.clean(true).format('-fo.o-')).toEqual('') + expect(numberFormat.clean(true).format('-fo,o-')).toEqual('') + expect(numberFormat.clean(true).format('!@#$%^&*()')).toEqual('') }) it('should return as follows', () => { - expect(numberFormat.unformat('')).toEqual('') - expect(numberFormat.unformat('foo')).toEqual('') - expect(numberFormat.unformat('-foo')).toEqual('') - expect(numberFormat.unformat('-fo.o-')).toEqual('') - expect(numberFormat.unformat('!@#$%^&*()')).toEqual('') + expect(numberFormat.clean(true).unformat('')).toEqual('') + expect(numberFormat.clean(true).unformat('foo')).toEqual('') + expect(numberFormat.clean(true).unformat('-foo')).toEqual('') + expect(numberFormat.clean(true).unformat('-fo.o-')).toEqual('') + expect(numberFormat.clean(true).unformat('!@#$%^&*()')).toEqual('') }) }) describe('format when options are custom', () => { @@ -53,34 +53,34 @@ describe('format when options are custom', () => { expect(numberFormat.format('0,10')).toEqual('$0,10') expect(numberFormat.format('0,0-')).toEqual('$0,0') expect(numberFormat.format('0,10-')).toEqual('-$0,10') - expect(numberFormat.format('12.345,54921')).toEqual('$12.345,55') - expect(numberFormat.format('--12.345,12345')).toEqual('-$12.345,12') - expect(numberFormat.format('12.345.54321,12945')).toEqual('$1.234.554.321,13') - expect(numberFormat.format('-12.345,,54321-')).toEqual('-$12.345,54') + expect(numberFormat.format('12.345,54921')).toEqual('$12.345,54921') + expect(numberFormat.format('--12.345,12345')).toEqual('-$12.345,12345') + expect(numberFormat.format('12.345.54321,12945')).toEqual('$1.234.554.321,12945') + expect(numberFormat.format('-12.345,,54321-')).toEqual('-$12.345,54321') }) it('format numerical value', () => { - expect(numberFormat.format(0)).toEqual('$0') - expect(numberFormat.format(0.)).toEqual('$0') - expect(numberFormat.format(0.0)).toEqual('$0') + expect(numberFormat.format(0)).toEqual('') + expect(numberFormat.format(0.)).toEqual('') + expect(numberFormat.format(0.0)).toEqual('') expect(numberFormat.format(-0.10)).toEqual('-$0,1') - expect(numberFormat.format(-0.0)).toEqual('$0') + expect(numberFormat.format(-0.0)).toEqual('') expect(numberFormat.format(0.10)).toEqual('$0,1') - expect(numberFormat.format(12345.54921)).toEqual('$12.345,55') - expect(numberFormat.format(12345.12345)).toEqual('$12.345,12') - expect(numberFormat.format(12345.54321)).toEqual('$12.345,54') - expect(numberFormat.format(12345.54321)).toEqual('$12.345,54') + expect(numberFormat.format(12345.54921)).toEqual('$12.345,54921') + expect(numberFormat.format(12345.12345)).toEqual('$12.345,12345') + expect(numberFormat.format(12345.54321)).toEqual('$12.345,54321') + expect(numberFormat.format(12345.54321)).toEqual('$12.345,54321') }) it('format and clean numerical value', () => { - expect(numberFormat.clean().format(0)).toEqual('$0') - expect(numberFormat.clean().format(0.)).toEqual('$0') - expect(numberFormat.clean().format(0.0)).toEqual('$0') - expect(numberFormat.clean().format(0.10)).toEqual('$0,1') - expect(numberFormat.clean().format(-0.0)).toEqual('$0') - expect(numberFormat.clean().format(-0.10)).toEqual('-$0,1') - expect(numberFormat.clean().format(12345.54921)).toEqual('$12.345,55') - expect(numberFormat.clean().format(12345.12345)).toEqual('$12.345,12') - expect(numberFormat.clean().format(12345.54321)).toEqual('$12.345,54') - expect(numberFormat.clean().format(12345.54321)).toEqual('$12.345,54') + expect(numberFormat.clean(true).format(0)).toEqual('') + expect(numberFormat.clean(true).format(0.)).toEqual('') + expect(numberFormat.clean(true).format(0.0)).toEqual('') + expect(numberFormat.clean(true).format(0.10)).toEqual('$0,1') + expect(numberFormat.clean(true).format(-0.0)).toEqual('') + expect(numberFormat.clean(true).format(-0.10)).toEqual('-$0,1') + expect(numberFormat.clean(true).format(12345.54921)).toEqual('$12.345,55') + expect(numberFormat.clean(true).format(12345.12345)).toEqual('$12.345,12') + expect(numberFormat.clean(true).format(12345.54321)).toEqual('$12.345,54') + expect(numberFormat.clean(true).format(12345.54321)).toEqual('$12.345,54') }) }) describe('unformat when options are default', () => { @@ -91,28 +91,28 @@ describe('unformat when options are default', () => { null_value: '', }) it('unformat string value', () => { - expect(numberFormat.unformat('0')).toEqual(0) - expect(numberFormat.unformat('0,')).toEqual(0) - expect(numberFormat.unformat('-0,0')).toEqual(0) - expect(numberFormat.unformat('0,10')).toEqual(0.1) - expect(numberFormat.unformat('0,0-')).toEqual(0) - expect(numberFormat.unformat('0,10-')).toEqual(-0.1) - expect(numberFormat.unformat('12.345,54921')).toEqual(12345.55) - expect(numberFormat.unformat('--12.345,12345')).toEqual(-12345.12) - expect(numberFormat.unformat('12.345.54321,12345')).toEqual(1234554321.12) - expect(numberFormat.unformat('-12.345,,54321-')).toEqual(-12345.54) + expect(numberFormat.clean(true).unformat('0')).toEqual(0) + expect(numberFormat.clean(true).unformat('0,')).toEqual(0) + expect(numberFormat.clean(true).unformat('-0,0')).toEqual(0) + expect(numberFormat.clean(true).unformat('0,10')).toEqual(0.1) + expect(numberFormat.clean(true).unformat('0,0-')).toEqual(0) + expect(numberFormat.clean(true).unformat('0,10-')).toEqual(-0.1) + expect(numberFormat.clean(true).unformat('12.345,54921')).toEqual(12345.55) + expect(numberFormat.clean(true).unformat('--12.345,12345')).toEqual(-12345.12) + expect(numberFormat.clean(true).unformat('12.345.54321,12345')).toEqual(1234554321.12) + expect(numberFormat.clean(true).unformat('-12.345,,54321-')).toEqual(-12345.54) }) it('unformat numerical value', () => { - expect(numberFormat.unformat(0)).toEqual(0) - expect(numberFormat.unformat(0.)).toEqual(0) - expect(numberFormat.unformat(0.0)).toEqual(0) - expect(numberFormat.unformat(-0.10)).toEqual(-0.1) - expect(numberFormat.unformat(-0.0)).toEqual(0) - expect(numberFormat.unformat(0.10)).toEqual(0.1) - expect(numberFormat.unformat(12345.54921)).toEqual(12345.55) - expect(numberFormat.unformat(12345.12345)).toEqual(12345.12) - expect(numberFormat.unformat(12345.54321)).toEqual(12345.54) - expect(numberFormat.unformat(12345.54321)).toEqual(12345.54) + expect(numberFormat.clean(true).unformat(0)).toEqual('') + expect(numberFormat.clean(true).unformat(0.)).toEqual('') + expect(numberFormat.clean(true).unformat(0.0)).toEqual('') + expect(numberFormat.clean(true).unformat(-0.10)).toEqual(-0.1) + expect(numberFormat.clean(true).unformat(-0.0)).toEqual('') + expect(numberFormat.clean(true).unformat(0.10)).toEqual(0.1) + expect(numberFormat.clean(true).unformat(12345.54921)).toEqual(12345.55) + expect(numberFormat.clean(true).unformat(12345.12345)).toEqual(12345.12) + expect(numberFormat.clean(true).unformat(12345.54321)).toEqual(12345.54) + expect(numberFormat.clean(true).unformat(12345.54321)).toEqual(12345.54) }) }) diff --git a/tests/unit/number-format.default.spec.js b/tests/unit/number-format.default.spec.js index d189cfe..cab46ce 100644 --- a/tests/unit/number-format.default.spec.js +++ b/tests/unit/number-format.default.spec.js @@ -13,11 +13,11 @@ describe('when the value is invalid with default config', () => { expect(numberFormat.format('!@#$%^&*()')).toEqual('') }) it('should return as follows', () => { - expect(numberFormat.clean().format('')).toEqual('') - expect(numberFormat.clean().format('foo')).toEqual('') - expect(numberFormat.clean().format('-foo')).toEqual('') - expect(numberFormat.clean().format('-fo,o-')).toEqual('') - expect(numberFormat.clean().format('!@#$%^&*()')).toEqual('') + expect(numberFormat.clean(true).format('')).toEqual('') + expect(numberFormat.clean(true).format('foo')).toEqual('') + expect(numberFormat.clean(true).format('-foo')).toEqual('') + expect(numberFormat.clean(true).format('-fo,o-')).toEqual('') + expect(numberFormat.clean(true).format('!@#$%^&*()')).toEqual('') }) it('should return as follows', () => { expect(numberFormat.unformat('')).toEqual('') @@ -36,61 +36,61 @@ describe('format when options are default', () => { expect(numberFormat.format('0.10')).toEqual('0.10') expect(numberFormat.format('0.0-')).toEqual('0.0') expect(numberFormat.format('0.10-')).toEqual('-0.10') - expect(numberFormat.format('12,345.54921')).toEqual('12,345.55') - expect(numberFormat.format('--12,345.12345')).toEqual('-12,345.12') - expect(numberFormat.format('12,345.54321.12345')).toEqual('12,345.54') - expect(numberFormat.format('-12,345..54321-')).toEqual('-12,345.54') + expect(numberFormat.format('12,345.54921')).toEqual('12,345.54921') + expect(numberFormat.format('--12,345.12345')).toEqual('-12,345.12345') + expect(numberFormat.format('12,345.54321.12345')).toEqual('12,345.5432112345') + expect(numberFormat.format('-12,345..54321-')).toEqual('-12,345.54321') }) it('format numerical value', () => { - expect(numberFormat.format(0)).toEqual('0') - expect(numberFormat.format(0.)).toEqual('0') - expect(numberFormat.format(0.0)).toEqual('0') + expect(numberFormat.format(0)).toEqual('') + expect(numberFormat.format(0.)).toEqual('') + expect(numberFormat.format(0.0)).toEqual('') expect(numberFormat.format(-0.10)).toEqual('-0.1') - expect(numberFormat.format(-0.0)).toEqual('0') + expect(numberFormat.format(-0.0)).toEqual('') expect(numberFormat.format(0.10)).toEqual('0.1') - expect(numberFormat.format(12345.54921)).toEqual('12,345.55') - expect(numberFormat.format(12345.12345)).toEqual('12,345.12') - expect(numberFormat.format(12345.54321)).toEqual('12,345.54') - expect(numberFormat.format(12345.54321)).toEqual('12,345.54') + expect(numberFormat.format(12345.54921)).toEqual('12,345.54921') + expect(numberFormat.format(12345.12345)).toEqual('12,345.12345') + expect(numberFormat.format(12345.54321)).toEqual('12,345.54321') + expect(numberFormat.format(12345.54321)).toEqual('12,345.54321') }) it('format and clean numerical value', () => { - expect(numberFormat.clean().format(0)).toEqual('0') - expect(numberFormat.clean().format(0.)).toEqual('0') - expect(numberFormat.clean().format(0.0)).toEqual('0') - expect(numberFormat.clean().format(0.10)).toEqual('0.1') - expect(numberFormat.clean().format(-0.0)).toEqual('0') - expect(numberFormat.clean().format(-0.10)).toEqual('-0.1') - expect(numberFormat.clean().format(12345.54921)).toEqual('12,345.55') - expect(numberFormat.clean().format(12345.12345)).toEqual('12,345.12') - expect(numberFormat.clean().format(12345.54321)).toEqual('12,345.54') - expect(numberFormat.clean().format(12345.54321)).toEqual('12,345.54') + expect(numberFormat.clean(true).format(0)).toEqual('') + expect(numberFormat.clean(true).format(0.)).toEqual('') + expect(numberFormat.clean(true).format(0.0)).toEqual('') + expect(numberFormat.clean(true).format(0.10)).toEqual('0.1') + expect(numberFormat.clean(true).format(-0.0)).toEqual('') + expect(numberFormat.clean(true).format(-0.10)).toEqual('-0.1') + expect(numberFormat.clean(true).format(12345.54921)).toEqual('12,345.55') + expect(numberFormat.clean(true).format(12345.12345)).toEqual('12,345.12') + expect(numberFormat.clean(true).format(12345.54321)).toEqual('12,345.54') + expect(numberFormat.clean(true).format(12345.54321)).toEqual('12,345.54') }) }) describe('unformat when options are default', () => { const numberFormat = new NumberFormat({}) it('unformat string value', () => { - expect(numberFormat.unformat('0')).toEqual(0) - expect(numberFormat.unformat('0.')).toEqual(0) - expect(numberFormat.unformat('-0.0')).toEqual(0) - expect(numberFormat.unformat('0.10')).toEqual(0.1) - expect(numberFormat.unformat('0.0-')).toEqual(0) - expect(numberFormat.unformat('0.10-')).toEqual(-0.1) - expect(numberFormat.unformat('12,345.54921')).toEqual(12345.55) - expect(numberFormat.unformat('--12,345.12345')).toEqual(-12345.12) - expect(numberFormat.unformat('12,345.54321.12345')).toEqual(12345.54) - expect(numberFormat.unformat('-12,345..54321-')).toEqual(-12345.54) + expect(numberFormat.clean(true).unformat('0')).toEqual(0) + expect(numberFormat.clean(true).unformat('0.')).toEqual(0) + expect(numberFormat.clean(true).unformat('-0.0')).toEqual(0) + expect(numberFormat.clean(true).unformat('0.10')).toEqual(0.1) + expect(numberFormat.clean(true).unformat('0.0-')).toEqual(0) + expect(numberFormat.clean(true).unformat('0.10-')).toEqual(-0.1) + expect(numberFormat.clean(true).unformat('12,345.54921')).toEqual(12345.55) + expect(numberFormat.clean(true).unformat('--12,345.12345')).toEqual(-12345.12) + expect(numberFormat.clean(true).unformat('12,345.54321.12345')).toEqual(12345.54) + expect(numberFormat.clean(true).unformat('-12,345..54321-')).toEqual(-12345.54) }) it('unformat numerical value', () => { - expect(numberFormat.unformat(0)).toEqual(0) - expect(numberFormat.unformat(0.)).toEqual(0) - expect(numberFormat.unformat(0.0)).toEqual(0) - expect(numberFormat.unformat(-0.10)).toEqual(-0.1) - expect(numberFormat.unformat(-0.0)).toEqual(0) - expect(numberFormat.unformat(0.10)).toEqual(0.1) - expect(numberFormat.unformat(12345.54921)).toEqual(12345.55) - expect(numberFormat.unformat(12345.12345)).toEqual(12345.12) - expect(numberFormat.unformat(12345.54321)).toEqual(12345.54) - expect(numberFormat.unformat(12345.54321)).toEqual(12345.54) + expect(numberFormat.clean(true).unformat(0)).toEqual('') + expect(numberFormat.clean(true).unformat(0.)).toEqual('') + expect(numberFormat.clean(true).unformat(0.0)).toEqual('') + expect(numberFormat.clean(true).unformat(-0.10)).toEqual(-0.1) + expect(numberFormat.clean(true).unformat(-0.0)).toEqual('') + expect(numberFormat.clean(true).unformat(0.10)).toEqual(0.1) + expect(numberFormat.clean(true).unformat(12345.54921)).toEqual(12345.55) + expect(numberFormat.clean(true).unformat(12345.12345)).toEqual(12345.12) + expect(numberFormat.clean(true).unformat(12345.54321)).toEqual(12345.54) + expect(numberFormat.clean(true).unformat(12345.54321)).toEqual(12345.54) }) })