diff --git a/src/__tests__/format.test.js b/src/__tests__/format.test.js index 8e0f5de4..187ea52e 100644 --- a/src/__tests__/format.test.js +++ b/src/__tests__/format.test.js @@ -1,6 +1,6 @@ -import format from '../format'; +import format, { unMask } from '../format'; -describe('format.js', () => { +describe('default export', () => { it('should be a function', () => { expect(format).toEqual(expect.any(Function)); }); @@ -80,3 +80,26 @@ describe('format.js', () => { expect(format('365038704', '###-##-####')).toBe('365-03-8704'); }); }); + +describe('.unMask()', () => { + it('should return the entry value without the mask', () => { + // time with seconds + expect(unMask('11:15:15', '##:##:##')).toBe('111515'); + // hours and minutes + expect(unMask('20h15m', '##h##m')).toBe('2015'); + // date-time + expect(unMask('27/10/2016 23:15', '##/##/#### ##:##')).toBe('271020162315'); + // credit card + expect(unMask('4532 4782 5524 7634', '#### #### #### ####')).toBe('4532478255247634'); + // phone number + expect(unMask('(999) 999-9999', '(###) ###-####')).toBe('9999999999'); + // phone number (US) + expect(unMask('+1 (999) 999-9999', '+1 (###) ###-####')).toBe('9999999999'); + // CPF + expect(unMask('390.533.447-05', '###.###.###-##')).toBe('39053344705'); + // CPNJ + expect(unMask('53.288.196/0001-28', '##.###.###/####-##')).toBe('53288196000128'); + // Social Security number + expect(unMask('365-03-8704', '###-##-####')).toBe('365038704'); + }); +}); diff --git a/src/directive.js b/src/directive.js index 295adc03..c7fa2499 100644 --- a/src/directive.js +++ b/src/directive.js @@ -1,5 +1,5 @@ /* eslint-disable no-param-reassign */ -import format from './format'; +import format, { unMask } from './format'; import { trigger, queryInputElementInside } from './utils'; import { isAndroid, isChrome } from './utils/env'; @@ -21,6 +21,7 @@ function updateValue(el, force = false) { } el.dataset.previousValue = value; + el.dataset.unmaskedValue = unMask(value, mask); } /** diff --git a/src/format.js b/src/format.js index 31090d12..020b451a 100644 --- a/src/format.js +++ b/src/format.js @@ -1,48 +1,21 @@ /* eslint-disable no-param-reassign, no-unused-expressions */ /** - * Simple format function borrowed from PureMask.js - * {@link https://github.com/romulobrasil/PureMask.js} + * Applies mask to data. * * @param {String} text String to mask (input value) * @param {String} [wholeMask] Mask format, like `####-##` * @returns {string} Formatted text */ -export default function (text, wholeMask) { - if (!wholeMask) return text; - - const maskStartRegExp = /^([^#ANX]+)/; - - if (+text.length === 1 && maskStartRegExp.test(wholeMask)) { - text = maskStartRegExp.exec(wholeMask)[0] + text; - } - +export const mask = (text, wholeMask) => { let newText = ''; let charOffset = 0; - // Cleans data to avoid value loss on dynamic mask changing - for (let maskIndex = 0; maskIndex < wholeMask.length; maskIndex += 1) { - const mask = wholeMask.charAt(maskIndex); - switch (mask) { - case '#': - break; - case 'A': - break; - case '?': - break; - case 'N': - break; - case 'X': - break; - default: - text = text.replace(mask, ''); - } - } for (let maskIndex = 0, x = 1; x && maskIndex < wholeMask.length; maskIndex += 1) { const char = text.charAt(maskIndex - charOffset); - const mask = wholeMask.charAt(maskIndex); + const maskChar = wholeMask.charAt(maskIndex); - switch (mask) { + switch (maskChar) { case '#': /\d/.test(char) ? newText += char : x = 0; break; @@ -60,11 +33,11 @@ export default function (text, wholeMask) { newText += char; break; default: - newText += mask; + newText += maskChar; // preserve characters that are in the same spot we need to insert a mask // character by shifting the data over to the right (issue #5, & #7) - if (char && char !== mask) { + if (char && char !== maskChar) { text = ` ${text}`; } @@ -72,4 +45,66 @@ export default function (text, wholeMask) { } } return newText; +}; + +/** + * Returns text without mask-provided delimiters + * @example + * unMask('11:12', '##:##'); // -> 1112 + * + * @param {String} text - String to clean (input value) + * @param {String} [wholeMask] - Mask format, like `####-##` + * @returns {string} Cleaned text + */ +export const unMask = (text, wholeMask) => { + for (let maskIndex = 0; maskIndex < wholeMask.length; maskIndex += 1) { + const maskChar = wholeMask.charAt(maskIndex); + switch (maskChar) { + case '#': + break; + case 'A': + break; + case '?': + break; + case 'N': + break; + case 'X': + break; + default: + text = text.replace(maskChar, ''); + } + } + + return text; +}; + +/** + * Prepares data. + * + * @param {String} text String to prepare (input value) + * @param {String} [wholeMask] Mask format, like `####-##` + * @returns {string} Prepared text + */ +export const prepare = (text, wholeMask) => { + const maskStartRegExp = /^([^#ANX]+)/; + + if (+text.length === 1 && maskStartRegExp.test(wholeMask)) { + text = maskStartRegExp.exec(wholeMask)[0] + text; + } + + return text; +}; + +/** + * Simple format function borrowed from PureMask.js + * {@link https://github.com/romulobrasil/PureMask.js} + * + * @param {String} text String to mask (input value) + * @param {String} [wholeMask] Mask format, like `####-##` + * @returns {string} Formatted text + */ +export default function (text, wholeMask) { + if (!wholeMask) return text; + + return mask(unMask(prepare(text, wholeMask), wholeMask), wholeMask); }