mapcomplete/UI/Input/TextField.ts

119 lines
3.5 KiB
TypeScript
Raw Normal View History

2020-07-01 00:12:33 +00:00
import {UIElement} from "../UIElement";
import {UIEventSource} from "../UIEventSource";
2020-07-20 13:54:50 +00:00
import {InputElement} from "./InputElement";
import {FixedUiElement} from "../Base/FixedUiElement";
2020-07-20 22:38:03 +00:00
import Translations from "../i18n/Translations";
2020-07-01 00:12:33 +00:00
2020-07-20 13:54:50 +00:00
export class TextField<T> extends InputElement<T> {
2020-07-01 00:12:33 +00:00
2020-07-20 11:28:45 +00:00
private value: UIEventSource<string>;
private mappedValue: UIEventSource<T>;
2020-07-01 00:12:33 +00:00
/**
* Pings and has the value data
*/
public enterPressed = new UIEventSource<string>(undefined);
2020-07-20 13:54:50 +00:00
private _placeholder: UIElement;
private _fromString?: (string: string) => T;
private _toString: (t: T) => string;
2020-07-01 00:12:33 +00:00
2020-07-20 11:28:45 +00:00
constructor(options: {
2020-07-20 13:54:50 +00:00
placeholder?: string | UIElement,
2020-07-20 16:24:00 +00:00
toString: (t: T) => string,
fromString: (string: string) => T,
2020-07-20 11:28:45 +00:00
value?: UIEventSource<T>
}) {
2020-07-20 13:54:50 +00:00
super(undefined);
2020-07-20 19:39:07 +00:00
const self = this;
2020-07-20 11:28:45 +00:00
this.value = new UIEventSource<string>("");
2020-07-20 19:39:07 +00:00
this.mappedValue = options?.value ?? new UIEventSource<T>(undefined);
this.mappedValue.addCallback(() => self.InnerUpdate());
2020-07-20 11:28:45 +00:00
2020-07-20 13:54:50 +00:00
// @ts-ignore
this._fromString = options.fromString ?? ((str) => (str))
2020-07-20 11:28:45 +00:00
this.value.addCallback((str) => this.mappedValue.setData(options.fromString(str)));
this.mappedValue.addCallback((t) => this.value.setData(options.toString(t)));
2020-07-20 22:38:03 +00:00
this._placeholder = Translations.W(options.placeholder ?? "");
this.ListenTo(this._placeholder._source);
2020-07-20 13:54:50 +00:00
this._toString = options.toString ?? ((t) => ("" + t));
2020-07-20 11:28:45 +00:00
this.mappedValue.addCallback((t) => {
2020-07-20 16:24:00 +00:00
if (t === undefined || t === null) {
2020-07-20 11:28:45 +00:00
return;
}
const field = document.getElementById('text-' + this.id);
2020-07-20 13:54:50 +00:00
if (field === undefined || field === null) {
2020-07-20 11:28:45 +00:00
return;
}
2020-07-20 13:54:50 +00:00
// @ts-ignore
2020-07-20 11:28:45 +00:00
field.value = options.toString(t);
})
2020-07-05 16:59:47 +00:00
}
GetValue(): UIEventSource<T> {
2020-07-20 11:28:45 +00:00
return this.mappedValue;
2020-07-01 00:12:33 +00:00
}
ShowValue(t: T): boolean {
if (!this.IsValid(t)) {
return false;
}
this.mappedValue.setData(t);
}
InnerRender(): string {
2020-07-20 13:54:50 +00:00
return "<form onSubmit='return false' class='form-text-field'>" +
"<input type='text' placeholder='" + this._placeholder.InnerRender() + "' id='text-" + this.id + "'>" +
2020-07-01 00:12:33 +00:00
"</form>";
}
2020-07-20 19:39:07 +00:00
InnerUpdate() {
2020-07-01 00:12:33 +00:00
const field = document.getElementById('text-' + this.id);
if (field === null) {
2020-07-20 13:54:50 +00:00
return;
}
2020-07-01 00:12:33 +00:00
const self = this;
field.oninput = () => {
2020-07-05 16:59:47 +00:00
// @ts-ignore
2020-07-01 00:12:33 +00:00
self.value.setData(field.value);
};
field.addEventListener("keyup", function (event) {
if (event.key === "Enter") {
2020-07-05 16:59:47 +00:00
// @ts-ignore
2020-07-01 00:12:33 +00:00
self.enterPressed.setData(field.value);
}
});
2020-07-05 16:59:47 +00:00
if (this.IsValid(this.mappedValue.data)) {
2020-07-20 19:39:07 +00:00
const expected = this._toString(this.mappedValue.data);
// @ts-ignore
2020-07-20 19:39:07 +00:00
if (field.value !== expected) {
// @ts-ignore
field.value = expected;
}
}
2020-07-05 16:59:47 +00:00
2020-07-01 00:12:33 +00:00
}
2020-07-20 13:54:50 +00: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 00:12:33 +00:00
Clear() {
const field = document.getElementById('text-' + this.id);
if (field !== undefined) {
2020-07-05 16:59:47 +00:00
// @ts-ignore
2020-07-01 00:12:33 +00:00
field.value = "";
}
}
}