V-mask plugin playground
by Dmitriy Belyaev
HTML
<script src="https://unpkg.com/vue"></script>
<script src="https://cdn.jsdelivr.net/npm/v-mask/dist/v-mask.min.js"></script>
<div id="app">
<label>
{{label}}:
<input :type="type" :value="value" @input="onInput">
</label>
</div>
JavaScript
// jsfiddle fix
if(!String.prototype.contains) {
String.prototype.contains = {
contains(str) {
return this.indexOf(str) !== -1;
}
}.contains;
}
const DEFAULT_LABEL = 'Phone or e-mail';
const DEFAULT_TYPE = 'text';
new Vue({
el: '#app',
data: () => ({
label: DEFAULT_LABEL,
type: DEFAULT_TYPE,
value: ''
}),
methods: {
onInput(e) {
setTimeout(() => {
console.log(e.target.value = this.value);
}, 100);
const {value} = e.target;
const normalizedValue = value.trim().toLowerCase();
if(normalizedValue === '') {
return this.reset();
}
const firstChar = normalizedValue.charAt(0);
const firstCharCode = normalizedValue.charCodeAt(0);
if(firstChar === '+' || isNumberChar(firstCharCode)) {
return this.checkPhone(normalizedValue);
}
if(isLetterChar(firstCharCode)) {
return this.checkEmail(normalizedValue);
}
this.reset();
},
reset() {
this.value = '';
this.type = DEFAULT_TYPE;
this.label = DEFAULT_LABEL;
},
checkPhone(value, target) {
this.type = 'phone';
this.label = 'Phone';
this.value = formatPhone(value);
},
checkEmail(value) {
this.type = 'email';
this.label = 'Email';
this.value = formatEmail(value);
}
}
});
function formatPhone(value) {
// тут только для России, другие форматы доделывайте сами
const validChars = [...value.slice(value.startsWith('+7')
? 2
: ('+78'.contains(value[0])
? 1
: 0
)
)].filter(char => isNumberChar(char.charCodeAt(0))).slice(0, 10).join('');
return '+7' + (len => {
switch(true) {
case len < 3:
return '(' + validChars;
case len < 6:
return `(${validChars.slice(0, 3)}) ${validChars.slice(3)}`;
case len < 8:
return `(${validChars.slice(0, 3)}) ${validChars.slice(3, 6)}-${validChars.slice(6)}`;
default:
return `(${validChars.slice(0, 3)}) ${validChars.slice(3,...