Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: feature get raw (unmasked) value #284

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions src/__tests__/format.test.js
Original file line number Diff line number Diff line change
@@ -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));
});
Expand Down Expand Up @@ -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');
});
});
3 changes: 2 additions & 1 deletion src/directive.js
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -21,6 +21,7 @@ function updateValue(el, force = false) {
}

el.dataset.previousValue = value;
el.dataset.unmaskedValue = unMask(value, mask);
}

/**
Expand Down
101 changes: 68 additions & 33 deletions src/format.js
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -60,16 +33,78 @@ 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}`;
}

break;
}
}
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);
}