UNPKG

angular2-text-mask

Version:

Angular 2 directive for input text masking

1 lines 92.5 kB
{"errors":[],"warnings":["angular2TextMask.js from UglifyJs\nSide effects in initialization of unused variable placeholderChar [./core/src/constants.js:1,13]"],"version":"1.13.1","hash":"c24f0f8d77ed3dd9d44e","publicPath":"","assetsByChunkName":{"main":"angular2TextMask.js"},"assets":[{"name":"angular2/src/angular2TextMask.d.ts","size":600,"chunks":[],"chunkNames":[]},{"name":"angular2TextMask.js","size":8204,"chunks":[0],"chunkNames":["main"],"emitted":true},{"name":"stats.json","size":0,"chunks":[],"chunkNames":[]}],"chunks":[{"id":0,"rendered":true,"initial":true,"entry":true,"extraAsync":false,"size":36263,"names":["main"],"files":["angular2TextMask.js"],"hash":"2d1c73f153d4af030e09","parents":[],"modules":[{"id":0,"identifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/awesome-typescript-loader/dist/entry.js?{\"tsconfig\":\"./angular2/tsconfig.json\",\"declaration\":true}!/Users/mk/Code/github/msafi/text-mask/angular2/src/angular2TextMask.ts","name":"./angular2/src/angular2TextMask.ts","index":0,"index2":7,"size":2632,"cacheable":true,"built":true,"optional":false,"prefetched":false,"chunks":[0],"assets":["angular2/src/angular2TextMask.d.ts"],"issuer":null,"failed":false,"errors":0,"warnings":0,"reasons":[],"source":"\"use strict\";\r\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n};\r\nvar __metadata = (this && this.__metadata) || function (k, v) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\r\n};\r\nvar core_1 = require('@angular/core');\r\nvar forms_1 = require('@angular/forms');\r\nvar createTextMaskInputElement_1 = require('../../core/src/createTextMaskInputElement');\r\nvar MaskedInputDirective = (function () {\r\n function MaskedInputDirective(inputElement, ngControl) {\r\n this.ngControl = ngControl;\r\n this.textMaskConfig = {\r\n mask: '',\r\n guide: true,\r\n placeholderChar: '_',\r\n pipe: undefined,\r\n keepCharPositions: false,\r\n onReject: undefined,\r\n onAccept: undefined\r\n };\r\n this.inputElement = inputElement.nativeElement;\r\n }\r\n MaskedInputDirective.prototype.ngOnInit = function () {\r\n var _this = this;\r\n this.textMaskInputElement = createTextMaskInputElement_1.default(Object.assign({ inputElement: this.inputElement, }, this.textMaskConfig));\r\n // This ensures that initial model value gets masked\r\n setTimeout(function () { return _this.onInput(); });\r\n };\r\n MaskedInputDirective.prototype.onInput = function () {\r\n this.textMaskInputElement.update();\r\n this.ngControl.viewToModelUpdate(this.inputElement.value);\r\n };\r\n __decorate([\r\n core_1.Input('textMask'), \r\n __metadata('design:type', Object)\r\n ], MaskedInputDirective.prototype, \"textMaskConfig\", void 0);\r\n MaskedInputDirective = __decorate([\r\n core_1.Directive({\r\n host: {\r\n '(input)': 'onInput()'\r\n },\r\n selector: 'input[textMask]'\r\n }), \r\n __metadata('design:paramtypes', [core_1.ElementRef, forms_1.NgControl])\r\n ], MaskedInputDirective);\r\n return MaskedInputDirective;\r\n}());\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.default = MaskedInputDirective;\r\nexports.Directive = MaskedInputDirective;\r\n"},{"id":1,"identifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/constants.js","name":"./core/src/constants.js","index":7,"index2":3,"size":132,"cacheable":true,"built":true,"optional":false,"prefetched":false,"chunks":[0],"assets":[],"issuer":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/createTextMaskInputElement.js","failed":false,"errors":0,"warnings":0,"reasons":[{"moduleId":2,"moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/utilities.js","module":"./core/src/utilities.js","moduleName":"./core/src/utilities.js","type":"cjs require","userRequest":"./constants.js","loc":"11:17-42"},{"moduleId":4,"moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/conformToMask.js","module":"./core/src/conformToMask.js","moduleName":"./core/src/conformToMask.js","type":"cjs require","userRequest":"./constants.js","loc":"10:17-42"},{"moduleId":5,"moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/createTextMaskInputElement.js","module":"./core/src/createTextMaskInputElement.js","moduleName":"./core/src/createTextMaskInputElement.js","type":"cjs require","userRequest":"./constants.js","loc":"23:17-42"}],"source":"'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nvar placeholderChar = exports.placeholderChar = '_';"},{"id":2,"identifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/utilities.js","name":"./core/src/utilities.js","index":6,"index2":4,"size":1627,"cacheable":true,"built":true,"optional":false,"prefetched":false,"chunks":[0],"assets":[],"issuer":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/createTextMaskInputElement.js","failed":false,"errors":0,"warnings":0,"reasons":[{"moduleId":4,"moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/conformToMask.js","module":"./core/src/conformToMask.js","moduleName":"./core/src/conformToMask.js","type":"cjs require","userRequest":"./utilities.js","loc":"8:17-42"},{"moduleId":5,"moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/createTextMaskInputElement.js","module":"./core/src/createTextMaskInputElement.js","moduleName":"./core/src/createTextMaskInputElement.js","type":"cjs require","userRequest":"./utilities.js","loc":"21:17-42"}],"source":"'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.convertMaskToPlaceholder = convertMaskToPlaceholder;\nexports.isString = isString;\nexports.isNumber = isNumber;\nexports.processCaretTraps = processCaretTraps;\n\nvar _constants = require('./constants.js');\n\nvar emptyArray = [];\n\nfunction convertMaskToPlaceholder() {\n var mask = arguments.length <= 0 || arguments[0] === undefined ? emptyArray : arguments[0];\n var placeholderChar = arguments.length <= 1 || arguments[1] === undefined ? _constants.placeholderChar : arguments[1];\n\n if (mask.indexOf(placeholderChar) !== -1) {\n throw new Error('Placeholder character must not be used as part of the mask. Please specify a character ' + 'that is not present in your mask as your placeholder character.\\n\\n' + ('The placeholder character that was received is: ' + JSON.stringify(placeholderChar) + '\\n\\n') + ('The mask that was received is: ' + JSON.stringify(mask)));\n }\n\n return mask.map(function (char) {\n return char instanceof RegExp ? placeholderChar : char;\n }).join('');\n}\n\nfunction isString(value) {\n return typeof value === 'string' || value instanceof String;\n}\n\nfunction isNumber(value) {\n return value && value.length === undefined && !isNaN(value);\n}\n\nvar strCaretTrap = '[]';\nfunction processCaretTraps(mask) {\n var indexes = [];\n\n var indexOfCaretTrap = void 0;\n while (indexOfCaretTrap = mask.indexOf(strCaretTrap), indexOfCaretTrap !== -1) {\n // eslint-disable-line\n indexes.push(indexOfCaretTrap);\n\n mask.splice(indexOfCaretTrap, 1);\n }\n\n return { maskWithoutCaretTraps: mask, indexes: indexes };\n}"},{"id":3,"identifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/adjustCaretPosition.js","name":"./core/src/adjustCaretPosition.js","index":4,"index2":2,"size":8123,"cacheable":true,"built":true,"optional":false,"prefetched":false,"chunks":[0],"assets":[],"issuer":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/createTextMaskInputElement.js","failed":false,"errors":0,"warnings":0,"reasons":[{"moduleId":5,"moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/createTextMaskInputElement.js","module":"./core/src/createTextMaskInputElement.js","moduleName":"./core/src/createTextMaskInputElement.js","type":"cjs require","userRequest":"./adjustCaretPosition.js","loc":"13:27-62"}],"source":"'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = adjustCaretPosition;\nvar defaultArray = [];\nvar emptyString = '';\n\nfunction adjustCaretPosition(_ref) {\n var _ref$previousConforme = _ref.previousConformedValue;\n var previousConformedValue = _ref$previousConforme === undefined ? emptyString : _ref$previousConforme;\n var _ref$currentCaretPosi = _ref.currentCaretPosition;\n var currentCaretPosition = _ref$currentCaretPosi === undefined ? 0 : _ref$currentCaretPosi;\n var conformedValue = _ref.conformedValue;\n var rawValue = _ref.rawValue;\n var placeholderChar = _ref.placeholderChar;\n var placeholder = _ref.placeholder;\n var _ref$indexesOfPipedCh = _ref.indexesOfPipedChars;\n var indexesOfPipedChars = _ref$indexesOfPipedCh === undefined ? defaultArray : _ref$indexesOfPipedCh;\n var _ref$caretTrapIndexes = _ref.caretTrapIndexes;\n var caretTrapIndexes = _ref$caretTrapIndexes === undefined ? defaultArray : _ref$caretTrapIndexes;\n\n if (currentCaretPosition === 0) {\n return 0;\n }\n\n // Store lengths for faster performance?\n var rawValueLength = rawValue.length;\n var previousConformedValueLength = previousConformedValue.length;\n var placeholderLength = placeholder.length;\n var conformedValueLength = conformedValue.length;\n\n // This tells us how long the edit is. If user modified input from `(2__)` to `(243__)`,\n // we know the user in this instance pasted two characters\n var editLength = rawValueLength - previousConformedValueLength;\n\n // If the edit length is positive, that means the user is adding characters, not deleting.\n var isAddition = editLength > 0;\n\n // This is the first character the user entered that needs to be conformed to mask\n var isFirstChar = rawValueLength === 1;\n\n // A partial multi-character edit happens when the user makes a partial selection in their\n // input and edits that selection. That is going from `(123) 432-4348` to `() 432-4348` by\n // selecting the first 3 digits and pressing backspace.\n //\n // Such cases can also happen when the user presses the backspace while holding down the ALT\n // key.\n var isPartialMultiCharEdit = editLength > 1 && !isAddition && !isFirstChar;\n\n // This algorithm doesn't support all cases of multi-character edits, so we just return\n // the current caret position.\n //\n // This works fine for most cases.\n if (isPartialMultiCharEdit) {\n return currentCaretPosition;\n }\n\n // For a mask like (111), if the `previousConformedValue` is (1__) and user attempts to enter\n // `f` so the `rawValue` becomes (1f__), the new `conformedValue` would be (1__), which is the\n // same as the original `previousConformedValue`. We handle this case differently for caret\n // positioning.\n var possiblyHasRejectedChar = isAddition && (previousConformedValue === conformedValue || conformedValue === placeholder);\n\n var startingSearchIndex = 0;\n\n if (possiblyHasRejectedChar) {\n startingSearchIndex = currentCaretPosition - editLength;\n } else {\n (function () {\n // At this point in the algorithm, we want to know where the caret is right before the raw input\n // has been conformed, and then see if we can find that same spot in the conformed input.\n //\n // We do that by seeing what character lies immediately before the caret, and then look for that\n // same character in the conformed input and place the caret there.\n\n // First, we need to normalize the inputs so that letter capitalization between raw input and\n // conformed input wouldn't matter.\n var normalizedConformedValue = conformedValue.toLowerCase();\n var normalizedRawValue = rawValue.toLowerCase();\n\n // Then we take all characters that come before where the caret currently is.\n var leftHalfChars = normalizedRawValue.substr(0, currentCaretPosition).split(emptyString);\n\n // Now we find all the characters in the left half that exist in the conformed input\n var intersection = leftHalfChars.filter(function (char) {\n return normalizedConformedValue.indexOf(char) !== -1;\n });\n\n // The last character in the intersection is the character we want to look for in the conformed\n // value and the one we want to adjust the caret close to\n var targetChar = intersection[intersection.length - 1];\n\n // If the `conformedValue` got piped, we need to know which characters were piped in so that when we look for\n // our `targetChar`, we don't select a piped char by mistake\n var pipedChars = indexesOfPipedChars.map(function (index) {\n return normalizedConformedValue[index];\n });\n\n // We need to know how many times the `targetChar` occurs in the piped characters.\n var countTargetCharInPipedChars = pipedChars.filter(function (char) {\n return char === targetChar;\n }).length;\n\n // And we need to know how many times it occurs in the intersection\n var countTargetCharInIntersection = intersection.filter(function (char) {\n return char === targetChar;\n }).length;\n\n // The number of times we need to see occurrences of the `targetChar` before we know it is the one we're looking\n // for is:\n var requiredNumberOfMatches = countTargetCharInIntersection + countTargetCharInPipedChars;\n\n // Now we start looking for the location of the `targetChar`.\n // We keep looping forward and store the index in every iteration. Once we have encountered\n // enough occurrences of the target character, we break out of the loop\n var numberOfEncounteredMatches = 0;\n for (var i = 0; i < conformedValueLength; i++) {\n var conformedValueChar = normalizedConformedValue[i];\n\n startingSearchIndex = i + 1;\n\n if (conformedValueChar === targetChar) {\n numberOfEncounteredMatches++;\n }\n\n if (numberOfEncounteredMatches >= requiredNumberOfMatches) {\n break;\n }\n }\n })();\n }\n\n // At this point, if we simply return `startingSearchIndex` as the adjusted caret position,\n // most cases would be handled. However, we want to fast forward or rewind the caret to the\n // closest placeholder character if it happens to be in a non-editable spot. That's what the next\n // logic is for.\n\n // In case of addition, we fast forward.\n if (isAddition) {\n // We want to remember the last placeholder character encountered so that if the mask\n // contains more characters after the last placeholder character, we don't forward the caret\n // that far to the right. Instead, we stop it at the last encountered placeholder character.\n var lastPlaceholderChar = startingSearchIndex;\n\n for (var i = startingSearchIndex; i <= placeholderLength; i++) {\n if (placeholder[i] === placeholderChar) {\n lastPlaceholderChar = i;\n }\n\n if (\n // If we're adding, we can position the caret at the next placeholder character.\n placeholder[i] === placeholderChar ||\n\n // If a caret trap was set by a mask function, we need to stop at the trap.\n caretTrapIndexes.indexOf(i) !== -1 ||\n\n // This is the end of the placeholder. We cannot move any further. Let's put the caret there.\n i === placeholderLength) {\n return lastPlaceholderChar;\n }\n }\n } else {\n // In case of deletion, we rewind.\n for (var _i = startingSearchIndex; _i >= 0; _i--) {\n // If we're deleting, we stop the caret right before the placeholder character.\n // For example, for mask `(111) 11`, current conformed input `(456) 86`. If user\n // modifies input to `(456 86`. That is, they deleted the `)`, we place the caret\n // right after the first `6`\n if (\n // If we're deleting, we can position the caret right before the placeholder character\n placeholder[_i - 1] === placeholderChar ||\n\n // If a caret trap was set by a mask function, we need to stop at the trap.\n caretTrapIndexes.indexOf(_i) !== -1 ||\n\n // This is the beginning of the placeholder. We cannot move any further.\n // Let's put the caret there.\n _i === 0) {\n return _i;\n }\n }\n }\n}"},{"id":4,"identifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/conformToMask.js","name":"./core/src/conformToMask.js","index":5,"index2":5,"size":12075,"cacheable":true,"built":true,"optional":false,"prefetched":false,"chunks":[0],"assets":[],"issuer":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/createTextMaskInputElement.js","failed":false,"errors":0,"warnings":0,"reasons":[{"moduleId":5,"moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/createTextMaskInputElement.js","module":"./core/src/createTextMaskInputElement.js","moduleName":"./core/src/createTextMaskInputElement.js","type":"cjs require","userRequest":"./conformToMask.js","loc":"17:22-51"}],"source":"'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = conformToMask;\n\nvar _utilities = require('./utilities.js');\n\nvar _constants = require('./constants.js');\n\nvar emptyString = '';\n\nfunction conformToMask() {\n var rawValue = arguments.length <= 0 || arguments[0] === undefined ? emptyString : arguments[0];\n var mask = arguments.length <= 1 || arguments[1] === undefined ? emptyString : arguments[1];\n var config = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];\n\n // These configurations tell us how to conform the mask\n var _config$guide = config.guide;\n var guide = _config$guide === undefined ? true : _config$guide;\n var _config$previousConfo = config.previousConformedValue;\n var previousConformedValue = _config$previousConfo === undefined ? emptyString : _config$previousConfo;\n var _config$placeholderCh = config.placeholderChar;\n var placeholderChar = _config$placeholderCh === undefined ? _constants.placeholderChar : _config$placeholderCh;\n var _config$placeholder = config.placeholder;\n var placeholder = _config$placeholder === undefined ? (0, _utilities.convertMaskToPlaceholder)(mask, placeholderChar) : _config$placeholder;\n var currentCaretPosition = config.currentCaretPosition;\n var keepCharPositions = config.keepCharPositions;\n\n // The configs below indicate that the user wants the algorithm to work in *no guide* mode\n\n var suppressGuide = guide === false && previousConformedValue !== undefined;\n\n // Calculate lengths once for performance\n var rawValueLength = rawValue.length;\n var previousConformedValueLength = previousConformedValue.length;\n var placeholderLength = placeholder.length;\n var maskLength = mask.length;\n\n // This tells us the number of edited characters and the direction in which they were edited (+/-)\n var editDistance = rawValueLength - previousConformedValueLength;\n\n // In *no guide* mode, we need to know if the user is trying to add a character or not\n var isAddition = editDistance > 0;\n\n // Tells us the index of the first change. For (438) 394-4938 to (38) 394-4938, that would be 1\n var indexOfFirstChange = currentCaretPosition + (isAddition ? -editDistance : 0);\n\n // We're also gonna need the index of last change, which we can derive as follows...\n var indexOfLastChange = indexOfFirstChange + Math.abs(editDistance);\n\n // If `conformToMask` is configured to keep character positions, that is, for mask 111, previous value\n // _2_ and raw value 3_2_, the new conformed value should be 32_, not 3_2 (default behavior). That's in the case of\n // addition. And in the case of deletion, previous value _23, raw value _3, the new conformed string should be\n // __3, not _3_ (default behavior)\n //\n // The next block of logic handles keeping character positions for the case of deletion. (Keeping\n // character positions for the case of addition is further down since it is handled differently.)\n // To do this, we want to compensate for all characters that were deleted\n if (keepCharPositions === true && !isAddition) {\n // We will be storing the new placeholder characters in this variable.\n var compensatingPlaceholderChars = emptyString;\n\n // For every character that was deleted from a placeholder position, we add a placeholder char\n for (var i = indexOfFirstChange; i < indexOfLastChange; i++) {\n if (placeholder[i] === placeholderChar) {\n compensatingPlaceholderChars += placeholderChar;\n }\n }\n\n // Now we trick our algorithm by modifying the raw value to make it contain additional placeholder characters\n // That way when the we start laying the characters again on the mask, it will keep the non-deleted characters\n // in their positions.\n rawValue = rawValue.slice(0, indexOfFirstChange) + compensatingPlaceholderChars + rawValue.slice(indexOfFirstChange, rawValueLength);\n }\n\n // Convert `rawValue` string to an array, and mark characters based on whether they are newly added or have\n // existed in the previous conformed value. Identifying new and old characters is needed for `conformToMask`\n // to work if it is configured to keep character positions.\n var rawValueArr = rawValue.split(emptyString).map(function (char, i) {\n return { char: char, isNew: i >= indexOfFirstChange && i < indexOfLastChange };\n });\n\n // The loop below removes masking characters from user input. For example, for mask\n // `00 (111)`, the placeholder would be `00 (___)`. If user input is `00 (234)`, the loop below\n // would remove all characters but `234` from the `rawValueArr`. The rest of the algorithm\n // then would lay `234` on top of the available placeholder positions in the mask.\n for (var _i = rawValueLength - 1; _i >= 0; _i--) {\n var char = rawValueArr[_i].char;\n\n\n if (char !== placeholderChar) {\n var shouldOffset = _i > indexOfFirstChange && previousConformedValueLength === maskLength;\n\n if (char === placeholder[shouldOffset ? _i - editDistance : _i]) {\n rawValueArr.splice(_i, 1);\n }\n }\n }\n\n // This is the variable that we will be filling with characters as we figure them out\n // in the algorithm below\n var conformedValue = emptyString;\n var someCharsRejected = false;\n\n // Ok, so first we loop through the placeholder looking for placeholder characters to fill up.\n placeholderLoop: for (var _i2 = 0; _i2 < placeholderLength; _i2++) {\n var charInPlaceholder = placeholder[_i2];\n\n // We see one. Let's find out what we can put in it.\n if (charInPlaceholder === placeholderChar) {\n // But before that, do we actually have any user characters that need a place?\n if (rawValueArr.length > 0) {\n // We will keep chipping away at user input until either we run out of characters\n // or we find at least one character that we can map.\n while (rawValueArr.length > 0) {\n // Let's retrieve the first user character in the queue of characters we have left\n var _rawValueArr$shift = rawValueArr.shift();\n\n var rawValueChar = _rawValueArr$shift.char;\n var isNew = _rawValueArr$shift.isNew;\n\n // If the character we got from the user input is a placeholder character (which happens\n // regularly because user input could be something like (540) 90_-____, which includes\n // a bunch of `_` which are placeholder characters) and we are not in *no guide* mode,\n // then we map this placeholder character to the current spot in the placeholder\n\n if (rawValueChar === placeholderChar && suppressGuide !== true) {\n conformedValue += placeholderChar;\n\n // And we go to find the next placeholder character that needs filling\n continue placeholderLoop;\n\n // Else if, the character we got from the user input is not a placeholder, let's see\n // if the current position in the mask can accept it.\n } else if (mask[_i2].test(rawValueChar)) {\n // we map the character differently based on whether we are keeping character positions or not.\n // If any of the conditions below are met, we simply map the raw value character to the\n // placeholder position.\n if (keepCharPositions !== true || isNew === false || previousConformedValue === emptyString || guide === false || !isAddition) {\n conformedValue += rawValueChar;\n } else {\n // We enter this block of code if we are trying to keep character positions and none of the conditions\n // above is met. In this case, we need to see if there's an available spot for the raw value character\n // to be mapped to. If we couldn't find a spot, we will discard the character.\n //\n // For example, for mask `1111`, previous conformed value `_2__`, raw value `942_2__`. We can map the\n // `9`, to the first available placeholder position, but then, there are no more spots available for the\n // `4` and `2`. So, we discard them and end up with a conformed value of `92__`.\n var rawValueArrLength = rawValueArr.length;\n var indexOfNextAvailablePlaceholderChar = null;\n\n // Let's loop through the remaining raw value characters. We are looking for either a suitable spot, ie,\n // a placeholder character or a non-suitable spot, ie, a non-placeholder character that is not new.\n // If we see a suitable spot first, we store its position and exit the loop. If we see a non-suitable\n // spot first, we exit the loop and our `indexOfNextAvailablePlaceholderChar` will stay as `null`.\n for (var _i3 = 0; _i3 < rawValueArrLength; _i3++) {\n var charData = rawValueArr[_i3];\n\n if (charData.char !== placeholderChar && charData.isNew === false) {\n break;\n }\n\n if (charData.char === placeholderChar) {\n indexOfNextAvailablePlaceholderChar = _i3;\n break;\n }\n }\n\n // If `indexOfNextAvailablePlaceholderChar` is not `null`, that means the character is not blocked.\n // We can map it. And to keep the character positions, we remove the placeholder character\n // from the remaining characters\n if (indexOfNextAvailablePlaceholderChar !== null) {\n conformedValue += rawValueChar;\n rawValueArr.splice(indexOfNextAvailablePlaceholderChar, 1);\n\n // If `indexOfNextAvailablePlaceholderChar` is `null`, that means the character is blocked. We have to\n // discard it.\n } else {\n _i2--;\n }\n }\n\n // Since we've mapped this placeholder position. We move on to the next one.\n continue placeholderLoop;\n } else {\n someCharsRejected = true;\n }\n }\n }\n\n // We reach this point when we've mapped all the user input characters to placeholder\n // positions in the mask. In *guide* mode, we append the left over characters in the\n // placeholder to the `conformedString`, but in *no guide* mode, we don't wanna do that.\n //\n // That is, for mask `(111)` and user input `2`, we want to return `(2`, not `(2__)`.\n if (suppressGuide === false) {\n conformedValue += placeholder.substr(_i2, placeholderLength);\n }\n\n // And we break\n break;\n\n // Else, the charInPlaceholder is not a placeholderChar. That is, we cannot fill it\n // with user input. So we just map it to the final output\n } else {\n conformedValue += charInPlaceholder;\n }\n }\n\n // The following logic is needed to deal with the case of deletion in *no guide* mode.\n //\n // Consider the silly mask `(111) /// 1`. What if user tries to delete the last placeholder\n // position? Something like `(589) /// `. We want to conform that to `(589`. Not `(589) /// `.\n // That's why the logic below finds the last filled placeholder character, and removes everything\n // from that point on.\n if (suppressGuide && isAddition === false) {\n var indexOfLastFilledPlaceholderChar = null;\n\n // Find the last filled placeholder position and substring from there\n for (var _i4 = 0; _i4 < conformedValue.length; _i4++) {\n if (placeholder[_i4] === placeholderChar) {\n indexOfLastFilledPlaceholderChar = _i4;\n }\n }\n\n if (indexOfLastFilledPlaceholderChar !== null) {\n // We substring from the beginning until the position after the last filled placeholder char.\n conformedValue = conformedValue.substr(0, indexOfLastFilledPlaceholderChar + 1);\n } else {\n // If we couldn't find `indexOfLastFilledPlaceholderChar` that means the user deleted\n // the first character in the mask. So we return an empty string.\n conformedValue = emptyString;\n }\n }\n\n return { conformedValue: conformedValue, meta: { someCharsRejected: someCharsRejected } };\n}"},{"id":5,"identifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/babel-loader/index.js!/Users/mk/Code/github/msafi/text-mask/core/src/createTextMaskInputElement.js","name":"./core/src/createTextMaskInputElement.js","index":3,"index2":6,"size":11590,"cacheable":true,"built":true,"optional":false,"prefetched":false,"chunks":[0],"assets":[],"issuer":"/Users/mk/Code/github/msafi/text-mask/node_modules/awesome-typescript-loader/dist/entry.js?{\"tsconfig\":\"./angular2/tsconfig.json\",\"declaration\":true}!/Users/mk/Code/github/msafi/text-mask/angular2/src/angular2TextMask.ts","failed":false,"errors":0,"warnings":0,"reasons":[{"moduleId":0,"moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/awesome-typescript-loader/dist/entry.js?{\"tsconfig\":\"./angular2/tsconfig.json\",\"declaration\":true}!/Users/mk/Code/github/msafi/text-mask/angular2/src/angular2TextMask.ts","module":"./angular2/src/angular2TextMask.ts","moduleName":"./angular2/src/angular2TextMask.ts","type":"cjs require","userRequest":"../../core/src/createTextMaskInputElement","loc":"13:35-87"}],"source":"'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol ? \"symbol\" : typeof obj; };\n\nexports.default = createTextMaskInputElement;\n\nvar _adjustCaretPosition = require('./adjustCaretPosition.js');\n\nvar _adjustCaretPosition2 = _interopRequireDefault(_adjustCaretPosition);\n\nvar _conformToMask2 = require('./conformToMask.js');\n\nvar _conformToMask3 = _interopRequireDefault(_conformToMask2);\n\nvar _utilities = require('./utilities.js');\n\nvar _constants = require('./constants.js');\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar strPlaceholder = 'placeholder';\nvar strFunction = 'function';\nvar emptyString = '';\nvar strNone = '';\n\nfunction createTextMaskInputElement(_ref) {\n var inputElement = _ref.inputElement;\n var providedMask = _ref.mask;\n var guide = _ref.guide;\n var pipe = _ref.pipe;\n var _ref$placeholderChar = _ref.placeholderChar;\n var placeholderChar = _ref$placeholderChar === undefined ? _constants.placeholderChar : _ref$placeholderChar;\n var onAccept = _ref.onAccept;\n var onReject = _ref.onReject;\n var _ref$keepCharPosition = _ref.keepCharPositions;\n var keepCharPositions = _ref$keepCharPosition === undefined ? false : _ref$keepCharPosition;\n\n // Text Mask accepts masks that are a combination of a `mask` and a `pipe` that work together. If such a `mask` is\n // passed, we destructure it below, so the rest of the code can work normally as if a separate `mask` and a `pipe`\n // were passed.\n if ((typeof providedMask === 'undefined' ? 'undefined' : _typeof(providedMask)) === 'object' && providedMask.pipe !== undefined && providedMask.mask !== undefined) {\n pipe = providedMask.pipe;\n providedMask = providedMask.mask;\n }\n\n // Anything that we will need to keep between `update` calls, we will store in this `state` object.\n var state = { previousConformedValue: emptyString };\n\n // The `placeholder` is an essential piece of how Text Mask works. For a mask like `(111)`, the placeholder would be\n // `(___)` if the `placeholderChar` is set to `_`.\n var placeholder = void 0;\n\n // We don't know what the mask would be yet. If it is an array, we take it as is, but if it's a function, we will\n // have to call that function to get the mask array.\n var mask = void 0;\n\n // If the provided mask is an array, we can call `convertMaskToPlaceholder` here once and we'll always have the\n // correct `placeholder`.\n if (providedMask instanceof Array) {\n placeholder = (0, _utilities.convertMaskToPlaceholder)(providedMask, placeholderChar);\n }\n\n // If the `inputElement`, doesn't have a placeholder. Text Mask will set a default placeholder on it.\n if (inputElement.placeholder === emptyString) {\n inputElement.setAttribute(strPlaceholder, placeholder);\n }\n\n return {\n state: state,\n\n // `update` is called by framework components whenever they want to update the `value` of the input element.\n // The caller can send a `rawValue` to be conformed and set on the input element. However, the default use-case\n // is for this to be read from the `inputElement` directly.\n update: function update() {\n var rawValue = arguments.length <= 0 || arguments[0] === undefined ? inputElement.value : arguments[0];\n\n // If `rawValue` equals `state.previousConformedValue`, we don't need to change anything. So, we return.\n // This check is here to handle controlled framework components that repeat the `update` call on every render.\n if (rawValue === state.previousConformedValue) {\n return;\n }\n\n // We check the provided `rawValue` before moving further.\n // If it's something we can't work with `getSafeRawValue` will throw.\n var safeRawValue = getSafeRawValue(rawValue);\n\n // `selectionStart` indicates to us where the caret position is after the user has typed into the input\n var currentCaretPosition = inputElement.selectionStart;\n\n // We need to know what the `previousConformedValue` is from the previous `update` call\n\n var previousConformedValue = state.previousConformedValue;\n\n\n var caretTrapIndexes = void 0;\n\n // If the `providedMask` is a function. We need to call it at every `update` to get the `mask` array.\n // Then we also need to get the `placeholder`\n if ((typeof providedMask === 'undefined' ? 'undefined' : _typeof(providedMask)) === strFunction) {\n mask = providedMask(safeRawValue, { currentCaretPosition: currentCaretPosition, previousConformedValue: previousConformedValue, placeholderChar: placeholderChar });\n\n // mask functions can setup caret traps to have some control over how the caret moves. We need to process\n // the mask for any caret traps. `processCaretTraps` will remove the caret traps from the mask and return\n // the indexes of the caret traps.\n\n var _processCaretTraps = (0, _utilities.processCaretTraps)(mask);\n\n var maskWithoutCaretTraps = _processCaretTraps.maskWithoutCaretTraps;\n var indexes = _processCaretTraps.indexes;\n\n\n mask = maskWithoutCaretTraps; // The processed mask is what we're interested in\n caretTrapIndexes = indexes; // And we need to store these indexes because they're needed by `adjustCaretPosition`\n\n placeholder = (0, _utilities.convertMaskToPlaceholder)(mask, placeholderChar);\n\n // If the `providedMask` is not a function, we just use it as-is.\n } else {\n mask = providedMask;\n }\n\n // The following object will be passed to `conformToMask` to determine how the `rawValue` will be conformed\n var conformToMaskConfig = {\n previousConformedValue: previousConformedValue,\n guide: guide,\n placeholderChar: placeholderChar,\n pipe: pipe,\n placeholder: placeholder,\n currentCaretPosition: currentCaretPosition,\n keepCharPositions: keepCharPositions\n };\n\n // `conformToMask` returns the information below: we need the `conformedValue` and we need to know whether\n // some characters were rejected. We'll use `someCharsRejected` to know whether we should call the `onReject`\n // callback\n\n var _conformToMask = (0, _conformToMask3.default)(safeRawValue, mask, conformToMaskConfig);\n\n var conformedValue = _conformToMask.conformedValue;\n var someCharsRejected = _conformToMask.meta.someCharsRejected;\n\n // The following few lines are to support the `pipe` feature.\n\n var piped = (typeof pipe === 'undefined' ? 'undefined' : _typeof(pipe)) === strFunction;\n\n var pipeResults = {};\n\n // If `pipe` is a function, we call it.\n if (piped) {\n // `pipe` receives the `conformedValue` and the configurations with which `conformToMask` was called.\n pipeResults = pipe(conformedValue, _extends({ rawValue: safeRawValue }, conformToMaskConfig));\n\n // `pipeResults` should be an object. But as a convenience, we allow the pipe author to just return `false` to\n // indicate rejection. Or return just a string when there are no piped characters.\n // If the `pipe` returns `false` or a string, the block below turns it into an object that the rest\n // of the code can work with.\n if (pipeResults === false) {\n // If the `pipe` rejects `conformedValue`, we use the `previousConformedValue`, and set `rejected` to `true`.\n pipeResults = { value: previousConformedValue, rejected: true };\n } else if ((0, _utilities.isString)(pipeResults)) {\n pipeResults = { value: pipeResults };\n }\n }\n\n // Before we proceed, we need to know which conformed value to use, the one returned by the pipe or the one\n // returned by `conformToMask`.\n var finalConformedValue = piped ? pipeResults.value : conformedValue;\n\n // After setting the `finalConformedValue` as the value of the `inputElement`, we will need to know where to set\n // the caret position. `adjustCaretPosition` will tell us.\n var adjustedCaretPosition = (0, _adjustCaretPosition2.default)({\n previousConformedValue: previousConformedValue,\n conformedValue: finalConformedValue,\n placeholder: placeholder,\n rawValue: safeRawValue,\n currentCaretPosition: currentCaretPosition,\n placeholderChar: placeholderChar,\n indexesOfPipedChars: pipeResults.indexesOfPipedChars,\n caretTrapIndexes: caretTrapIndexes\n });\n\n // Text Mask sets the input value to an empty string when the condition below is set. It provides a better UX.\n var inputValueShouldBeEmpty = finalConformedValue === placeholder && adjustedCaretPosition === 0;\n var inputElementValue = inputValueShouldBeEmpty ? emptyString : finalConformedValue;\n\n inputElement.value = inputElementValue; // set the input value\n safeSetSelection(inputElement, adjustedCaretPosition); // adjust caret position\n state.previousConformedValue = inputElementValue; // store value for access for next time\n\n // If we set a value to the input element that's different form `previousConformedValue`, it means user input\n // was accepted, and we call the `onAccept` callback if it's a function.\n if ((typeof onAccept === 'undefined' ? 'undefined' : _typeof(onAccept)) === strFunction && inputElementValue !== previousConformedValue) {\n onAccept();\n }\n\n // Now we need to figure out if user input was rejected to decide whether to call `onReject` callback or not.\n // We need to know if the operation is deletion, because if it is, then we definitely don't need to call\n // `onReject` in that case.\n var isDeletion = safeRawValue.length < previousConformedValue.length;\n\n // To call `onReject`\n if (\n // `onReject` has to be a function\n (typeof onReject === 'undefined' ? 'undefined' : _typeof(onReject)) === strFunction && (\n\n // `someCharsRejected` or `pipeResults.rejected` has to be true\n someCharsRejected || pipeResults.rejected) &&\n\n // the operation needs to be addition, not deletion\n isDeletion === false) {\n // `onReject` receives the `finalConformedValue` and booleans for `pipeRejection` and `maskRejection`\n // so know whether the user input was rejected by the mask pattern or by the pipe.\n onReject({\n conformedValue: finalConformedValue,\n pipeRejection: pipeResults.rejected,\n maskRejection: someCharsRejected\n });\n }\n }\n };\n}\n\nfunction safeSetSelection(element, selectionPosition) {\n if (document.activeElement === element) {\n element.setSelectionRange(selectionPosition, selectionPosition, strNone);\n }\n}\n\nfunction getSafeRawValue(inputValue) {\n if ((0, _utilities.isString)(inputValue)) {\n return inputValue;\n } else if ((0, _utilities.isNumber)(inputValue)) {\n return String(inputValue);\n } else if (inputValue === undefined || inputValue === null) {\n return emptyString;\n } else {\n throw new Error(\"The 'value' provided to Text Mask needs to be a string or a number. The value \" + ('received was:\\n\\n ' + JSON.stringify(inputValue)));\n }\n}"},{"id":6,"identifier":"external {\"root\":[\"ng\",\"core\"],\"commonjs\":\"@angular/core\",\"commonjs2\":\"@angular/core\",\"amd\":\"@angular/core\"}","name":"external {\"root\":[\"ng\",\"core\"],\"commonjs\":\"@angular/core\",\"commonjs2\":\"@angular/core\",\"amd\":\"@angular/core\"}","index":1,"index2":0,"size":42,"cacheable":false,"built":false,"optional":false,"prefetched":false,"chunks":[0],"assets":[],"issuer":"/Users/mk/Code/github/msafi/text-mask/node_modules/awesome-typescript-loader/dist/entry.js?{\"tsconfig\":\"./angular2/tsconfig.json\",\"declaration\":true}!/Users/mk/Code/github/msafi/text-mask/angular2/src/angular2TextMask.ts","failed":false,"errors":0,"warnings":0,"reasons":[{"moduleId":0,"moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/awesome-typescript-loader/dist/entry.js?{\"tsconfig\":\"./angular2/tsconfig.json\",\"declaration\":true}!/Users/mk/Code/github/msafi/text-mask/angular2/src/angular2TextMask.ts","module":"./angular2/src/angular2TextMask.ts","moduleName":"./angular2/src/angular2TextMask.ts","type":"cjs require","userRequest":"@angular/core","loc":"11:13-37"}]},{"id":7,"identifier":"external {\"root\":[\"ng\",\"forms\"],\"commonjs\":\"@angular/forms\",\"commonjs2\":\"@angular/forms\",\"amd\":\"@angular/forms\"}","name":"external {\"root\":[\"ng\",\"forms\"],\"commonjs\":\"@angular/forms\",\"commonjs2\":\"@angular/forms\",\"amd\":\"@angular/forms\"}","index":2,"index2":1,"size":42,"cacheable":false,"built":false,"optional":false,"prefetched":false,"chunks":[0],"assets":[],"issuer":"/Users/mk/Code/github/msafi/text-mask/node_modules/awesome-typescript-loader/dist/entry.js?{\"tsconfig\":\"./angular2/tsconfig.json\",\"declaration\":true}!/Users/mk/Code/github/msafi/text-mask/angular2/src/angular2TextMask.ts","failed":false,"errors":0,"warnings":0,"reasons":[{"moduleId":0,"moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/awesome-typescript-loader/dist/entry.js?{\"tsconfig\":\"./angular2/tsconfig.json\",\"declaration\":true}!/Users/mk/Code/github/msafi/text-mask/angular2/src/angular2TextMask.ts","module":"./angular2/src/angular2TextMask.ts","moduleName":"./angular2/src/angular2TextMask.ts","type":"cjs require","userRequest":"@angular/forms","loc":"12:14-39"}]}],"filteredModules":0,"origins":[{"moduleId":0,"module":"/Users/mk/Code/github/msafi/text-mask/node_modules/awesome-typescript-loader/dist/entry.js?{\"tsconfig\":\"./angular2/tsconfig.json\",\"declaration\":true}!/Users/mk/Code/github/msafi/text-mask/angular2/src/angular2TextMask.ts","moduleIdentifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/awesome-typescript-loader/dist/entry.js?{\"tsconfig\":\"./angular2/tsconfig.json\",\"declaration\":true}!/Users/mk/Code/github/msafi/text-mask/angular2/src/angular2TextMask.ts","moduleName":"./angular2/src/angular2TextMask.ts","loc":"","name":"main","reasons":[]}]}],"modules":[{"id":0,"identifier":"/Users/mk/Code/github/msafi/text-mask/node_modules/awesome-typescript-loader/dist/entry.js?{\"tsconfig\":\"./angular2/tsconfig.json\",\"declaration\":true}!/Users/mk/Code/github/msafi/text-mask/angular2/src/angular2TextMask.ts","name":"./angular2/src/angular2TextMask.ts","index":0,"index2":7,"size":2632,"cacheable":true,"built":true,"optional":false,"prefetched":false,"chunks":[0],"assets":["angular2/src/angular2TextMask.d.ts"],"issuer":null,"failed":false,"errors":0,"warnings":0,"reasons":[],"source":"\"use strict\";\r\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n};\r\nvar __metadata = (this && this.__metadata) || function (k, v) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\r\n};\r\nvar core_1 = require('@angular/core');\r\nvar forms_1 = require('@angular/forms');\r\nvar createTextMaskInputElement_1 = require('../../core/src/createTextMaskInputElement');\r\nvar MaskedInputDirective = (function () {\r\n function MaskedInputDirective(inputElement, ngControl) {\r\n this.ngControl = ngControl;\r\n this.textMaskConfig = {\r\n mask: '',\r\n guide: true,\r\n placeholderChar: '_',\r\n pipe: undefined,\r\n keepCharPositions: false,\r\n onReject: undefined,\r\n onAccept: undefined\r\n };\r\n this.inputElement = inputElement.nativeElement;\r\n }\r\n MaskedInputDirective.prototype.ngOnInit = function () {\r\n var _this = this;\r\n this.textMaskInputElement = createTextMaskInputElement_1.default(Object.assign({ inputElement: this.inputElement, }, this.textMaskConfig));\r\n // This ensures that initial model value gets masked\r\n setTimeout(function () { return _this.onInput(); });\r\n };\r\n MaskedInputDirective.prototype.onInput = function () {\r\n this.textMaskInputElement.update();\r\n this.ngControl.viewToModelUpdate(this.inputElement.value);\r\n };\r\n __decorate([\r\n core_1.Input('textMask'), \r\n __metadata('design:type', Object)\r\n ], MaskedInputDirective.prototype, \"textMaskConfig\", void 0);\r\n MaskedInputDirective = __decorate([\r\n core_1.Directive({\r\n host: {\r\n '(input)': 'onInput()'\r\n },\r\n selector: 'input[textMask]'\r\n }), \r\n __metadata('design:paramtypes', [core_1.ElementRef, forms_1.NgControl])\r\n ], MaskedInputDirective);\r\n ret