Skip to content

Commit 233b47a

Browse files
author
Dipak Sarkar
committed
updated number formator
1 parent 5a46ec6 commit 233b47a

File tree

5 files changed

+63
-31
lines changed

5 files changed

+63
-31
lines changed

docs/.vuepress/components/Example.vue

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,14 @@ export default {
7272
priceDirective: 5432.1,
7373
priceUnmasked: 6789.10,
7474
config: {
75-
decimal: '.',
76-
separator: ',',
75+
decimal: ',',
76+
separator: '.',
7777
prefix: '$',
7878
suffix: '',
7979
precision: 2,
8080
masked: false
8181
}
8282
}
83-
},
84-
methods: {
85-
change (evt) {
86-
console.log('change', evt.target.value);
87-
}
8883
}
8984
}
9085
</script>

src/component.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
:value="maskedValue"
66
@change="change"
77
@input="input"
8-
v-number="{precision, decimal, separator, prefix, suffix}"
8+
v-number="config"
99
class="v-number"
1010
/>
1111
</template>
@@ -76,6 +76,9 @@ export default {
7676
computed: {
7777
emittedValue() {
7878
return this.masked ? this.maskedValue : this.unmaskedValue
79+
},
80+
config() {
81+
return this.$props
7982
}
8083
}
8184
}

src/core.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export function updateCursor(el, position) {
6767
* @param {Boolean} options.emit Wether to dispatch a new InputEvent or not
6868
* @param {Boolean} options.force Forces the update even if the old value and the new value are the same
6969
*/
70-
export function updateValue(el, vnode, { emit = true, force = false } = {}) {
70+
export function updateValue(el, vnode, { emit = true, force = false, clean = false } = {}) {
7171
const { config } = el[CONFIG_KEY]
7272
let { oldValue } = el[CONFIG_KEY]
7373

@@ -77,7 +77,7 @@ export function updateValue(el, vnode, { emit = true, force = false } = {}) {
7777
currentValue = currentValue || ''
7878

7979
if (force || oldValue !== currentValue) {
80-
const number = new NumberFormat(config)
80+
const number = new NumberFormat(config).clean(clean)
8181
const masked = number.format(currentValue)
8282
const unmasked = number.unformat(currentValue)
8383

@@ -121,3 +121,24 @@ export function inputHandler(event) {
121121
target.dispatchEvent(FacadeInputEvent())
122122
}
123123
}
124+
125+
/**
126+
* Blur event handler
127+
*
128+
* @param {Event} event The event object
129+
*/
130+
export function blurHandler(event) {
131+
const { target, detail } = event
132+
// We dont need to run this method on the event we emit (prevent event loop)
133+
if (detail && detail.facade) {
134+
return false
135+
}
136+
137+
const { oldValue } = target[CONFIG_KEY]
138+
139+
updateValue(target, null, { force: true, clean: true }, event)
140+
141+
if (oldValue !== target.value) {
142+
target.dispatchEvent(FacadeInputEvent())
143+
}
144+
}

src/directive.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,23 @@ export default {
1313

1414
inserted: (el) => {
1515
el = core.getInputElement(el)
16-
const config = el[CONFIG_KEY]
16+
const option = el[CONFIG_KEY]
1717
// prefer adding event listener to parent element to avoid Firefox bug which does not
1818
// execute `useCapture: true` event handlers before non-capturing event handlers
1919
const handlerOwner = el.parentElement || el
2020

2121
// use anonymous event handler to avoid inadvertently removing masking for all inputs within a container
22-
const handler = (e) => core.inputHandler(e)
22+
const oninput = (e) => core.inputHandler(e)
2323

24-
handlerOwner.addEventListener('input', handler, true)
24+
handlerOwner.addEventListener('input', oninput, true)
2525

26-
config.cleanup = () => handlerOwner.removeEventListener('input', handler, true)
26+
el.onblur = (e) => core.blurHandler(e)
27+
28+
option.cleanup = () => handlerOwner.removeEventListener('input', oninput, true)
2729
},
2830

2931
update: (el, { value, oldValue }, vnode) => {
3032
el = core.getInputElement(el)
31-
3233
if (value !== oldValue) {
3334
el[CONFIG_KEY].config = core.normalizeConfig(value)
3435
core.updateValue(el, vnode, { force: true })

src/number-format.js

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,33 @@ export default function NumberFormat(opt = options) {
99
this.input = this.options.null_value
1010
this.number = this.options.null_value
1111
this.isClean = false
12-
this.clean = () => {
13-
this.isClean = true
12+
this.clean = (clean = false) => {
13+
this.isClean = clean
1414
return this
1515
}
16-
this.negative = () => {
17-
const negetive = (this.input.toString().indexOf('-') >= 0 && this.realNumber() > 0) ? '-' : ''
18-
return negetive
16+
this.sign = () => {
17+
const sign = (this.input.toString().indexOf('-') >= 0 && this.realNumber() > 0) ? '-' : ''
18+
return sign
1919
}
20+
this.toNumber = (string) => Number(string)
21+
this.isNegative = this.sign() === '-'
2022
this.numbers = () => {
2123
if (typeof this.input === 'number') {
2224
this.number = this.input.toFixed(this.options.precision).toString().replace('-', '').replace('.', this.options.decimal)
25+
// eslint-disable-next-line no-restricted-globals
26+
} else if (!isNaN(this.toNumber(this.input))) {
27+
this.number = this.input.replace('-', '').replace('.', this.options.decimal)
2328
} else {
24-
this.number = this.numberOnly()
29+
const regExp = new RegExp(`[^0-9\\${this.options.decimal}]+`, 'gi')
30+
this.number = this.input.toString().replace(regExp, '')
31+
this.number = this.parts(this.number).join(this.options.decimal)
2532
}
2633
return this.number
2734
}
28-
this.numberOnly = () => {
29-
const regExp = new RegExp(`[^0-9\\${this.options.decimal}]+`, 'gi')
30-
this.number = this.input.toString().replace(regExp, '')
31-
return this.parts(this.number).join(this.options.decimal)
32-
}
33-
this.realNumber = () => Number(this.numbers().toString().replace(this.options.decimal, '.'))
35+
this.realNumber = () => this.toNumber(this.numbers().toString().replace(this.options.decimal, '.'))
3436
this.parts = (number = '', decimal = this.options.decimal) => {
3537
var parts = number.toString().split(decimal)
36-
parts[0] = (Number(parts[0]) ? Number(parts[0]) : 0)
38+
parts[0] = this.toNumber(parts[0]) || 0
3739
if (parts.length > 1) {
3840
parts[1] = parts.slice(1, parts.length).join('')
3941
parts = parts.slice(0, 2)
@@ -47,19 +49,29 @@ export default function NumberFormat(opt = options) {
4749
var parts = this.numbers().split(this.options.decimal)
4850
parts[0] = parts[0].toString().replace(/(\d)(?=(?:\d{3})+\b)/gm, `$1${this.options.separator}`)
4951
if (this.isClean) {
50-
parts[1] = Number(`.${parts[1]}`).toString().replace('0.', '')
52+
parts[1] = this.toNumber(`.${parts[1]}`).toString().replace('0.', '')
5153
return parts[1] && parts[1] > 0 ? parts.join(this.options.decimal) : parts[0]
5254
}
5355
return parts.join(this.options.decimal)
5456
}
57+
/**
58+
* Format the input with default config if there is no constructor config
59+
* @param {Number, String} input
60+
* @return {String}
61+
*/
5562
this.format = (input) => {
5663
if (input === '') return this.options.null_value
5764
this.input = input
58-
return this.negative() + this.options.prefix + this.addSeparator() + this.options.suffix
65+
return this.sign() + this.options.prefix + this.addSeparator() + this.options.suffix
5966
}
67+
/**
68+
* Unformat the input with default config if there is no constructor config
69+
* @param {Number, String} input
70+
* @return {String}
71+
*/
6072
this.unformat = (input) => {
6173
if (input === '') return this.options.null_value
6274
this.input = input
63-
return this.negative() + this.realNumber()
75+
return this.sign() + this.realNumber()
6476
}
6577
}

0 commit comments

Comments
 (0)