mapcomplete/UI/Input/DropDown.ts

98 lines
2.8 KiB
TypeScript
Raw Normal View History

2020-06-29 03:12:44 +02:00
import {UIEventSource} from "../UIEventSource";
import {UIElement} from "../UIElement";
2020-07-20 21:39:07 +02:00
import {InputElement} from "./InputElement";
import instantiate = WebAssembly.instantiate;
import {FixedUiElement} from "../Base/FixedUiElement";
2020-07-21 00:38:03 +02:00
import Translations from "../i18n/Translations";
2020-07-20 21:39:07 +02:00
export class DropDown<T> extends InputElement<T> {
2020-07-21 00:38:03 +02:00
private readonly _label: UIElement;
2020-07-20 21:39:07 +02:00
private readonly _values: { value: T; shown: UIElement }[];
private readonly _value : UIEventSource<T>;
2020-07-20 21:39:07 +02:00
2020-07-21 00:38:03 +02:00
constructor(label: string | UIElement,
2020-07-20 21:39:07 +02:00
values: { value: T, shown: string | UIElement }[],
value: UIEventSource<T> = undefined) {
super(undefined);
2020-07-20 21:39:07 +02:00
this._value = value ?? new UIEventSource<T>(undefined);
2020-07-21 00:38:03 +02:00
this._label = Translations.W(label);
2020-07-20 21:39:07 +02:00
this._values = values.map(v => {
return {
value: v.value,
2020-07-21 00:38:03 +02:00
shown: Translations.W(v.shown)
2020-07-20 21:39:07 +02:00
}
}
);
2020-07-21 00:38:03 +02:00
for (const v of this._values) {
this.ListenTo(v.shown._source);
}
2020-07-22 16:44:07 +02:00
this.ListenTo(this._value);
this.onClick(() => {}) // by registering a click, the click event is consumed and doesn't bubble furter to other elements, e.g. checkboxes
2020-07-20 21:39:07 +02:00
}
2020-07-20 21:39:07 +02:00
GetValue(): UIEventSource<T> {
return this._value;
}
2020-07-20 21:39:07 +02:00
ShowValue(t: T): boolean {
if (!this.IsValid(t)) {
return false;
}
this._value.setData(t);
}
2020-07-20 21:39:07 +02:00
IsValid(t: T): boolean {
for (const value of this._values) {
2020-07-20 21:39:07 +02:00
if (value.value === t) {
return true;
}
}
2020-07-20 21:39:07 +02:00
return false
}
InnerRender(): string {
2020-07-21 00:07:04 +02:00
if(this._values.length <=1){
return "";
}
2020-07-20 21:39:07 +02:00
let options = "";
for (let i = 0; i < this._values.length; i++) {
options += "<option value='" + i + "'>" + this._values[i].shown.InnerRender() + "</option>"
}
2020-07-23 16:00:49 +02:00
return "<form>" +
2020-07-21 00:38:03 +02:00
"<label for='dropdown-" + this.id + "'>" + this._label.Render() + "</label>" +
"<select name='dropdown-" + this.id + "' id='dropdown-" + this.id + "'>" +
options +
"</select>" +
"</form>";
}
2020-07-20 21:39:07 +02:00
protected InnerUpdate(element) {
var e = document.getElementById("dropdown-" + this.id);
2020-07-21 00:07:04 +02:00
if(e === null){
return;
}
const self = this;
2020-07-20 21:39:07 +02:00
e.onchange = (() => {
// @ts-ignore
2020-07-20 21:39:07 +02:00
var index = parseInt(e.selectedIndex);
self._value.setData(self._values[index].value);
});
var t = this._value.data;
for (let i = 0; i < this._values.length ; i++) {
const value = this._values[i].value;
if (value === t) {
2020-07-20 21:39:07 +02:00
// @ts-ignore
e.selectedIndex = i;
}
}
}
}