2
0
mirror of https://github.com/tenrok/maska.git synced 2026-06-05 16:42:28 +03:00

Add dynamic mask

This commit is contained in:
Alexander Shabunevich
2019-12-07 21:44:32 +03:00
parent 3104177848
commit 558b1a60d2
7 changed files with 83 additions and 9 deletions
+19 -1
View File
@@ -5,7 +5,7 @@ Simple zero-dependency input mask for Vue.js and vanilla JS. [Demo and examples]
- No dependencies
- Small size (~2 Kb gziped)
- Ability to define custom tokens
- Supports repeat symbols
- Supports repeat symbols and dynamic masks
- Works on any input (custom or native)
## Install
@@ -101,6 +101,24 @@ Default tokens:
You can add your own tokens by passing them in `maska` directive or `create` method at initialization (see above). **Important**: `pattern` field should be JS *regular expression* (`/[0-9]/`) or *string without delimiters* (`"[0-9]"`).
## Dynamic masks
To use several masks on single input, pass array instead of string as mask value.
You could use it with Vue directives:
``` html
<input v-maska="['+1 (###) ##-##-##', '+1 (###) ###-##-##']">
<input v-maska="{ mask: ['!#HHHHHH', '!#HHHHHH-HH'], tokens: { 'H': { pattern: /[0-9a-fA-F]/, uppercase: true }}}">
```
and with vanilla JS attribute, but make sure that mask value is proper `JSON`, so use double quotes inside array:
``` html
<input data-mask='["# cm", "#.# cm", "#.## cm"]'>
```
## Source of Inspiration
- [vue-the-mask](https://vuejs-tips.github.io/vue-the-mask/)
+1 -1
View File
File diff suppressed because one or more lines are too long
+16 -2
View File
@@ -25,9 +25,9 @@
<div class="field">
<label class="label">Phone with code: {{ phone }}</label>
<div class="control">
<input v-maska="'+1 (###) ###-##-##'" class="input" type="tel" autocomplete="tel" v-model="phone">
<input v-maska="['+1 (###) ##-##-##', '+1 (###) ###-##-##']" class="input" type="tel" autocomplete="tel" v-model="phone">
</div>
<p class="help is-family-code">v-maska="'+1 (###) ###-##-##'"</p>
<p class="help is-family-code">v-maska="['+1 (###) ##-##-##', '+1 (###) ###-##-##']"</p>
</div>
<div class="field">
<label class="label">Hex color (custom tokens): {{ color }}</label>
@@ -65,6 +65,13 @@
</div>
<p class="help is-family-code">data-mask="#*"</p>
</div>
<div class="field">
<label class="label">Dynamic mask</label>
<div class="control">
<input data-mask='["# cm", "#.# cm", "#.## cm"]' class="masked input">
</div>
<p class="help is-family-code">data-mask='["# cm", "#.# cm", "#.## cm"]'</p>
</div>
</div>
<div class="column">
<div class="field">
@@ -88,6 +95,13 @@
</div>
<p class="help is-family-code">data-mask="###"</p>
</div>
<div class="field">
<label class="label">CPF/CNPJ</label>
<div class="control">
<input data-mask='["###.###.###-##", "##.###.###/####-##"]' class="masked input">
</div>
<p class="help is-family-code">data-mask='["###.###.###-##", "##.###.###/####-##"]'</p>
</div>
</div>
</div>
</form>
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "maska",
"version": "1.0.3",
"version": "1.1.0",
"description": "Simple zero-dependency input mask for Vue.js and vanilla JS",
"keywords": [
"mask",
+4 -4
View File
@@ -4,11 +4,11 @@ import { isString } from './utils'
function getOpts (mask) {
const opts = {}
if (isString(mask)) {
opts.mask = mask
} else if (mask.mask) {
opts.mask = mask.mask
if (mask.mask) {
opts.mask = Array.isArray(mask.mask) ? JSON.stringify(mask.mask) : mask.mask
opts.tokens = mask.tokens ? { ...mask.tokens } : {}
} else {
opts.mask = Array.isArray(mask) ? JSON.stringify(mask) : mask
}
return opts
+31
View File
@@ -1,4 +1,35 @@
export default function mask (value, mask, tokens, masked = true) {
return (processMask(mask).length > 1)
? dynamic(mask)(value, mask, tokens, masked)
: process(value, mask, tokens, masked)
}
function processMask (mask) {
try {
return JSON.parse(mask)
} catch {
return [mask]
}
}
function dynamic (mask) {
const masks = processMask(mask).sort((a, b) => a.length - b.length)
return function (value, mask, tokens, masked = true) {
let i = 0
while (i < masks.length) {
const currentMask = masks[i]
i++
const nextMask = masks[i]
if (!(nextMask && process(value, nextMask, tokens, true).length > currentMask.length)) {
return process(value, currentMask, tokens, masked)
}
}
return '' // empty masks
}
}
function process (value, mask, tokens, masked = true) {
let im = 0
let iv = 0
let ret = ''
+11
View File
@@ -109,3 +109,14 @@ test('123abc -> # (A*)', () => {
test('Raw 123abc ##(A*)', () => {
expect(mask('123abc', '##(A*)', tokens, false)).toBe('12ABC')
})
test('Dynamic floats', () => {
expect(mask('1', '["# cm", "#.# cm", "#.## cm"]', tokens)).toBe('1 cm')
expect(mask('12', '["# cm", "#.# cm", "#.## cm"]', tokens)).toBe('1.2 cm')
expect(mask('123', '["# cm", "#.# cm", "#.## cm"]', tokens)).toBe('1.23 cm')
})
test('Dynamic CPF/CNPJ', () => {
expect(mask('12345678901', '["###.###.###-##", "##.###.###/####-##"]', tokens)).toBe('123.456.789-01')
expect(mask('12345678901234', '["###.###.###-##", "##.###.###/####-##"]', tokens)).toBe('12.345.678/9012-34')
})