vue-the-mask
Version:
Tiny (2KB) and dependency free mask input for Vue.js
68 lines (60 loc) • 1.93 kB
JavaScript
import masker from './masker'
import tokens from './tokens'
// https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events#The_old-fashioned_way
function event (name) {
var evt = document.createEvent('Event')
evt.initEvent(name, true, true)
return evt
}
export default function (el, binding) {
var config = binding.value
if (Array.isArray(config) || typeof config === 'string') {
config = {
mask: config,
tokens: tokens
}
}
if (el.tagName.toLocaleUpperCase() !== 'INPUT') {
var els = el.getElementsByTagName('input')
if (els.length !== 1) {
throw new Error("v-mask directive requires 1 input, found " + els.length)
} else {
el = els[0]
}
}
el.oninput = function (evt) {
if (!evt.isTrusted) return // avoid infinite loop
/* other properties to try to diferentiate InputEvent of Event (custom)
InputEvent (native)
cancelable: false
isTrusted: true
composed: true
isComposing: false
which: 0
Event (custom)
cancelable: true
isTrusted: false
*/
// by default, keep cursor at same position as before the mask
var position = el.selectionEnd
// save the character just inserted
var digit = el.value[position-1]
el.value = masker(el.value, config.mask, true, config.tokens)
// if the digit was changed, increment position until find the digit again
while (position < el.value.length && el.value.charAt(position-1) !== digit) {
position++
}
if (el === document.activeElement) {
el.setSelectionRange(position, position)
setTimeout(function () {
el.setSelectionRange(position, position)
}, 0)
}
el.dispatchEvent(event('input'))
}
var newDisplay = masker(el.value, config.mask, true, config.tokens)
if (newDisplay !== el.value) {
el.value = newDisplay
el.dispatchEvent(event('input'))
}
}