Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import NumericInput from "./NumericInput.js";
- import ParseMath from "./ParseMath.js";
- export default class CalcInput extends NumericInput {
- private spanElement: HTMLSpanElement;
- constructor(hostElementId: string) {
- super(hostElementId);
- this.spanElement = document.createElement("SPAN") as HTMLSpanElement;
- this.hostElement.appendChild(this.spanElement);
- }
- public destroy(): void {
- super.destroy();
- this.spanElement.remove();
- this.spanElement = null;
- }
- protected saveProps(
- newValue: number,
- sync: boolean = false,
- originalText?: string
- ) {
- super.saveProps(newValue, sync, originalText);
- this.spanElement.innerHTML = String(this.isValid ? this.value : "?");
- }
- protected textToValue(text: string): number {
- if (this.isEmptyString(text) || text === null) {
- return null;
- }
- try {
- const num: number = Number(ParseMath(text.trim()));
- return isNaN(num) ? undefined : num;
- } catch {
- return undefined;
- }
- }
- }
- import InputControl from "./InputControl.js";
- export default class NumericInput extends InputControl<number> {
- protected textToValue(text: string): number {
- if (this.isEmptyString(text) || text === null) {
- return null;
- }
- const num: number = Number(text.trim());
- return isNaN(num) ? undefined : num;
- }
- protected listener(): void {
- this.saveText(this.inputElement.value);
- }
- private saveText(text: string, sync: boolean = false): void {
- this.saveProps(this.textToValue(text), sync, text);
- }
- set value(newValue: number) {
- this.saveProps(this.textToValue(String(newValue)), true);
- }
- get value(): number {
- return this._value;
- }
- set text(newText: string) {
- this.saveText(newText, true);
- }
- get text(): string {
- return this._text;
- }
- }
- import EventEmitter from "./EventEmitter.js";
- export default class InputControl<T> {
- public isValidChanged: EventEmitter = new EventEmitter();
- public valueChanged: EventEmitter = new EventEmitter();
- public textChanged: EventEmitter = new EventEmitter();
- protected _text: string;
- protected _value: any = null;
- protected inputElement: HTMLInputElement;
- protected hostElement: HTMLDivElement;
- private _isValid: boolean;
- private invalidCSSClass: string = "wij-invalid";
- private baseCSSClass: string = "wij-control";
- constructor(hostElementId: string) {
- this.hostElement = document.querySelector(`#${hostElementId}`);
- const isInvalidElement: boolean =
- !!this.hostElement &&
- (this.hostElement.tagName !== "DIV" ||
- !!this.hostElement.firstElementChild);
- if (this.hostElement === null) {
- console.error("Host element cannot be null.");
- } else if (isInvalidElement) {
- console.error("Host element must be an empty div.");
- } else {
- const input: HTMLInputElement = document.createElement(
- "INPUT"
- ) as HTMLInputElement;
- input.setAttribute("type", "text");
- input.addEventListener("input", this.listener.bind(this));
- this.hostElement.appendChild(input);
- this.inputElement = input;
- this.inputElement.classList.add(this.baseCSSClass);
- }
- }
- public onValueChanged(): void {
- this.valueChanged.broadcast(this.value);
- }
- public onTextChanged(): void {
- this.textChanged.broadcast(this.text);
- }
- public onIsValidChanged(): void {
- this.isValidChanged.broadcast(this.isValid);
- }
- public destroy(): void {
- this.hostElement.removeEventListener("input", this.listener);
- this.inputElement.remove();
- this.inputElement = null;
- this.valueChanged.removeHandler();
- this.isValidChanged.removeHandler();
- this.textChanged.removeHandler();
- }
- get isValid(): boolean {
- return this._isValid;
- }
- set value(newValue: T) {
- this.saveProps(newValue, true);
- }
- get value(): T {
- return this._value;
- }
- set text(newText: string) {
- const oldValue: T = this.value;
- this._text = newText;
- this._value = this._text;
- if (this.text !== newText) {
- this.onTextChanged();
- }
- if (oldValue !== this.value) {
- this.onValueChanged();
- }
- }
- get text(): string {
- return this._text;
- }
- protected listener(): void {}
- // pass originalText to save text w/o any changes
- protected saveProps(
- newValue: T,
- sync: boolean = false,
- originalText?: string
- ) {
- const oldValue: T = this.value;
- const oldText: string = this.text;
- let newText: string;
- this._value = newValue;
- if (this.value === null) {
- newText = "";
- this.setValid();
- } else if (this.value === undefined) {
- newText = null;
- this.setInvalid();
- } else {
- newText = this.value.toString();
- this.setValid();
- }
- this._text = originalText ? originalText : newText;
- if (this.text !== oldText) {
- this.onTextChanged();
- }
- if (this.value !== oldValue) {
- this.onValueChanged();
- }
- if (sync) {
- this.inputElement.value = this.text;
- }
- }
- // protected setter is required to call onIsValidChanged
- // but different access modifiers is prohibited in ts
- protected setValid(newIsValid: boolean = true): void {
- const oldIsValid = this.isValid;
- this._isValid = newIsValid;
- if (this.isValid) {
- this.inputElement.classList.remove(this.invalidCSSClass);
- } else {
- this.inputElement.classList.add(this.invalidCSSClass);
- }
- if (this.isValid !== oldIsValid) {
- this.onIsValidChanged();
- }
- }
- protected setInvalid(): void {
- this.setValid(false);
- }
- protected isEmptyString = (str: string): boolean =>
- String(str).trim().length === 0
- }
- type Handler = (value: any) => void;
- export default class EventEmitter {
- private eventHandlers: Handler[] = [];
- public addHandler(eventHandler: Handler): void {
- this.eventHandlers.push(eventHandler);
- }
- public removeHandler(handler?: Handler): void {
- if (!handler) {
- this.eventHandlers = [];
- } else {
- this.eventHandlers = this.eventHandlers.filter((eventHander: Handler) => handler !== eventHander);
- }
- }
- public broadcast(value): void {
- this.eventHandlers.forEach((handler: Handler) => handler(value));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement