UNPKG

ngx-mask-fork

Version:
1,076 lines (1,071 loc) 66.8 kB
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) {