ngx-mask-fork
Version:
awesome ngx mask
1,076 lines (1,071 loc) • 66.8 kB
JavaScript
import { __read, __decorate, __param, __metadata, __extends, __awaiter, __generator, __assign } from 'tslib';
import { InjectionToken, Inject, Injectable, ElementRef, Renderer2, Input, HostListener, Directive, forwardRef, Pipe, NgModule } from '@angular/core';
import { FormControl, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
import { DOCUMENT } from '@angular/common';
var config = new InjectionToken('config');
var NEW_CONFIG = new InjectionToken('NEW_CONFIG');
var INITIAL_CONFIG = new InjectionToken('INITIAL_CONFIG');
var initialConfig = {
suffix: '',
prefix: '',
thousandSeparator: ' ',
decimalMarker: '.',
clearIfNotMatch: false,
showTemplate: false,
showMaskTyped: false,
placeHolderCharacter: '_',
dropSpecialCharacters: true,
hiddenInput: undefined,
shownMaskExpression: '',
separatorLimit: '',
allowNegativeNumbers: false,
validation: true,
// tslint:disable-next-line: quotemark
specialCharacters: ['-', '/', '(', ')', '.', ':', ' ', '+', ',', '@', '[', ']', '"', "'"],
patterns: {
'0': {
pattern: new RegExp('\\d'),
},
'9': {
pattern: new RegExp('\\d'),
optional: true,
},
X: {
pattern: new RegExp('\\d'),
symbol: '*',
},
A: {
pattern: new RegExp('[a-zA-Z0-9]'),
},
S: {
pattern: new RegExp('[a-zA-Z]'),
},
d: {
pattern: new RegExp('\\d'),
},
m: {
pattern: new RegExp('\\d'),
},
M: {
pattern: new RegExp('\\d'),
},
H: {
pattern: new RegExp('\\d'),
},
h: {
pattern: new RegExp('\\d'),
},
s: {
pattern: new RegExp('\\d'),
},
},
};
var timeMasks = ['Hh:m0:s0', 'Hh:m0', 'm0:s0'];
var withoutValidation = [
'percent',
'Hh',
's0',
'm0',
'separator',
'd0/M0/0000',
'd0/M0',
'd0',
'M0',
];
var MaskApplierService = /** @class */ (function () {
function MaskApplierService(_config) {
var _this = this;
this._config = _config;
this.maskExpression = '';
this.actualValue = '';
this.shownMaskExpression = '';
this._formatWithSeparators = function (str, thousandSeparatorChar, decimalChar, precision) {
var x = str.split(decimalChar);
var decimals = x.length > 1 ? "" + decimalChar + x[1] : '';
var res = x[0];
var separatorLimit = _this.separatorLimit.replace(/\s/g, '');
if (separatorLimit && +separatorLimit) {
if (res[0] === '-') {
res = "-" + res.slice(1, res.length).slice(0, separatorLimit.length);
}
else {
res = res.slice(0, separatorLimit.length);
}
}
var rgx = /(\d+)(\d{3})/;
while (thousandSeparatorChar && rgx.test(res)) {
res = res.replace(rgx, '$1' + thousandSeparatorChar + '$2');
}
if (precision === undefined) {
return res + decimals;
}
else if (precision === 0) {
return res;
}
return res + decimals.substr(0, precision + 1);
};
this.percentage = function (str) {
return Number(str) >= 0 && Number(str) <= 100;
};
this.getPrecision = function (maskExpression) {
var x = maskExpression.split('.');
if (x.length > 1) {
return Number(x[x.length - 1]);
}
return Infinity;
};
this.checkInputPrecision = function (inputValue, precision, decimalMarker) {
if (precision < Infinity) {
var precisionRegEx = new RegExp(_this._charToRegExpExpression(decimalMarker) + ("\\d{" + precision + "}.*$"));
var precisionMatch = inputValue.match(precisionRegEx);
if (precisionMatch && precisionMatch[0].length - 1 > precision) {
inputValue = inputValue.substring(0, inputValue.length - 1);
}
else if (precision === 0 && inputValue.endsWith(decimalMarker)) {
inputValue = inputValue.substring(0, inputValue.length - 1);
}
}
return inputValue;
};
this._shift = new Set();
this.clearIfNotMatch = this._config.clearIfNotMatch;
this.dropSpecialCharacters = this._config.dropSpecialCharacters;
this.maskSpecialCharacters = this._config.specialCharacters;
this.maskAvailablePatterns = this._config.patterns;
this.prefix = this._config.prefix;
this.suffix = this._config.suffix;
this.thousandSeparator = this._config.thousandSeparator;
this.decimalMarker = this._config.decimalMarker;
this.hiddenInput = this._config.hiddenInput;
this.showMaskTyped = this._config.showMaskTyped;
this.placeHolderCharacter = this._config.placeHolderCharacter;
this.validation = this._config.validation;
this.separatorLimit = this._config.separatorLimit;
this.allowNegativeNumbers = this._config.allowNegativeNumbers;
}
MaskApplierService.prototype.applyMaskWithPattern = function (inputValue, maskAndPattern) {
var _a = __read(maskAndPattern, 2), mask = _a[0], customPattern = _a[1];
this.customPattern = customPattern;
return this.applyMask(inputValue, mask);
};
MaskApplierService.prototype.applyMask = function (inputValue, maskExpression, position, cb) {
if (position === void 0) { position = 0; }
if (cb === void 0) { cb = function () { }; }
if (inputValue === undefined || inputValue === null || maskExpression === undefined) {
return '';
}
var cursor = 0;
var result = '';
var multi = false;
var backspaceShift = false;
var shift = 1;
var stepBack = false;
if (inputValue.slice(0, this.prefix.length) === this.prefix) {
inputValue = inputValue.slice(this.prefix.length, inputValue.length);
}
if (!!this.suffix && inputValue.endsWith(this.suffix)) {
inputValue = inputValue.slice(0, inputValue.length - this.suffix.length);
}
var inputArray = inputValue.toString().split('');
if (maskExpression === 'IP') {
this.ipError = !!(inputArray.filter(function (i) { return i === '.'; }).length < 3 && inputArray.length < 7);
maskExpression = '099.099.099.099';
}
var arr = [];
for (var i = 0; i < inputValue.length; i++) {
if (inputValue[i].match('\\d')) {
arr.push(inputValue[i]);
}
}
if (maskExpression === 'CPF_CNPJ') {
this.cpfCnpjError = !!(arr.length !== 11 && arr.length !== 14 && arr.length !== 15);
if (arr.length > 11) {
maskExpression = '00.000.000/0000-00';
}
else {
maskExpression = '000.000.000-00';
}
}
if (maskExpression.startsWith('percent')) {
if (inputValue.match('[a-z]|[A-Z]') || inputValue.match(/[-!$%^&*()_+|~=`{}\[\]:";'<>?,\/]/)) {
inputValue = this._stripToDecimal(inputValue);
var precision = this.getPrecision(maskExpression);
inputValue = this.checkInputPrecision(inputValue, precision, '.');
}
if (inputValue.indexOf('.') > 0 && !this.percentage(inputValue.substring(0, inputValue.indexOf('.')))) {
var base = inputValue.substring(0, inputValue.indexOf('.') - 1);
inputValue = "" + base + inputValue.substring(inputValue.indexOf('.'), inputValue.length);
}
if (this.percentage(inputValue)) {
result = inputValue;
}
else {
result = inputValue.substring(0, inputValue.length - 1);
}
}
else if (maskExpression.startsWith('separator')) {
if (inputValue.match('[wа-яА-Я]') ||
inputValue.match('[ЁёА-я]') ||
inputValue.match('[a-z]|[A-Z]') ||
inputValue.match(/[-@#!$%\\^&*()_£¬'+|~=`{}\[\]:";<>.?\/]/) ||
inputValue.match('[^A-Za-z0-9,]')) {
inputValue = this._stripToDecimal(inputValue);
}
inputValue =
inputValue.length > 1 && inputValue[0] === '0' && inputValue[1] !== this.decimalMarker
? inputValue.slice(1, inputValue.length)
: inputValue;
// TODO: we had different rexexps here for the different cases... but tests dont seam to bother - check this
// separator: no COMMA, dot-sep: no SPACE, COMMA OK, comma-sep: no SPACE, COMMA OK
var thousandSeperatorCharEscaped = this._charToRegExpExpression(this.thousandSeparator);
var decimalMarkerEscaped = this._charToRegExpExpression(this.decimalMarker);
var invalidChars = '@#!$%^&*()_+|~=`{}\\[\\]:\\s,";<>?\\/'
.replace(thousandSeperatorCharEscaped, '')
.replace(decimalMarkerEscaped, '');
var invalidCharRegexp = new RegExp('[' + invalidChars + ']');
if (inputValue.match(invalidCharRegexp)) {
inputValue = inputValue.substring(0, inputValue.length - 1);
}
var precision = this.getPrecision(maskExpression);
inputValue = this.checkInputPrecision(inputValue, precision, this.decimalMarker);
var strForSep = inputValue.replace(new RegExp(thousandSeperatorCharEscaped, 'g'), '');
result = this._formatWithSeparators(strForSep, this.thousandSeparator, this.decimalMarker, precision);
var commaShift = result.indexOf(',') - inputValue.indexOf(',');
var shiftStep = result.length - inputValue.length;
if (shiftStep > 0 && result[position] !== ',') {
backspaceShift = true;
var _shift = 0;
do {
this._shift.add(position + _shift);
_shift++;
} while (_shift < shiftStep);
}
else if ((commaShift !== 0 && position > 0 && !(result.indexOf(',') >= position && position > 3)) ||
(!(result.indexOf('.') >= position && position > 3) && shiftStep <= 0)) {
this._shift.clear();
backspaceShift = true;
shift = shiftStep;
position += shiftStep;
this._shift.add(position);
}
else {
this._shift.clear();
}
}
else {
for (
// tslint:disable-next-line
var i = 0, inputSymbol = inputArray[0]; i < inputArray.length; i++, inputSymbol = inputArray[i]) {
if (cursor === maskExpression.length) {
break;
}
if (this._checkSymbolMask(inputSymbol, maskExpression[cursor]) && maskExpression[cursor + 1] === '?') {
result += inputSymbol;
cursor += 2;
}
else if (maskExpression[cursor + 1] === '*' &&
multi &&
this._checkSymbolMask(inputSymbol, maskExpression[cursor + 2])) {
result += inputSymbol;
cursor += 3;
multi = false;
}
else if (this._checkSymbolMask(inputSymbol, maskExpression[cursor]) && maskExpression[cursor + 1] === '*') {
result += inputSymbol;
multi = true;
}
else if (maskExpression[cursor + 1] === '?' &&
this._checkSymbolMask(inputSymbol, maskExpression[cursor + 2])) {
result += inputSymbol;
cursor += 3;
}
else if (this._checkSymbolMask(inputSymbol, maskExpression[cursor]) ||
(this.hiddenInput &&
this.maskAvailablePatterns[maskExpression[cursor]] &&
this.maskAvailablePatterns[maskExpression[cursor]].symbol === inputSymbol)) {
if (maskExpression[cursor] === 'H') {
if (Number(inputSymbol) > 2) {
cursor += 1;
var shiftStep = /[*?]/g.test(maskExpression.slice(0, cursor)) ? inputArray.length : cursor;
this._shift.add(shiftStep + this.prefix.length || 0);
i--;
continue;
}
}
if (maskExpression[cursor] === 'h') {
if (result === '2' && Number(inputSymbol) > 3) {
cursor += 1;
i--;
continue;
}
}
if (maskExpression[cursor] === 'm') {
if (Number(inputSymbol) > 5) {
cursor += 1;
var shiftStep = /[*?]/g.test(maskExpression.slice(0, cursor)) ? inputArray.length : cursor;
this._shift.add(shiftStep + this.prefix.length || 0);
i--;
continue;
}
}
if (maskExpression[cursor] === 's') {
if (Number(inputSymbol) > 5) {
cursor += 1;
var shiftStep = /[*?]/g.test(maskExpression.slice(0, cursor)) ? inputArray.length : cursor;
this._shift.add(shiftStep + this.prefix.length || 0);
i--;
continue;
}
}
var daysCount = 31;
if (maskExpression[cursor] === 'd') {
if (Number(inputValue.slice(cursor, cursor + 2)) > daysCount || inputValue[cursor + 1] === '/') {
cursor += 1;
var shiftStep = /[*?]/g.test(maskExpression.slice(0, cursor)) ? inputArray.length : cursor;
this._shift.add(shiftStep + this.prefix.length || 0);
i--;
continue;
}
}
if (maskExpression[cursor] === 'M') {
var monthsCount = 12;
// mask without day
var withoutDays = cursor === 0 &&
(Number(inputSymbol) > 2 ||
Number(inputValue.slice(cursor, cursor + 2)) > monthsCount ||
inputValue[cursor + 1] === '/');
// day<10 && month<12 for input
var day1monthInput = inputValue.slice(cursor - 3, cursor - 1).includes('/') &&
((inputValue[cursor - 2] === '/' &&
Number(inputValue.slice(cursor - 1, cursor + 1)) > monthsCount &&
inputValue[cursor] !== '/') ||
inputValue[cursor] === '/' ||
(inputValue[cursor - 3] === '/' &&
Number(inputValue.slice(cursor - 2, cursor)) > monthsCount &&
inputValue[cursor - 1] !== '/') ||
inputValue[cursor - 1] === '/');
// 10<day<31 && month<12 for input
var day2monthInput = Number(inputValue.slice(cursor - 3, cursor - 1)) <= daysCount &&
!inputValue.slice(cursor - 3, cursor - 1).includes('/') &&
inputValue[cursor - 1] === '/' &&
(Number(inputValue.slice(cursor, cursor + 2)) > monthsCount || inputValue[cursor + 1] === '/');
// day<10 && month<12 for paste whole data
var day1monthPaste = Number(inputValue.slice(cursor - 3, cursor - 1)) > daysCount &&
!inputValue.slice(cursor - 3, cursor - 1).includes('/') &&
!inputValue.slice(cursor - 2, cursor).includes('/') &&
Number(inputValue.slice(cursor - 2, cursor)) > monthsCount;
// 10<day<31 && month<12 for paste whole data
var day2monthPaste = Number(inputValue.slice(cursor - 3, cursor - 1)) <= daysCount &&
!inputValue.slice(cursor - 3, cursor - 1).includes('/') &&
inputValue[cursor - 1] !== '/' &&
Number(inputValue.slice(cursor - 1, cursor + 1)) > monthsCount;
if (withoutDays || day1monthInput || day2monthInput || day1monthPaste || day2monthPaste) {
cursor += 1;
var shiftStep = /[*?]/g.test(maskExpression.slice(0, cursor)) ? inputArray.length : cursor;
this._shift.add(shiftStep + this.prefix.length || 0);
i--;
continue;
}
}
result += inputSymbol;
cursor++;
}
else if (this.maskSpecialCharacters.indexOf(maskExpression[cursor]) !== -1) {
result += maskExpression[cursor];
cursor++;
var shiftStep = /[*?]/g.test(maskExpression.slice(0, cursor)) ? inputArray.length : cursor;
this._shift.add(shiftStep + this.prefix.length || 0);
i--;
}
else if (this.maskSpecialCharacters.indexOf(inputSymbol) > -1 &&
this.maskAvailablePatterns[maskExpression[cursor]] &&
this.maskAvailablePatterns[maskExpression[cursor]].optional) {
if (!!inputArray[cursor] &&
maskExpression !== '099.099.099.099' &&
maskExpression !== '000.000.000-00' &&
maskExpression !== '00.000.000/0000-00') {
result += inputArray[cursor];
}
cursor++;
i--;
}
else if (this.maskExpression[cursor + 1] === '*' &&
this._findSpecialChar(this.maskExpression[cursor + 2]) &&
this._findSpecialChar(inputSymbol) === this.maskExpression[cursor + 2] &&
multi) {
cursor += 3;
result += inputSymbol;
}
else if (this.maskExpression[cursor + 1] === '?' &&
this._findSpecialChar(this.maskExpression[cursor + 2]) &&
this._findSpecialChar(inputSymbol) === this.maskExpression[cursor + 2] &&
multi) {
cursor += 3;
result += inputSymbol;
}
else if (this.showMaskTyped &&
this.maskSpecialCharacters.indexOf(inputSymbol) < 0 &&
inputSymbol !== this.placeHolderCharacter) {
stepBack = true;
}
}
}
if (result.length + 1 === maskExpression.length &&
this.maskSpecialCharacters.indexOf(maskExpression[maskExpression.length - 1]) !== -1) {
result += maskExpression[maskExpression.length - 1];
}
var newPosition = position + 1;
while (this._shift.has(newPosition)) {
shift++;
newPosition++;
}
var actualShift = this._shift.has(position) ? shift : 0;
if (stepBack) {
actualShift--;
}
cb(actualShift, backspaceShift);
if (shift < 0) {
this._shift.clear();
}
var res = "" + this.prefix + result + this.suffix;
if (result.length === 0) {
res = "" + this.prefix + result;
}
return res;
};
MaskApplierService.prototype._findSpecialChar = function (inputSymbol) {
return this.maskSpecialCharacters.find(function (val) { return val === inputSymbol; });
};
MaskApplierService.prototype._checkSymbolMask = function (inputSymbol, maskSymbol) {
this.maskAvailablePatterns = this.customPattern ? this.customPattern : this.maskAvailablePatterns;
return (this.maskAvailablePatterns[maskSymbol] &&
this.maskAvailablePatterns[maskSymbol].pattern &&
this.maskAvailablePatterns[maskSymbol].pattern.test(inputSymbol));
};
MaskApplierService.prototype._stripToDecimal = function (str) {
var _this = this;
return str
.split('')
.filter(function (i, idx) {
return i.match('^-?\\d') || i === '.' || i === ',' || (i === '-' && idx === 0 && _this.allowNegativeNumbers);
})
.join('');
};
MaskApplierService.prototype._charToRegExpExpression = function (char) {
if (char) {
var charsToEscape = '[\\^$.|?*+()';
return char === ' ' ? '\\s' : charsToEscape.indexOf(char) >= 0 ? '\\' + char : char;
}
return char;
};
MaskApplierService.ctorParameters = function () { return [
{ type: undefined, decorators: [{ type: Inject, args: [config,] }] }
]; };
MaskApplierService = __decorate([
Injectable(),
__param(0, Inject(config)),
__metadata("design:paramtypes", [Object])
], MaskApplierService);
return MaskApplierService;
}());
var MaskService = /** @class */ (function (_super) {
__extends(MaskService, _super);
function MaskService(document, _config, _elementRef, _renderer) {
var _this = _super.call(this, _config) || this;
_this.document = document;
_this._config = _config;
_this._elementRef = _elementRef;
_this._renderer = _renderer;
_this.maskExpression = '';
_this.isNumberValue = false;
_this.placeHolderCharacter = '_';
_this.maskIsShown = '';
_this.selStart = null;
_this.selEnd = null;
/**
* Whether we are currently in writeValue function, in this case when applying the mask we don't want to trigger onChange function,
* since writeValue should be a one way only process of writing the DOM value based on the Angular model value.
*/
_this.writingValue = false;
_this.onChange = function (_) { };
_this._formElement = _this._elementRef.nativeElement;
return _this;
}
// tslint:disable-next-line:cyclomatic-complexity
MaskService.prototype.applyMask = function (inputValue, maskExpression, position, cb) {
var _this = this;
if (position === void 0) { position = 0; }
if (cb === void 0) { cb = function () { }; }
if (!maskExpression) {
return inputValue;
}
this.maskIsShown = this.showMaskTyped ? this.showMaskInInput() : '';
if (this.maskExpression === 'IP' && this.showMaskTyped) {
this.maskIsShown = this.showMaskInInput(inputValue || '#');
}
if (this.maskExpression === 'CPF_CNPJ' && this.showMaskTyped) {
this.maskIsShown = this.showMaskInInput(inputValue || '#');
}
if (!inputValue && this.showMaskTyped) {
this.formControlResult(this.prefix);
return this.prefix + this.maskIsShown;
}
var getSymbol = !!inputValue && typeof this.selStart === 'number' ? inputValue[this.selStart] : '';
var newInputValue = '';
if (this.hiddenInput !== undefined) {
var actualResult = this.actualValue.split('');
// tslint:disable no-unused-expression
inputValue !== '' && actualResult.length
? typeof this.selStart === 'number' && typeof this.selEnd === 'number'
? inputValue.length > actualResult.length
? actualResult.splice(this.selStart, 0, getSymbol)
: inputValue.length < actualResult.length
? actualResult.length - inputValue.length === 1
? actualResult.splice(this.selStart - 1, 1)
: actualResult.splice(this.selStart, this.selEnd - this.selStart)
: null
: null
: (actualResult = []);
// tslint:enable no-unused-expression
newInputValue = this.actualValue.length ? this.shiftTypedSymbols(actualResult.join('')) : inputValue;
}
newInputValue = Boolean(newInputValue) && newInputValue.length ? newInputValue : inputValue;
var result = _super.prototype.applyMask.call(this, newInputValue, maskExpression, position, cb);
this.actualValue = this.getActualValue(result);
// handle some separator implications:
// a.) adjust decimalMarker default (. -> ,) if thousandSeparator is a dot
if (this.thousandSeparator === '.' && this.decimalMarker === '.') {
this.decimalMarker = ',';
}
// b) remove decimal marker from list of special characters to mask
if (this.maskExpression.startsWith('separator') && this.dropSpecialCharacters === true) {
this.maskSpecialCharacters = this.maskSpecialCharacters.filter(function (item) { return item !== _this.decimalMarker; });
}
this.formControlResult(result);
if (!this.showMaskTyped) {
if (this.hiddenInput) {
return result && result.length ? this.hideInput(result, this.maskExpression) : result;
}
return result;
}
var resLen = result.length;
var prefNmask = this.prefix + this.maskIsShown;
return (result +
(this.maskExpression === 'IP' || this.maskExpression === 'CPF_CNPJ' ? prefNmask : prefNmask.slice(resLen)));
};
MaskService.prototype.applyValueChanges = function (position, cb) {
if (position === void 0) { position = 0; }
if (cb === void 0) { cb = function () { }; }
this._formElement.value = this.applyMask(this._formElement.value, this.maskExpression, position, cb);
if (this._formElement === this.document.activeElement) {
return;
}
this.clearIfNotMatchFn();
};
MaskService.prototype.hideInput = function (inputValue, maskExpression) {
var _this = this;
return inputValue
.split('')
.map(function (curr, index) {
if (_this.maskAvailablePatterns &&
_this.maskAvailablePatterns[maskExpression[index]] &&
_this.maskAvailablePatterns[maskExpression[index]].symbol) {
return _this.maskAvailablePatterns[maskExpression[index]].symbol;
}
return curr;
})
.join('');
};
// this function is not necessary, it checks result against maskExpression
MaskService.prototype.getActualValue = function (res) {
var _this = this;
var compare = res
.split('')
.filter(function (symbol, i) {
return _this._checkSymbolMask(symbol, _this.maskExpression[i]) ||
(_this.maskSpecialCharacters.includes(_this.maskExpression[i]) && symbol === _this.maskExpression[i]);
});
if (compare.join('') === res) {
return compare.join('');
}
return res;
};
MaskService.prototype.shiftTypedSymbols = function (inputValue) {
var _this = this;
var symbolToReplace = '';
var newInputValue = (inputValue &&
inputValue.split('').map(function (currSymbol, index) {
if (_this.maskSpecialCharacters.includes(inputValue[index + 1]) &&
inputValue[index + 1] !== _this.maskExpression[index + 1]) {
symbolToReplace = currSymbol;
return inputValue[index + 1];
}
if (symbolToReplace.length) {
var replaceSymbol = symbolToReplace;
symbolToReplace = '';
return replaceSymbol;
}
return currSymbol;
})) ||
[];
return newInputValue.join('');
};
MaskService.prototype.showMaskInInput = function (inputVal) {
if (this.showMaskTyped && !!this.shownMaskExpression) {
if (this.maskExpression.length !== this.shownMaskExpression.length) {
throw new Error('Mask expression must match mask placeholder length');
}
else {
return this.shownMaskExpression;
}
}
else if (this.showMaskTyped) {
if (inputVal) {
if (this.maskExpression === 'IP') {
return this._checkForIp(inputVal);
}
if (this.maskExpression === 'CPF_CNPJ') {
return this._checkForCpfCnpj(inputVal);
}
}
return this.maskExpression.replace(/\w/g, this.placeHolderCharacter);
}
return '';
};
MaskService.prototype.clearIfNotMatchFn = function () {
if (this.clearIfNotMatch &&
this.prefix.length + this.maskExpression.length + this.suffix.length !==
this._formElement.value.replace(/_/g, '').length) {
this.formElementProperty(['value', '']);
this.applyMask(this._formElement.value, this.maskExpression);
}
};
MaskService.prototype.formElementProperty = function (_a) {
var _b = __read(_a, 2), name = _b[0], value = _b[1];
this._renderer.setProperty(this._formElement, name, value);
};
MaskService.prototype.checkSpecialCharAmount = function (mask) {
var _this = this;
var chars = mask.split('').filter(function (item) { return _this._findSpecialChar(item); });
return chars.length;
};
MaskService.prototype.removeMask = function (inputValue) {
return this._removeMask(this._removeSuffix(this._removePrefix(inputValue)), this.maskSpecialCharacters.concat('_').concat(this.placeHolderCharacter));
};
MaskService.prototype._checkForIp = function (inputVal) {
if (inputVal === '#') {
return this.placeHolderCharacter + "." + this.placeHolderCharacter + "." + this.placeHolderCharacter + "." + this.placeHolderCharacter;
}
var arr = [];
for (var i = 0; i < inputVal.length; i++) {
if (inputVal[i].match('\\d')) {
arr.push(inputVal[i]);
}
}
if (arr.length <= 3) {
return this.placeHolderCharacter + "." + this.placeHolderCharacter + "." + this.placeHolderCharacter;
}
if (arr.length > 3 && arr.length <= 6) {
return this.placeHolderCharacter + "." + this.placeHolderCharacter;
}
if (arr.length > 6 && arr.length <= 9) {
return this.placeHolderCharacter;
}
if (arr.length > 9 && arr.length <= 12) {
return '';
}
return '';
};
MaskService.prototype._checkForCpfCnpj = function (inputVal) {
var cpf = "" + this.placeHolderCharacter + this.placeHolderCharacter + this.placeHolderCharacter +
("." + this.placeHolderCharacter + this.placeHolderCharacter + this.placeHolderCharacter) +
("." + this.placeHolderCharacter + this.placeHolderCharacter + this.placeHolderCharacter) +
("-" + this.placeHolderCharacter + this.placeHolderCharacter);
var cnpj = "" + this.placeHolderCharacter + this.placeHolderCharacter +
("." + this.placeHolderCharacter + this.placeHolderCharacter + this.placeHolderCharacter) +
("." + this.placeHolderCharacter + this.placeHolderCharacter + this.placeHolderCharacter) +
("/" + this.placeHolderCharacter + this.placeHolderCharacter + this.placeHolderCharacter + this.placeHolderCharacter) +
("-" + this.placeHolderCharacter + this.placeHolderCharacter);
if (inputVal === '#') {
return cpf;
}
var arr = [];
for (var i = 0; i < inputVal.length; i++) {
if (inputVal[i].match('\\d')) {
arr.push(inputVal[i]);
}
}
if (arr.length <= 3) {
return cpf.slice(arr.length, cpf.length);
}
if (arr.length > 3 && arr.length <= 6) {
return cpf.slice(arr.length + 1, cpf.length);
}
if (arr.length > 6 && arr.length <= 9) {
return cpf.slice(arr.length + 2, cpf.length);
}
if (arr.length > 9 && arr.length < 11) {
return cpf.slice(arr.length + 3, cpf.length);
}
if (arr.length === 11) {
return '';
}
if (arr.length === 12) {
if (inputVal.length === 17) {
return cnpj.slice(16, cnpj.length);
}
return cnpj.slice(15, cnpj.length);
}
if (arr.length > 12 && arr.length <= 14) {
return cnpj.slice(arr.length + 4, cnpj.length);
}
return '';
};
/**
* Propogates the input value back to the Angular model by triggering the onChange function. It won't do this if writingValue
* is true. If that is true it means we are currently in the writeValue function, which is supposed to only update the actual
* DOM element based on the Angular model value. It should be a one way process, i.e. writeValue should not be modifying the Angular
* model value too. Therefore, we don't trigger onChange in this scenario.
* @param inputValue the current form input value
*/
MaskService.prototype.formControlResult = function (inputValue) {
if (!this.writingValue) {
if (Array.isArray(this.dropSpecialCharacters)) {
this.onChange(this._removeMask(this._removeSuffix(this._removePrefix(inputValue)), this.dropSpecialCharacters));
}
else if (this.dropSpecialCharacters) {
this.onChange(this._checkSymbols(inputValue));
}
else {
this.onChange(this._removeSuffix(this._removePrefix(inputValue)));
}
}
};
MaskService.prototype._removeMask = function (value, specialCharactersForRemove) {
return value ? value.replace(this._regExpForRemove(specialCharactersForRemove), '') : value;
};
MaskService.prototype._removePrefix = function (value) {
if (!this.prefix) {
return value;
}
return value ? value.replace(this.prefix, '') : value;
};
MaskService.prototype._removeSuffix = function (value) {
if (!this.suffix) {
return value;
}
return value ? value.replace(this.suffix, '') : value;
};
MaskService.prototype._retrieveSeparatorValue = function (result) {
return this._removeMask(this._removeSuffix(this._removePrefix(result)), this.maskSpecialCharacters);
};
MaskService.prototype._regExpForRemove = function (specialCharactersForRemove) {
return new RegExp(specialCharactersForRemove.map(function (item) { return "\\" + item; }).join('|'), 'gi');
};
MaskService.prototype._checkSymbols = function (result) {
if (result === '') {
return result;
}
var separatorPrecision = this._retrieveSeparatorPrecision(this.maskExpression);
var separatorValue = this._retrieveSeparatorValue(result);
if (this.decimalMarker !== '.') {
separatorValue = separatorValue.replace(this.decimalMarker, '.');
}
if (this.isNumberValue) {
if (separatorPrecision) {
if (result === this.decimalMarker) {
return null;
}
return this._checkPrecision(this.maskExpression, separatorValue);
}
else {
return Number(separatorValue);
}
}
else {
return separatorValue;
}
};
// TODO should think about helpers or separting decimal precision to own property
MaskService.prototype._retrieveSeparatorPrecision = function (maskExpretion) {
var matcher = maskExpretion.match(new RegExp("^separator\\.([^d]*)"));
return matcher ? Number(matcher[1]) : null;
};
MaskService.prototype._checkPrecision = function (separatorExpression, separatorValue) {
if (separatorExpression.indexOf('2') > 0) {
return Number(separatorValue).toFixed(2);
}
return Number(separatorValue);
};
MaskService.ctorParameters = function () { return [
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
{ type: undefined, decorators: [{ type: Inject, args: [config,] }] },
{ type: ElementRef },
{ type: Renderer2 }
]; };
MaskService = __decorate([
Injectable(),
__param(0, Inject(DOCUMENT)),
__param(1, Inject(config)),
__metadata("design:paramtypes", [Object, Object, ElementRef,
Renderer2])
], MaskService);
return MaskService;
}(MaskApplierService));
// tslint:disable deprecation
var MaskDirective = /** @class */ (function () {
function MaskDirective(document, _maskService, _config, _elementRef) {
this.document = document;
this._maskService = _maskService;
this._config = _config;
this._elementRef = _elementRef;
this.maskExpression = '';
this.specialCharacters = [];
this.patterns = {};
this.prefix = '';
this.suffix = '';
this.thousandSeparator = ' ';
this.decimalMarker = '.';
this.dropSpecialCharacters = null;
this.hiddenInput = null;
this.showMaskTyped = null;
this.placeHolderCharacter = null;
this.shownMaskExpression = null;
this.showTemplate = null;
this.clearIfNotMatch = null;
this.validation = null;
this.separatorLimit = null;
this.allowNegativeNumbers = null;
this._formControl = new FormControl();
this._maskValue = '';
this._position = null;
this._maskExpressionArray = [];
this.onChange = function (_) { };
this.onTouch = function () { };
this._formElement = this._elementRef.nativeElement;
}
MaskDirective_1 = MaskDirective;
MaskDirective.prototype.ngOnChanges = function (changes) {
var maskExpression = changes.maskExpression, specialCharacters = changes.specialCharacters, patterns = changes.patterns, prefix = changes.prefix, suffix = changes.suffix, thousandSeparator = changes.thousandSeparator, decimalMarker = changes.decimalMarker, dropSpecialCharacters = changes.dropSpecialCharacters, hiddenInput = changes.hiddenInput, showMaskTyped = changes.showMaskTyped, placeHolderCharacter = changes.placeHolderCharacter, shownMaskExpression = changes.shownMaskExpression, showTemplate = changes.showTemplate, clearIfNotMatch = changes.clearIfNotMatch, validation = changes.validation, separatorLimit = changes.separatorLimit, allowNegativeNumbers = changes.allowNegativeNumbers;
if (maskExpression) {
this._maskValue = maskExpression.currentValue || '';
if (maskExpression.currentValue && maskExpression.currentValue.split('||').length > 1) {
this._maskExpressionArray = maskExpression.currentValue.split('||').sort(function (a, b) {
return a.length - b.length;
});
this._setMask();
}
}
if (specialCharacters) {
if (!specialCharacters.currentValue || !Array.isArray(specialCharacters.currentValue)) {
return;
}
else {
this._maskService.maskSpecialCharacters = specialCharacters.currentValue || [];
}
}
// Only overwrite the mask available patterns if a pattern has actually been passed in
if (patterns && patterns.currentValue) {
this._maskService.maskAvailablePatterns = patterns.currentValue;
}
if (prefix) {
this._maskService.prefix = prefix.currentValue;
}
if (suffix) {
this._maskService.suffix = suffix.currentValue;
}
if (thousandSeparator) {
this._maskService.thousandSeparator = thousandSeparator.currentValue;
}
if (decimalMarker) {
this._maskService.decimalMarker = decimalMarker.currentValue;
}
if (dropSpecialCharacters) {
this._maskService.dropSpecialCharacters = dropSpecialCharacters.currentValue;
}
if (hiddenInput) {
this._maskService.hiddenInput = hiddenInput.currentValue;
}
if (showMaskTyped) {
this._maskService.showMaskTyped = showMaskTyped.currentValue;
}
if (placeHolderCharacter) {
this._maskService.placeHolderCharacter = placeHolderCharacter.currentValue;
}
if (shownMaskExpression) {
this._maskService.shownMaskExpression = shownMaskExpression.currentValue;
}
if (showTemplate) {
this._maskService.showTemplate = showTemplate.currentValue;
}
if (clearIfNotMatch) {
this._maskService.clearIfNotMatch = clearIfNotMatch.currentValue;
}
if (validation) {
this._maskService.validation = validation.currentValue;
}
if (separatorLimit) {
this._maskService.separatorLimit = separatorLimit.currentValue;
}
if (allowNegativeNumbers) {
this._maskService.allowNegativeNumbers = allowNegativeNumbers.currentValue;
if (this._maskService.allowNegativeNumbers) {
this._maskService.maskSpecialCharacters = this._maskService.maskSpecialCharacters.filter(function (c) { return c !== '-'; });
}
}
this._applyMask();
};
// tslint:disable-next-line: cyclomatic-complexity
MaskDirective.prototype.validate = function (_a) {
var value = _a.value;
if (!this._maskService.validation || !this._maskValue) {
return null;
}
if (this._maskService.ipError) {
return this._createValidationError(value);
}
if (this._maskService.cpfCnpjError) {
return this._createValidationError(value);
}
if (this._maskValue.startsWith('separator')) {
return null;
}
if (withoutValidation.includes(this._maskValue)) {
return null;
}
if (this._maskService.clearIfNotMatch) {
return null;
}
if (timeMasks.includes(this._maskValue)) {
return this._validateTime(value);
}
if (value && value.toString().length >= 1) {
var counterOfOpt = 0;
var _loop_1 = function (key) {
if (this_1._maskService.maskAvailablePatterns[key].optional &&
this_1._maskService.maskAvailablePatterns[key].optional === true) {
if (this_1._maskValue.indexOf(key) !== this_1._maskValue.lastIndexOf(key)) {
var opt = this_1._maskValue
.split('')
.filter(function (i) { return i === key; })
.join('');
counterOfOpt += opt.length;
}
else if (this_1._maskValue.indexOf(key) !== -1) {
counterOfOpt++;
}
if (this_1._maskValue.indexOf(key) !== -1 && value.toString().length >= this_1._maskValue.indexOf(key)) {
return { value: null };
}
if (counterOfOpt === this_1._maskValue.length) {
return { value: null };
}
}
};
var this_1 = this;
for (var key in this._maskService.maskAvailablePatterns) {
var state_1 = _loop_1(key);
if (typeof state_1 === "object")
return state_1.value;
}
if (this._maskValue.indexOf('{') === 1 &&
value.toString().length === this._maskValue.length + Number(this._maskValue.split('{')[1].split('}')[0]) - 4) {
return null;
}
if (this._maskValue.indexOf('*') === 1 || this._maskValue.indexOf('?') === 1) {
return null;
}
else if ((this._maskValue.indexOf('*') > 1 && value.toString().length < this._maskValue.indexOf('*')) ||
(this._maskValue.indexOf('?') > 1 && value.toString().length < this._maskValue.indexOf('?')) ||
this._maskValue.indexOf('{') === 1) {
return this._createValidationError(value);
}
if (this._maskValue.indexOf('*') === -1 || this._maskValue.indexOf('?') === -1) {
var length_1 = this._maskService.dropSpecialCharacters
? this._maskValue.length - this._maskService.checkSpecialCharAmount(this._maskValue) - counterOfOpt
: this._maskValue.length - counterOfOpt;
if (value.toString().length < length_1) {
return this._createValidationError(value);
}
}
}
return null;
};
MaskDirective.prototype.onInput = function (e) {
var el = e.target;
this._inputValue = el.value;
this._setMask();
if (!this._maskValue) {
this.onChange(el.value);
return;
}
var position = el.selectionStart === 1
? el.selectionStart + this._maskService.prefix.length
: el.selectionStart;
var caretShift = 0;
var backspaceShift = false;
this._maskService.applyValueChanges(position, function (shift, _backspaceShift) {
caretShift = shift;
backspaceShift = _backspaceShift;
});
// only set the selection if the element is active
if (this.document.activeElement !== el) {
return;
}
this._position = this._position === 1 && this._inputValue.length === 1 ? null : this._position;
var positionToApply = this._position
? this._inputValue.length + position + caretShift
: position + (this._code === 'Backspace' && !backspaceShift ? 0 : caretShift);
if (positionToApply > this._getActualInputLength()) {
positionToApply = this._getActualInputLength();
}
el.setSelectionRange(positionToApply, positionToApply);
if ((this.maskExpression.includes('H') || this.maskExpression.includes('M')) && caretShift === 0) {
el.setSelectionRange(el.selectionStart + 1, el.selectionStart + 1);
}
this._position = null;
};
MaskDirective.prototype.onBlur = function () {
if (this._maskValue) {
this._maskService.clearIfNotMatchFn();
}
this.onTouch();
};
MaskDirective.prototype.onFocus = function (e) {
if (!this._maskValue) {
return;
}
var el = e.target;
var posStart = 0;
var posEnd = 0;
if (el !== null &&
el.selectionStart !== null &&
el.selectionStart === el.selectionEnd &&
el.selectionStart > this._maskService.prefix.length &&
// tslint:disable-next-line
e.keyCode !== 38)
if (this._maskService.showMaskTyped) {
// We are showing the mask in the input
this._maskService.maskIsShown = this._maskService.showMaskInInput();
if (el.setSelectionRange && this._maskService.prefix + this._maskService.maskIsShown === el.value) {
// the input ONLY contains the mask, so position the cursor at the start
el.focus();
el.setSelectionRange(posStart, posEnd);
}
else {
// the input contains some characters already
if (el.selectionStart > this._maskService.actualValue.length) {
// if the user clicked beyond our value's length, position the cursor at the end of our value
el.setSelectionRange(this._maskService.actualValue.length, this._maskService.actualValue.length);
}
}
}
var nextValue = !el.value || el.value === this._maskService.prefix
? this._maskService.prefix + this._maskService.maskIsShown
: el.value;
/** Fix of cursor position jumping to end in most browsers no matter where cursor is inserted onFocus */
if (el.value !== nextValue) {
el.value = nextValue;
}
/** fix of cursor position with prefix when mouse click occur */
if ((el.selectionStart || el.selectionEnd) <= this._maskService.prefix.length) {