diff --git a/README.md b/README.md index 72e1a5b..4447ac7 100644 --- a/README.md +++ b/README.md @@ -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 + + + +``` + +and with vanilla JS attribute, but make sure that mask value is proper `JSON`, so use double quotes inside array: + +``` html + +``` + ## Source of Inspiration - [vue-the-mask](https://vuejs-tips.github.io/vue-the-mask/) diff --git a/dist/maska.js b/dist/maska.js index 41495a5..57f02bb 100644 --- a/dist/maska.js +++ b/dist/maska.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Maska",[],t):"object"==typeof exports?exports.Maska=t():e.Maska=t()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";function r(e,t,n){for(var r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],a=0,u=0,i="",c="";a1&&void 0!==arguments[1]?arguments[1]:{};if(function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),!t)throw new Error("Maska: no element for mask");if(n.tokens)for(var r in n.tokens)n.tokens[r]=s({},n.tokens[r]),n.tokens[r].pattern&&i(n.tokens[r].pattern)&&(n.tokens[r].pattern=new RegExp(n.tokens[r].pattern));this._opts={mask:n.mask,tokens:s({},a,{},n.tokens)},this._el=i(t)?document.querySelectorAll(t):t.length?t:[t],this.init()}var t,n,o;return t=e,(n=[{key:"init",value:function(){for(var e=this,t=0;t3&&void 0!==arguments[3])||arguments[3];return o(t).length>1?function(e){var t=o(e).sort((function(e,t){return e.length-t.length}));return function(e,n,r){for(var o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],u=0;ui.length))return a(e,i,r,o)}return""}}(t)(e,t,n,r):a(e,t,n,r)}function o(e){try{return JSON.parse(e)}catch(t){return[e]}}function a(e,t,n){for(var r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],o=0,a=0,i="",c="";o1&&void 0!==arguments[1]?arguments[1]:{};if(function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),!t)throw new Error("Maska: no element for mask");if(n.tokens)for(var r in n.tokens)n.tokens[r]=f({},n.tokens[r]),n.tokens[r].pattern&&s(n.tokens[r].pattern)&&(n.tokens[r].pattern=new RegExp(n.tokens[r].pattern));this._opts={mask:n.mask,tokens:f({},i,{},n.tokens)},this._el=s(t)?document.querySelectorAll(t):t.length?t:[t],this.init()}var t,n,o;return t=e,(n=[{key:"init",value:function(){for(var e=this,t=0;t
- +
-

v-maska="'+1 (###) ###-##-##'"

+

v-maska="['+1 (###) ##-##-##', '+1 (###) ###-##-##']"

@@ -65,6 +65,13 @@

data-mask="#*"

+
+ +
+ +
+

data-mask='["# cm", "#.# cm", "#.## cm"]'

+
@@ -88,6 +95,13 @@

data-mask="###"

+
+ +
+ +
+

data-mask='["###.###.###-##", "##.###.###/####-##"]'

+
diff --git a/package.json b/package.json index 0ea005a..9c56faa 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/directive.js b/src/directive.js index 153bc83..7325822 100644 --- a/src/directive.js +++ b/src/directive.js @@ -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 diff --git a/src/mask.js b/src/mask.js index 1426914..ee09b88 100644 --- a/src/mask.js +++ b/src/mask.js @@ -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 = '' diff --git a/test/mask.test.js b/test/mask.test.js index 8f92cdc..b599f0d 100644 --- a/test/mask.test.js +++ b/test/mask.test.js @@ -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') +})