vue-masked-input
Version:
Masked input component for Vue.js 2.X
340 lines (321 loc) • 10.1 kB
JavaScript
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
import InputMask from 'inputmask-core';
import ffpoly from './ff-polyfill'; // Firefox Polyfill for focus events
ffpoly();
export default {
name: 'MaskedInput',
render: function render(h) {
return h('input', {
ref: 'input',
attrs: {
disabled: this.maskCore === null || this.disabled
},
domProps: {
value: this.value
},
on: {
keydown: this.keyDown,
keypress: this.keyPress,
keyup: this.keyUp,
textInput: this.textInput,
mouseup: this.mouseUp,
focusout: this.focusOut,
cut: this.cut,
copy: this.copy,
paste: this.paste
}
});
},
data: function data() {
return {
marginLeft: 0,
maskCore: null,
updateAfterAll: false
};
},
props: {
value: {
type: String
},
mask: {
required: true,
validator: function validator(value) {
return !!(value && value.length >= 1 || value instanceof Object);
}
},
placeholderChar: {
type: String,
default: '_',
validator: function validator(value) {
return !!(value && value.length === 1);
}
},
disabled: {
type: Boolean,
default: false
}
},
watch: {
mask: function mask(newValue, oldValue) {
if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
this.initMask();
}
},
value: function value(newValue) {
if (this.maskCore) this.maskCore.setValue(newValue); // For multiple inputs support
}
},
mounted: function mounted() {
this.initMask();
},
methods: {
initMask: function initMask() {
var _this = this;
try {
if (this.mask instanceof Object) {
this.maskCore = new InputMask(this.mask);
} else {
this.maskCore = new InputMask({
pattern: this.mask,
value: '',
placeholderChar: this.placeholderChar,
/* eslint-disable quote-props */
formatCharacters: {
'a': {
validate: function validate(char) {
return (/^[A-Za-zА-Яа-я]$/.test(char)
);
}
},
'A': {
validate: function validate(char) {
return (/^[A-Za-zА-Яа-я]$/.test(char)
);
},
transform: function transform(char) {
return char.toUpperCase();
}
},
'*': {
validate: function validate(char) {
return (/^[\dA-Za-zА-Яа-я]$/.test(char)
);
}
},
'#': {
validate: function validate(char) {
return (/^[\dA-Za-zА-Яа-я]$/.test(char)
);
},
transform: function transform(char) {
return char.toUpperCase();
}
},
'+': {
validate: function validate() {
return true;
}
}
}
});
}
[].concat(_toConsumableArray(this.$refs.input.value)).reduce(function (memo, item) {
return _this.maskCore.input(item);
}, null);
this.maskCore.setSelection({
start: 0,
end: 0
});
if (this.$refs.input.value === '') {
this.$emit('input', '', '');
} else {
this.updateToCoreState();
}
} catch (e) {
this.maskCore = null;
this.$refs.input.value = 'Error';
this.$emit('input', this.$refs.input.value, '');
}
},
getValue: function getValue() {
return this.maskCore ? this.maskCore.getValue() : '';
},
keyDown: function keyDown(e) {
// Always
if (this.maskCore === null) {
e.preventDefault();
return;
}
this.setNativeSelection();
switch (e.keyCode) {
// backspace
case 8:
e.preventDefault();
if (this.maskCore.selection.start > this.marginLeft || this.maskCore.selection.start !== this.maskCore.selection.end) {
this.maskCore.backspace();
this.updateToCoreState();
}
break;
// left arrow
case 37:
e.preventDefault();
if (this.$refs.input.selectionStart === this.$refs.input.selectionEnd) {
// this.$refs.input.selectionEnd = this.$refs.input.selectionStart - 1; @TODO
this.$refs.input.selectionStart -= 1;
}
this.maskCore.selection = {
start: this.$refs.input.selectionStart,
end: this.$refs.input.selectionStart
};
this.updateToCoreState();
break;
// right arrow
case 39:
e.preventDefault();
if (this.$refs.input.selectionStart === this.$refs.input.selectionEnd) {
this.$refs.input.selectionEnd += 1;
}
this.maskCore.selection = {
start: this.$refs.input.selectionEnd,
end: this.$refs.input.selectionEnd
};
this.updateToCoreState();
break;
// end
case 35:
e.preventDefault();
this.$refs.input.selectionStart = this.$refs.input.value.length;
this.$refs.input.selectionEnd = this.$refs.input.value.length;
this.maskCore.selection = {
start: this.$refs.input.selectionEnd,
end: this.$refs.input.selectionEnd
};
this.updateToCoreState();
break;
// home
case 36:
e.preventDefault();
this.$refs.input.selectionStart = 0;
this.$refs.input.selectionEnd = 0;
this.maskCore.selection = {
start: this.$refs.input.selectionStart,
end: this.$refs.input.selectionStart
};
this.updateToCoreState();
break;
// delete
case 46:
e.preventDefault();
if (this.$refs.input.selectionStart === this.$refs.input.selectionEnd) {
this.maskCore.setValue('');
this.maskCore.setSelection({
start: 0,
end: 0
});
this.$refs.input.selectionStart = this.maskCore.selection.start;
this.$refs.input.selectionEnd = this.maskCore.selection.start;
} else {
this.maskCore.backspace();
}
this.updateToCoreState();
break;
default:
break;
}
},
keyPress: function keyPress(e) {
// works only on Desktop
if (e.ctrlKey) return; // Fix FF copy/paste issue
// IE & FF are not trigger textInput event, so we have to force it
/* eslint-disable */
var isIE = /*@cc_on!@*/false || !!document.documentMode; //by http://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser
/* eslint-enable */
var isFirefox = typeof InstallTrigger !== 'undefined';
if (isIE || isFirefox) {
e.preventDefault();
e.data = e.key;
this.textInput(e);
}
},
textInput: function textInput(e) {
if (e.preventDefault) e.preventDefault();
if (this.maskCore.input(e.data)) {
this.updateAfterAll = true;
}
this.updateToCoreState();
},
keyUp: function keyUp(e) {
if (e.keyCode === 9) {
// Preven change selection for Tab in
return;
}
this.updateToCoreState();
this.updateAfterAll = false;
},
cut: function cut(e) {
e.preventDefault();
if (this.$refs.input.selectionStart !== this.$refs.input.selectionEnd) {
try {
document.execCommand('copy');
} catch (err) {} // eslint-disable-line no-empty
this.maskCore.backspace();
this.updateToCoreState();
}
},
copy: function copy() {},
paste: function paste(e) {
var _this2 = this;
e.preventDefault();
var text = e.clipboardData.getData('text');
[].concat(_toConsumableArray(text)).reduce(function (memo, item) {
return _this2.maskCore.input(item);
}, null);
this.updateToCoreState();
},
updateToCoreState: function updateToCoreState() {
if (this.maskCore === null) {
return;
}
if (this.$refs.input.value !== this.maskCore.getValue()) {
this.$refs.input.value = this.maskCore.getValue();
this.$emit('input', this.$refs.input.value, this.maskCore.getRawValue());
}
this.$refs.input.selectionStart = this.maskCore.selection.start;
this.$refs.input.selectionEnd = this.maskCore.selection.end;
},
isEmpty: function isEmpty() {
if (this.maskCore === null) return true;
return this.maskCore.getValue() === this.maskCore.emptyValue;
},
focusOut: function focusOut() {
if (this.isEmpty()) {
this.$refs.input.value = '';
this.maskCore.setSelection({
start: 0,
end: 0
});
this.$emit('input', '', '');
}
},
setNativeSelection: function setNativeSelection() {
this.maskCore.selection = {
start: this.$refs.input.selectionStart,
end: this.$refs.input.selectionEnd
};
},
mouseUp: function mouseUp() {
if (this.isEmpty() && this.$refs.input.selectionStart === this.$refs.input.selectionEnd) {
this.maskCore.setSelection({
start: 0,
end: 0
});
this.$refs.input.selectionStart = this.maskCore.selection.start;
this.$refs.input.selectionEnd = this.maskCore.selection.start;
this.marginLeft = this.maskCore.selection.start;
this.updateToCoreState();
} else {
this.setNativeSelection();
}
}
}
};