import {UIElement} from "../UIElement"; import {UIEventSource} from "../UIEventSource"; import {InputElement} from "./InputElement"; import Translations from "../i18n/Translations"; export class TextField extends InputElement { private value: UIEventSource; private mappedValue: UIEventSource; /** * Pings and has the value data */ public enterPressed = new UIEventSource(undefined); private _placeholder: UIElement; private _fromString?: (string: string) => T; private _toString: (t: T) => string; constructor(options: { /** * Shown as placeholder */ placeholder?: string | UIElement, /** * Converts the T to a (canonical) string * @param t */ toString: (t: T) => string, /** * Converts the string to a T * Returns undefined if invalid * @param string */ fromString: (string: string) => T, value?: UIEventSource }) { super(undefined); const self = this; this.value = new UIEventSource(""); this.mappedValue = options?.value ?? new UIEventSource(undefined); this.mappedValue.addCallback(() => self.InnerUpdate()); // @ts-ignore this._fromString = options.fromString ?? ((str) => (str)) this.value.addCallback((str) => this.mappedValue.setData(options.fromString(str))); this.mappedValue.addCallback((t) => this.value.setData(options.toString(t))); this._placeholder = Translations.W(options.placeholder ?? ""); this.ListenTo(this._placeholder._source); this._toString = options.toString ?? ((t) => ("" + t)); this.mappedValue.addCallback((t) => { if (t === undefined || t === null) { return; } const field = document.getElementById('text-' + this.id); if (field === undefined || field === null) { return; } // @ts-ignore field.value = options.toString(t); }) } GetValue(): UIEventSource { return this.mappedValue; } ShowValue(t: T): boolean { if (!this.IsValid(t)) { return false; } this.mappedValue.setData(t); } InnerRender(): string { return `
` + `` + `
`; } InnerUpdate() { const field = document.getElementById('text-' + this.id); if (field === null) { return; } this.mappedValue.addCallback((data) => { field.className = this.mappedValue.data !== undefined ? "valid" : "invalid"; }); const self = this; field.oninput = () => { // @ts-ignore self.value.setData(field.value); }; field.addEventListener("keyup", function (event) { if (event.key === "Enter") { // @ts-ignore self.enterPressed.setData(field.value); } }); if (this.IsValid(this.mappedValue.data)) { const expected = this._toString(this.mappedValue.data); // @ts-ignore if (field.value !== expected) { // @ts-ignore field.value = expected; } } } IsValid(t: T): boolean { if(t === undefined || t === null){ return false; } const result = this._toString(t); return result !== undefined && result !== null; } Clear() { const field = document.getElementById('text-' + this.id); if (field !== undefined) { // @ts-ignore field.value = ""; } } }