mapcomplete/UI/Input/TextField.ts

102 lines
3.1 KiB
TypeScript
Raw Normal View History

2020-07-01 02:12:33 +02:00
import {UIElement} from "../UIElement";
import {UIEventSource} from "../UIEventSource";
2020-07-20 15:54:50 +02:00
import {InputElement} from "./InputElement";
import {FixedUiElement} from "../Base/FixedUiElement";
2020-07-01 02:12:33 +02:00
2020-07-20 15:54:50 +02:00
export class TextField<T> extends InputElement<T> {
2020-07-01 02:12:33 +02:00
2020-07-20 13:28:45 +02:00
private value: UIEventSource<string>;
private mappedValue: UIEventSource<T>;
2020-07-01 02:12:33 +02:00
/**
* Pings and has the value data
*/
public enterPressed = new UIEventSource<string>(undefined);
2020-07-20 15:54:50 +02:00
private _placeholder: UIElement;
private _fromString?: (string: string) => T;
private _toString: (t: T) => string;
2020-07-01 02:12:33 +02:00
2020-07-20 13:28:45 +02:00
constructor(options: {
2020-07-20 15:54:50 +02:00
placeholder?: string | UIElement,
toString?: (t: T) => string,
fromString?: (string: string) => T,
2020-07-20 13:28:45 +02:00
value?: UIEventSource<T>
}) {
2020-07-20 15:54:50 +02:00
super(undefined);
2020-07-20 13:28:45 +02:00
this.value = new UIEventSource<string>("");
this.mappedValue = options?.value ?? new UIEventSource<T>(undefined);
2020-07-20 15:54:50 +02:00
// @ts-ignore
this._fromString = options.fromString ?? ((str) => (str))
2020-07-20 13:28:45 +02:00
this.value.addCallback((str) => this.mappedValue.setData(options.fromString(str)));
this.mappedValue.addCallback((t) => this.value.setData(options.toString(t)));
2020-07-20 15:54:50 +02:00
this._placeholder =
typeof(options.placeholder) === "string" ? new FixedUiElement(options.placeholder) :
(options.placeholder ?? new FixedUiElement(""));
this._toString = options.toString ?? ((t) => ("" + t));
2020-07-20 13:28:45 +02:00
const self = this;
this.mappedValue.addCallback((t) => {
if (t === undefined && t === null) {
return;
}
const field = document.getElementById('text-' + this.id);
2020-07-20 15:54:50 +02:00
if (field === undefined || field === null) {
2020-07-20 13:28:45 +02:00
return;
}
2020-07-20 15:54:50 +02:00
// @ts-ignore
2020-07-20 13:28:45 +02:00
field.value = options.toString(t);
})
2020-07-05 18:59:47 +02:00
}
GetValue(): UIEventSource<T> {
2020-07-20 13:28:45 +02:00
return this.mappedValue;
2020-07-01 02:12:33 +02:00
}
protected InnerRender(): string {
2020-07-20 15:54:50 +02:00
return "<form onSubmit='return false' class='form-text-field'>" +
"<input type='text' placeholder='" + this._placeholder.InnerRender() + "' id='text-" + this.id + "'>" +
2020-07-01 02:12:33 +02:00
"</form>";
}
InnerUpdate(htmlElement: HTMLElement) {
const field = document.getElementById('text-' + this.id);
2020-07-20 15:54:50 +02:00
if(field === null){
return;
}
2020-07-01 02:12:33 +02:00
const self = this;
field.oninput = () => {
2020-07-05 18:59:47 +02:00
// @ts-ignore
2020-07-01 02:12:33 +02:00
self.value.setData(field.value);
};
field.addEventListener("keyup", function (event) {
if (event.key === "Enter") {
2020-07-05 18:59:47 +02:00
// @ts-ignore
2020-07-01 02:12:33 +02:00
self.enterPressed.setData(field.value);
}
});
2020-07-05 18:59:47 +02:00
2020-07-01 02:12:33 +02:00
}
2020-07-20 15:54:50 +02:00
IsValid(t: T): boolean {
if(t === undefined || t === null){
return false;
}
const result = this._toString(t);
return result !== undefined && result !== null;
}
2020-07-01 02:12:33 +02:00
Clear() {
const field = document.getElementById('text-' + this.id);
if (field !== undefined) {
2020-07-05 18:59:47 +02:00
// @ts-ignore
2020-07-01 02:12:33 +02:00
field.value = "";
}
}
}