Skip to content

Commit

Permalink
work for #4842
Browse files Browse the repository at this point in the history
  • Loading branch information
OlgaLarina committed Jan 24, 2024
1 parent 9dc7660 commit d5fb9f0
Show file tree
Hide file tree
Showing 13 changed files with 529 additions and 177 deletions.
5 changes: 4 additions & 1 deletion src/entries/chunks/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,10 @@ export {
sanitizeEditableContent,
IAttachKey2clickOptions
} from "../../utils/utils";
export { InputMaskBase } from "../../mask/mask";
export { MaskManagerType } from "../../mask/mask_manager";
export { InputMaskBase } from "../../mask/mask_base";
export { InputMaskPattern } from "../../mask/mask_pattern";
export { InputMaskNumber } from "../../mask/mask_number";
export * from "../../utils/cssClassBuilder";

export { surveyCss, defaultV2Css, defaultV2ThemeName } from "../../defaultCss/defaultV2Css";
Expand Down
54 changes: 54 additions & 0 deletions src/mask/input_element_adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { InputMaskBase } from "./mask_base";
import { ITextMaskInputArgs } from "./mask_manager";

export class InputElementAdapter {
constructor(private mask: InputMaskBase, private inputElement: HTMLInputElement, value: string = "") {
this.inputElement.value = mask.getMaskedValue(value, true);
this.addInputEventListener();
}

beforeInputHandler = (event: any) => {
const args = this.createArgs(event);
const result = this.mask.processInput(args);
this.inputElement.value = result.text;
this.inputElement.setSelectionRange(result.cursorPosition, result.cursorPosition);
if(!result.cancelPreventDefault) {
event.preventDefault();
}
};

public createArgs(event: any): ITextMaskInputArgs {
const args: ITextMaskInputArgs = {
insertedCharacters: event.data,
selectionStart: event.target.selectionStart,
selectionEnd: event.target.selectionEnd,
prevValue: event.target.value,
inputDirection: "leftToRight"
};
switch (event.inputType) {
case "deleteContentBackward": {
args.selectionStart = Math.max(args.selectionStart - 1, 0);
args.inputDirection = "rightToLeft";
break;
}
case "deleteContentForward": {
args.selectionEnd += 1;
break;
}
}
return args;
}
public addInputEventListener(): void {
if (!!this.inputElement) {
this.inputElement.addEventListener("beforeinput", this.beforeInputHandler);
}
}
public removeInputEventListener(): void {
if (!!this.inputElement) {
this.inputElement.removeEventListener("beforeinput", this.beforeInputHandler);
}
}
public dispose(): void {
this.removeInputEventListener();
}
}
54 changes: 0 additions & 54 deletions src/mask/mask.ts

This file was deleted.

33 changes: 33 additions & 0 deletions src/mask/mask_base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { IInputMaskType, IMaskOption, IMaskedValue, ITextMaskInputArgs } from "./mask_manager";

export class InputMaskBase implements IInputMaskType {
protected prevSelectionStart: number;
protected prevInputValue: string;

constructor(protected maskOptions: IMaskOption) { }

// public get maskedInputValue(): string {
// return this.input.value;
// }
// public get unmaskedInputValue(): string {
// return this.getUnmaskedValue(this.input.value, true);
// }

public processInput(args: ITextMaskInputArgs): IMaskedValue {
const result = { text: args.prevValue, cursorPosition: args.selectionEnd, cancelPreventDefault: false };

const leftPart = args.prevValue.slice(0, args.selectionStart) + (args.insertedCharacters || "");
if(!args.insertedCharacters && args.inputDirection === "rightToLeft") {
result.cursorPosition = args.selectionStart;
} else {
result.cursorPosition = this.getMaskedValue(leftPart).length;
}

const src = leftPart + args.prevValue.slice(args.selectionEnd);
result.text = this.getMaskedValue(src, true);
return result;
}

public getUnmaskedValue(src: string, matchWholeMask: boolean = false): string { return src; }
public getMaskedValue(src: string, matchWholeMask: boolean = false): string { return src; }
}
43 changes: 43 additions & 0 deletions src/mask/mask_manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { HashTable } from "../helpers";
import { InputMaskBase } from "./mask_base";

export interface IMaskOption {
type: string;
mask: string;
}

export interface IMaskedValue {
text: string;
cursorPosition: number;
cancelPreventDefault: boolean;
}

export interface ITextMaskInputArgs {
prevValue: string;
selectionStart: number;
selectionEnd: number;
insertedCharacters: string | null;
inputDirection?: "leftToRight" | "rightToLeft";
}

export interface IInputMaskType {
getMaskedValue(src: string, matchWholeMask?: boolean): string;
getUnmaskedValue(src: string, matchWholeMask?: boolean): string;
processInput(args: ITextMaskInputArgs): IMaskedValue;
}

export class MaskManagerType {
public static Instance: MaskManagerType = new MaskManagerType();
private creatorHash: HashTable<(maskOption: IMaskOption) => IInputMaskType> = {};

public registerMaskManagerType(maskType: string, maskCreator: (maskOption: IMaskOption) => IInputMaskType): void {
this.creatorHash[maskType] = maskCreator;
}

public createInputMask(maskOption: IMaskOption): IInputMaskType {
const creator = MaskManagerType.Instance.creatorHash[maskOption.type];
if (!!creator) return creator(maskOption);

return new InputMaskBase(maskOption);
}
}
35 changes: 21 additions & 14 deletions src/mask/number_mask.ts → src/mask/mask_number.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { InputMaskBase } from "./mask";
import { InputMaskBase } from "./mask_base";
import { IMaskLiteral } from "./mask_pattern";
import { IMaskedValue, settings } from "./mask_utils";
import { MaskManagerType, IMaskOption, IMaskedValue } from "./mask_manager";
import { settings } from "./mask_utils";

interface INumberMaskOption {
mask?: string;
interface INumberMaskOption extends IMaskOption {
align?: "left" | "right";
allowNegative?: boolean;
decimal?: string;
Expand Down Expand Up @@ -109,18 +109,25 @@ export function getNumberUnmaskedValue(str: string, option?: INumberMaskOption):
}

export class InputMaskNumber extends InputMaskBase {

constructor(input: HTMLInputElement, private options?: INumberMaskOption) {
super(input, "9+");
constructor(options?: INumberMaskOption) {
super(options || <IMaskOption>{ mask: "9+" });
}

protected getMaskedValue(mask: string): string {
return getNumberMaskedValue(getNumberUnmaskedValue(this.input.value, this.options), this.options);
get numberOptions(): INumberMaskOption {
return this.maskOptions as INumberMaskOption;
}

protected processMaskedValue(mask: string): IMaskedValue {
// return processValueWithPattern(this.input.value, mask, this._prevSelectionStart, this.input.selectionStart);
const text = getNumberMaskedValue(getNumberUnmaskedValue(this.input.value, this.options), this.options);
return { text: text, cursorPosition: this.input.selectionStart };
public getMaskedValue(src: string, matchWholeMask: boolean = false): string {
return getNumberMaskedValue(src, this.numberOptions);
}
public getUnmaskedValue(src: string, matchWholeMask: boolean = false): string {
return getNumberUnmaskedValue(src, this.numberOptions).toString();
}
}
// public processMaskedValue(): IMaskedValue {
// // return processValueWithPattern(this.input.value, mask, this._prevSelectionStart, this.input.selectionStart);
// const text = getNumberMaskedValue(getNumberUnmaskedValue(this.input.value, this.numberOptions), this.numberOptions);
// return { text: text, cursorPosition: this.input.selectionStart, cancelPreventDefault: false };
// }
}

MaskManagerType.Instance.registerMaskManagerType("number", (maskOptions: IMaskOption) => { return new InputMaskNumber(maskOptions); });
Loading

0 comments on commit d5fb9f0

Please sign in to comment.