2020-07-20 21:39:07 +02:00
|
|
|
import { InputElement } from "./InputElement"
|
2020-07-21 00:38:03 +02:00
|
|
|
import Translations from "../i18n/Translations"
|
2020-08-17 17:23:15 +02:00
|
|
|
import { UIEventSource } from "../../Logic/UIEventSource"
|
2021-06-10 01:36:20 +02:00
|
|
|
import BaseUIElement from "../BaseUIElement"
|
2020-06-28 00:06:23 +02:00
|
|
|
|
2020-07-20 21:39:07 +02:00
|
|
|
export class DropDown<T> extends InputElement<T> {
|
2021-06-10 01:36:20 +02:00
|
|
|
private static _nextDropdownId = 0
|
|
|
|
public IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false)
|
2020-06-28 00:06:23 +02:00
|
|
|
|
2021-06-10 01:36:20 +02:00
|
|
|
private readonly _element: HTMLElement
|
2020-06-28 00:06:23 +02:00
|
|
|
|
2021-06-10 01:36:20 +02:00
|
|
|
private readonly _value: UIEventSource<T>
|
|
|
|
private readonly _values: { value: T; shown: string | BaseUIElement }[]
|
2020-07-20 21:39:07 +02:00
|
|
|
|
2022-07-20 19:35:08 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* const dropdown = new DropDown<number>("test",[{value: 42, shown: "the answer"}])
|
|
|
|
* dropdown.GetValue().data // => 42
|
|
|
|
*/
|
2021-06-10 01:36:20 +02:00
|
|
|
constructor(
|
|
|
|
label: string | BaseUIElement,
|
|
|
|
values: { value: T; shown: string | BaseUIElement }[],
|
2021-01-17 21:06:54 +01:00
|
|
|
value: UIEventSource<T> = undefined,
|
2021-06-10 01:36:20 +02:00
|
|
|
options?: {
|
|
|
|
select_class?: string
|
2020-07-20 21:39:07 +02:00
|
|
|
}
|
2021-06-10 01:36:20 +02:00
|
|
|
) {
|
|
|
|
super()
|
2022-07-20 19:35:08 +02:00
|
|
|
value = value ?? new UIEventSource<T>(values[0].value)
|
2021-06-15 16:18:58 +02:00
|
|
|
this._value = value
|
2021-06-12 02:58:32 +02:00
|
|
|
this._values = values
|
2021-06-10 01:36:20 +02:00
|
|
|
if (values.length <= 1) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
const id = DropDown._nextDropdownId
|
|
|
|
DropDown._nextDropdownId++
|
|
|
|
|
|
|
|
const el = document.createElement("form")
|
|
|
|
this._element = el
|
|
|
|
el.id = "dropdown" + id
|
|
|
|
|
|
|
|
{
|
2022-01-19 20:34:04 +01:00
|
|
|
const labelEl = Translations.W(label)?.ConstructElement()
|
2021-06-12 02:58:32 +02:00
|
|
|
if (labelEl !== undefined) {
|
|
|
|
const labelHtml = document.createElement("label")
|
|
|
|
labelHtml.appendChild(labelEl)
|
|
|
|
labelHtml.htmlFor = el.id
|
2021-06-13 15:04:55 +02:00
|
|
|
el.appendChild(labelHtml)
|
2021-06-12 02:58:32 +02:00
|
|
|
}
|
2021-06-10 01:36:20 +02:00
|
|
|
}
|
2021-06-15 16:18:58 +02:00
|
|
|
|
2021-06-14 17:42:26 +02:00
|
|
|
options = options ?? {}
|
2022-04-19 23:43:28 +02:00
|
|
|
options.select_class =
|
|
|
|
options.select_class ?? "w-full bg-indigo-100 p-1 rounded hover:bg-indigo-200"
|
2021-06-10 01:36:20 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
const select = document.createElement("select")
|
2021-06-14 17:42:26 +02:00
|
|
|
select.classList.add(...(options.select_class.split(" ") ?? []))
|
2021-06-10 01:36:20 +02:00
|
|
|
for (let i = 0; i < values.length; i++) {
|
|
|
|
const option = document.createElement("option")
|
|
|
|
option.value = "" + i
|
|
|
|
option.appendChild(Translations.W(values[i].shown).ConstructElement())
|
2021-06-13 15:04:55 +02:00
|
|
|
select.appendChild(option)
|
2020-07-20 21:39:07 +02:00
|
|
|
}
|
2021-06-13 15:04:55 +02:00
|
|
|
el.appendChild(select)
|
|
|
|
|
2021-06-10 01:36:20 +02:00
|
|
|
select.onchange = () => {
|
2022-07-20 19:35:08 +02:00
|
|
|
const index = select.selectedIndex
|
2021-06-10 01:36:20 +02:00
|
|
|
value.setData(values[index].value)
|
2022-09-08 21:40:48 +02:00
|
|
|
}
|
2021-06-10 01:36:20 +02:00
|
|
|
|
|
|
|
value.addCallbackAndRun((selected) => {
|
|
|
|
for (let i = 0; i < values.length; i++) {
|
|
|
|
const value = values[i].value
|
|
|
|
if (value === selected) {
|
|
|
|
select.selectedIndex = i
|
|
|
|
}
|
2021-06-12 02:58:32 +02:00
|
|
|
}
|
2021-06-10 01:36:20 +02:00
|
|
|
})
|
2020-07-21 00:38:03 +02:00
|
|
|
}
|
2020-07-20 21:39:07 +02:00
|
|
|
|
2021-06-10 01:36:20 +02:00
|
|
|
this.onClick(() => {}) // by registering a click, the click event is consumed and doesn't bubble further to other elements, e.g. checkboxes
|
2020-06-28 00:06:23 +02:00
|
|
|
}
|
|
|
|
|
2020-07-20 21:39:07 +02:00
|
|
|
GetValue(): UIEventSource<T> {
|
|
|
|
return this._value
|
|
|
|
}
|
2021-06-10 01:36:20 +02:00
|
|
|
|
2020-07-20 21:39:07 +02:00
|
|
|
IsValid(t: T): boolean {
|
2020-06-28 00:06:23 +02:00
|
|
|
for (const value of this._values) {
|
2020-07-20 21:39:07 +02:00
|
|
|
if (value.value === t) {
|
|
|
|
return true
|
|
|
|
}
|
2020-06-28 00:06:23 +02:00
|
|
|
}
|
2020-07-20 21:39:07 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-06-10 01:36:20 +02:00
|
|
|
protected InnerConstructElement(): HTMLElement {
|
|
|
|
return this._element
|
2020-06-28 00:06:23 +02:00
|
|
|
}
|
|
|
|
}
|