diff --git a/dist/directive.d.ts b/dist/directive.d.ts new file mode 100644 index 0000000..5537644 --- /dev/null +++ b/dist/directive.d.ts @@ -0,0 +1,7 @@ +declare function bind(el: any, binding: any, vnode: any): void; +declare function componentUpdated(el: any, binding: any, vnode: any, oldVnode: any): void; +declare const _default: { + bind: typeof bind; + componentUpdated: typeof componentUpdated; +}; +export default _default; diff --git a/dist/directive.js b/dist/directive.js new file mode 100644 index 0000000..b7b6790 --- /dev/null +++ b/dist/directive.js @@ -0,0 +1,82 @@ +"use strict"; +exports.__esModule = true; +var lodash_1 = require("lodash"); +var masker_1 = require("./masker"); +var predefined_1 = require("./predefined"); +var utils_1 = require("./utils"); +var tokens_1 = require("./tokens"); +// Helpers +function event(name) { + var evt = document.createEvent('Event'); + evt.initEvent(name, true, true); + return evt; +} +function getInput(el) { + if (el.tagName.toLocaleUpperCase() !== 'INPUT') { + var els = el.getElementsByTagName('input'); + if (els.length !== 1) { + throw new Error("v-mask requires 1 input, found " + els.length); + } + else { + el = els[0]; + } + } + return el; +} +function getConfig(binding) { + var config = binding.value || {}; + if (Array.isArray(config) || typeof config === 'string') { + config = { + masked: true, + mask: config, + unmaskedVar: null, + tokens: tokens_1["default"] + }; + } + config.mask = predefined_1["default"](config.mask) || config.mask || ''; + return config; +} +function run(el, eventName, config, vnode) { + var position = el.selectionEnd; + // save the character just inserted + var digit = el.value[position - 1]; + el.value = masker_1["default"](el.value, config.mask, config.masked, 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); + } + if (config.unmaskedVar) { + lodash_1.set(vnode.context, config.unmaskedVar, utils_1.unmaskText(el.value)); + } + el.dispatchEvent(event(eventName)); +} +// Vue.js directive hooks +function bind(el, binding, vnode) { + if (binding.value === false) { + return; + } + el = getInput(el); + run(el, 'input', getConfig(binding), vnode); +} +function componentUpdated(el, binding, vnode, oldVnode) { + if (binding.value === false) { + return; + } + // Prevent firing endless events + var data = vnode.data.props || vnode.data.model; + var oldData = oldVnode.data.props || oldVnode.data.model; + if (data && data.value === oldData.value) { + return; + } + el = getInput(el); + el.value = data ? data.value : el.value; + run(el, 'input', getConfig(binding), vnode); +} +exports["default"] = { bind: bind, componentUpdated: componentUpdated }; diff --git a/dist/index.d.ts b/dist/index.d.ts index 081ca8c..28b4c76 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1,3 +1,4 @@ -export declare const mask: { - bind(el: any, binding: any, vnode: any): void; -}; +import mask from './directive'; +declare function install(Vue: any): void; +export { mask }; +export default install; diff --git a/dist/index.js b/dist/index.js index 9808f24..5c7609c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,70 +1,9 @@ "use strict"; exports.__esModule = true; -var lodash_1 = require("lodash"); -var masker_1 = require("./masker"); -var predefined_1 = require("./predefined"); -var utils_1 = require("./utils"); -var tokens_1 = require("./tokens"); -function event(name) { - var evt = document.createEvent('Event'); - evt.initEvent(name, true, true); - return evt; +var directive_1 = require("./directive"); +exports.mask = directive_1["default"]; +/* tslint:disable-next-line:variable-name */ +function install(Vue) { + Vue.directive('mask', directive_1["default"]); } -exports.mask = { - bind: function (el, binding, vnode) { - // console.log ('bind'); - var config = binding.value || {}; - if (Array.isArray(config) || typeof config === 'string') { - config = { - masked: true, - mask: config, - unmaskedVar: null, - tokens: tokens_1["default"] - }; - } - config.mask = predefined_1["default"](config.mask) || config.mask || ''; - 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 - // 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_1["default"](el.value, config.mask, config.masked, 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); - } - if (config.unmaskedVar) { - lodash_1.set(vnode.context, config.unmaskedVar, utils_1.unmaskText(el.value)); - } - el.dispatchEvent(event('input')); - }; - var newDisplay = masker_1["default"](el.value, config.mask, config.masked, config.tokens); - if (newDisplay !== el.value) { - el.value = newDisplay; - if (config.unmaskedVar) { - lodash_1.set(vnode.context, config.unmaskedVar, utils_1.unmaskText(el.value)); - } - el.dispatchEvent(event('input')); - } - } -}; +exports["default"] = install; diff --git a/package.json b/package.json index 40c2053..7b9a8af 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@titou10/v-mask", "description": "mask directive for vue.js that exposes the unmasked value", - "version": "0.9.5", + "version": "1.0.0", "author": "Denis Forveille ", "license": "MIT", "keywords": [ diff --git a/src/directive.ts b/src/directive.ts new file mode 100644 index 0000000..e841af8 --- /dev/null +++ b/src/directive.ts @@ -0,0 +1,85 @@ + +import { set } from 'lodash'; + +import masker from './masker'; +import getPredefined from './predefined'; +import { unmaskText } from './utils'; +import tokens from './tokens'; + +// Helpers +function event(name: string) { + const evt = document.createEvent('Event'); + evt.initEvent(name, true, true); + return evt; +} + +function getInput(el) { + if (el.tagName.toLocaleUpperCase() !== 'INPUT') { + const els = el.getElementsByTagName('input'); + if (els.length !== 1) { + throw new Error(`v-mask requires 1 input, found ${els.length}`); + } else { el = els[0]; } + } + return el; +} + +function getConfig(binding) { + let config = binding.value || {}; + + if (Array.isArray(config) || typeof config === 'string') { + config = { + masked: true, + mask: config, + unmaskedVar: null, + tokens + }; + } + config.mask = getPredefined(config.mask) || config.mask || ''; + return config; +} + +function run(el , eventName: string, config, vnode) { + let position = el.selectionEnd; + // save the character just inserted + const digit = el.value[position - 1]; + el.value = masker(el.value, config.mask, config.masked, 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); + } + if (config.unmaskedVar) { + set(vnode.context, config.unmaskedVar, unmaskText(el.value)); + } + el.dispatchEvent(event(eventName)); +} + +// Vue.js directive hooks + +function bind(el, binding, vnode) { + if (binding.value === false) { return; } + + el = getInput(el); + run(el, 'input', getConfig(binding), vnode); +} + +function componentUpdated(el, binding, vnode, oldVnode) { + if (binding.value === false) { return; } + + // Prevent firing endless events + const data = vnode.data.props || vnode.data.model; + const oldData = oldVnode.data.props || oldVnode.data.model; + if (data && data.value === oldData.value) { return; } + + el = getInput(el); + el.value = data ? data.value : el.value; + run(el, 'input', getConfig(binding), vnode); +} + +export default { bind, componentUpdated }; diff --git a/src/dynamic-mask.ts b/src/dynamic-mask.ts index de4dcad..08083e5 100644 --- a/src/dynamic-mask.ts +++ b/src/dynamic-mask.ts @@ -1,6 +1,6 @@ -export default function dynamicMask(maskit: any , masks: any , tokens: any) { - masks = masks.slice().sort((a: any, b: any) => a.length - b.length); - return function(value: any, mask: any, masked = true) { +export default function dynamicMask(maskit , masks , tokens) { + masks = masks.slice().sort((a, b) => a.length - b.length); + return function(value, mask, masked = true) { let i = 0; while (i < masks.length) { const currentMask = masks[i]; diff --git a/src/index.ts b/src/index.ts index 74aa17a..8b03a0d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,76 +1,9 @@ +import mask from './directive'; -import { set } from 'lodash'; - -import masker from './masker'; -import getPredefined from './predefined'; -import { unmaskText } from './utils'; -import tokens from './tokens'; - -function event(name: string) { - const evt = document.createEvent('Event'); - evt.initEvent(name, true, true); - return evt; +/* tslint:disable-next-line:variable-name */ +function install(Vue) { + Vue.directive('mask', mask); } -export const mask = { - bind(el: any, binding: any, vnode: any) { - // console.log ('bind'); - let config = binding.value || {}; - - if (Array.isArray(config) || typeof config === 'string') { - config = { - masked: true, - mask: config, - unmaskedVar: null, - tokens - }; - } - config.mask = getPredefined(config.mask) || config.mask || ''; - - if (el.tagName.toLocaleUpperCase() !== 'INPUT') { - const 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: any) { - if (!evt.isTrusted) { return; } // avoid infinite loop - // by default, keep cursor at same position as before the mask - let position = el.selectionEnd; - // save the character just inserted - const digit = el.value[position - 1]; - el.value = masker(el.value, config.mask, config.masked, 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); - } - if (config.unmaskedVar) { - set(vnode.context, config.unmaskedVar, unmaskText(el.value)); - } - el.dispatchEvent(event('input')); - }; - - const newDisplay = masker(el.value, - config.mask, - config.masked, - config.tokens); - if (newDisplay !== el.value) { - el.value = newDisplay; - if (config.unmaskedVar) { - set(vnode.context, config.unmaskedVar, unmaskText(el.value)); - } - el.dispatchEvent(event('input')); - } - } -}; +export { mask }; +export default install; diff --git a/tsconfig.json b/tsconfig.json index 078fc12..d5ea969 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "CommonJS", "outDir": "./dist/", - "noImplicitAny": true, + "noImplicitAny": false, "declaration": true, "strict": true }