Skip to content

Commit 41fe0d3

Browse files
author
Ilya Karpuk
committed
fix: fix caret pisition
1 parent f2067b1 commit 41fe0d3

File tree

5 files changed

+56
-31
lines changed

5 files changed

+56
-31
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"release:major": "npm run version:major && npm run build:lib && npm run pack:lib && npm run publish:lib",
3939
"release:minor": "npm run version:minor && npm run build:lib && npm run pack:lib && npm run publish:lib",
4040
"release:patch": "npm run version:patch && npm run build:lib && npm run pack:lib && npm run publish:lib",
41-
"start": "ng serve -o showcase",
41+
"start": "ng serve -o showcase --hmr --port=4199",
4242
"test": "ng test ngx-mask-lib",
4343
"version:major": "npm --no-git-tag-version version major && cd projects/ngx-mask-lib && npm --no-git-tag-version version major",
4444
"version:minor": "npm --no-git-tag-version version minor && cd projects/ngx-mask-lib && npm --no-git-tag-version version minor",

projects/ngx-mask-lib/src/lib/mask-applier.service.ts

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,30 @@ export class MaskApplierService {
5050
this.customPattern = customPattern;
5151
return this.applyMask(inputValue, mask);
5252
}
53-
public applyMask(inputValue: string, maskExpression: string, position: number = 0, cb: Function = () => { }): string {
53+
54+
private checkAndRemoveSuffix = (inputValue: string): string => {
55+
if (!this.suffix) {
56+
return inputValue;
57+
}
58+
for (let i = this.suffix.length - 1; i >= 0; i--) {
59+
const substr = this.suffix.substr(i, this.suffix.length);
60+
if (
61+
inputValue.includes(substr) &&
62+
(i - 1 < 0 || !inputValue.includes(this.suffix.substr(i - 1, this.suffix.length)))
63+
) {
64+
return inputValue.replace(substr, '');
65+
}
66+
}
67+
return inputValue;
68+
};
69+
70+
public applyMask(
71+
inputValue: string,
72+
maskExpression: string,
73+
position: number = 0,
74+
backspaced: boolean = false,
75+
cb: Function = () => { },
76+
): string {
5477
if (inputValue === undefined || inputValue === null || maskExpression === undefined) {
5578
return '';
5679
}
@@ -63,8 +86,8 @@ export class MaskApplierService {
6386
if (inputValue.slice(0, this.prefix.length) === this.prefix) {
6487
inputValue = inputValue.slice(this.prefix.length, inputValue.length);
6588
}
66-
if (!!this.suffix && inputValue.endsWith(this.suffix)) {
67-
inputValue = inputValue.slice(0, inputValue.length - this.suffix.length);
89+
if (!!this.suffix && inputValue && inputValue.length > 0) {
90+
inputValue = this.checkAndRemoveSuffix(inputValue);
6891
}
6992
const inputArray: string[] = inputValue.toString().split('');
7093
if (maskExpression === 'IP') {
@@ -330,7 +353,11 @@ export class MaskApplierService {
330353
if (shift < 0) {
331354
this._shift.clear();
332355
}
333-
let res = `${this.prefix}${result}${this.suffix}`;
356+
let onlySpecial = false;
357+
if (backspaced) {
358+
onlySpecial = inputArray.every((char) => this.maskSpecialCharacters.includes(char));
359+
}
360+
let res = `${this.prefix}${onlySpecial ? '' : result}${this.suffix}`;
334361
if (result.length === 0) {
335362
res = `${this.prefix}${result}`;
336363
}
@@ -401,8 +428,10 @@ export class MaskApplierService {
401428

402429
const precisionMatch: RegExpMatchArray | null = inputValue.match(precisionRegEx);
403430
if (precisionMatch && precisionMatch[0].length - 1 > precision) {
404-
inputValue = inputValue.substring(0, inputValue.length - 1);
405-
} else if (precision === 0 && inputValue.endsWith(decimalMarker)) {
431+
const diff = precisionMatch[0].length - 1 - precision;
432+
inputValue = inputValue.substring(0, inputValue.length - diff);
433+
}
434+
if (precision === 0 && inputValue.endsWith(decimalMarker)) {
406435
inputValue = inputValue.substring(0, inputValue.length - 1);
407436
}
408437
}
@@ -413,14 +442,17 @@ export class MaskApplierService {
413442
return str
414443
.split('')
415444
.filter((i: string, idx: number) => {
416-
return i.match('^-?\\d') || i === '.' || i === ',' || (i === '-' && idx === 0);
445+
return i.match('^-?\\d') || i.match('\\s') || i === '.' || i === ',' || (i === '-' && idx === 0);
417446
})
418447
.join('');
419448
}
420449

421450
private _charToRegExpExpression(char: string): string {
422-
const charsToEscape = '[\\^$.|?*+()';
423-
return char === ' ' ? '\\s' : charsToEscape.indexOf(char) >= 0 ? '\\' + char : char;
451+
if (char) {
452+
const charsToEscape = '[\\^$.|?*+()';
453+
return char === ' ' ? '\\s' : charsToEscape.indexOf(char) >= 0 ? '\\' + char : char;
454+
}
455+
return char;
424456
}
425457
// tslint:disable-next-line:max-file-line-count
426458
}

projects/ngx-mask-lib/src/lib/mask.directive.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ export class MaskDirective implements ControlValueAccessor, OnChanges {
221221
: (el.selectionStart as number);
222222
let caretShift = 0;
223223
let backspaceShift = false;
224-
this._maskService.applyValueChanges(position, (shift: number, _backspaceShift: boolean) => {
224+
this._maskService.applyValueChanges(position, this._code === 'Backspace', (shift: number, _backspaceShift: boolean) => {
225225
caretShift = shift;
226226
backspaceShift = _backspaceShift;
227227
});
@@ -234,6 +234,9 @@ export class MaskDirective implements ControlValueAccessor, OnChanges {
234234
let positionToApply: number = this._position
235235
? this._inputValue.length + position + caretShift
236236
: position + (this._code === 'Backspace' && !backspaceShift ? 0 : caretShift);
237+
if (positionToApply === 0) {
238+
positionToApply = this.prefix.length;
239+
}
237240
if (positionToApply > this._getActualInputLength()) {
238241
positionToApply = this._getActualInputLength();
239242
}
@@ -451,14 +454,6 @@ export class MaskDirective implements ControlValueAccessor, OnChanges {
451454
this._maskService.formElementProperty = ['disabled', isDisabled];
452455
}
453456

454-
@HostListener('ngModelChange', ['$event'])
455-
// tslint:disable-next-line: no-any
456-
public onModelChange(e: any): void {
457-
if (!e) {
458-
this._maskService.actualValue = '';
459-
}
460-
}
461-
462457
private _repeatPatternSymbols(maskExp: string): string {
463458
return (
464459
(maskExp.match(/{[0-9]+}/) &&
@@ -470,8 +465,8 @@ export class MaskDirective implements ControlValueAccessor, OnChanges {
470465
}
471466
this._end = index;
472467
const repeatNumber: number = Number(maskExp.slice(this._start + 1, this._end));
473-
const repaceWith: string = new Array(repeatNumber + 1).join(maskExp[this._start - 1]);
474-
return accum + repaceWith;
468+
const replaceWith: string = new Array(repeatNumber + 1).join(maskExp[this._start - 1]);
469+
return accum + replaceWith;
475470
}, '')) ||
476471
maskExp
477472
);

projects/ngx-mask-lib/src/lib/mask.service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class MaskService extends MaskApplierService {
3131
}
3232

3333
// tslint:disable-next-line:cyclomatic-complexity
34-
public applyMask(inputValue: string, maskExpression: string, position: number = 0, cb: Function = () => { }): string {
34+
public applyMask(inputValue: string, maskExpression: string, position: number = 0, backspaced = false, cb: Function = () => { }): string {
3535
if (!maskExpression) {
3636
return inputValue;
3737
}
@@ -68,7 +68,7 @@ export class MaskService extends MaskApplierService {
6868
newInputValue = this.actualValue.length ? this.shiftTypedSymbols(actualResult.join('')) : inputValue;
6969
}
7070
newInputValue = Boolean(newInputValue) && newInputValue.length ? newInputValue : inputValue;
71-
const result: string = super.applyMask(newInputValue, maskExpression, position, cb);
71+
const result: string = super.applyMask(newInputValue, maskExpression, position, backspaced, cb);
7272
this.actualValue = this.getActualValue(result);
7373

7474
// handle some separator implications:
@@ -104,9 +104,9 @@ export class MaskService extends MaskApplierService {
104104
return result + (this.maskExpression === 'IP' ? prefNmask : prefNmask.slice(resLen));
105105
}
106106

107-
public applyValueChanges(position: number = 0, cb: Function = () => { }): void {
107+
public applyValueChanges(position: number = 0, backspaced: boolean = false, cb: Function = () => { }): void {
108108
this.valueWithMask = this._formElement.value; // Сохраняем значение с маской в переменную
109-
this._formElement.value = this.applyMask(this._formElement.value, this.maskExpression, position, cb);
109+
this._formElement.value = this.applyMask(this._formElement.value, this.maskExpression, position, backspaced, cb);
110110
if (this._formElement === this.document.activeElement) {
111111
return;
112112
}

tsconfig.json

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,10 @@
2121
"dom"
2222
],
2323
"paths": {
24-
"ngx-mask": [
25-
"dist/ngx-mask-lib"
26-
],
27-
"ngx-mask/*": [
28-
"dist/ngx-mask-lib/*"
29-
]
24+
// "ngx-mask": ["dist/ngx-mask-lib"],
25+
// "ngx-mask/*": ["dist/ngx-mask-lib/*"]
26+
"ngx-mask": ["projects/ngx-mask-lib/src"],
27+
"ngx-mask/*": ["projects/ngx-mask-lib/src"]
3028
}
3129
}
3230
}

0 commit comments

Comments
 (0)