forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			102 lines
		
	
	
		
			No EOL
		
	
	
		
			3.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			102 lines
		
	
	
		
			No EOL
		
	
	
		
			3.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import {InputElement} from "./InputElement";
 | 
						|
import Translations from "../i18n/Translations";
 | 
						|
import {UIEventSource} from "../../Logic/UIEventSource";
 | 
						|
import BaseUIElement from "../BaseUIElement";
 | 
						|
 | 
						|
export class DropDown<T> extends InputElement<T> {
 | 
						|
 | 
						|
    private static _nextDropdownId = 0;
 | 
						|
    public IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
						|
 | 
						|
    private readonly _element: HTMLElement;
 | 
						|
 | 
						|
    private readonly _value: UIEventSource<T>;
 | 
						|
    private readonly _values: { value: T; shown: string | BaseUIElement }[];
 | 
						|
 | 
						|
    constructor(label: string | BaseUIElement,
 | 
						|
                values: { value: T, shown: string | BaseUIElement }[],
 | 
						|
                value: UIEventSource<T> = undefined,
 | 
						|
                options?: {
 | 
						|
                    select_class?: string
 | 
						|
                }
 | 
						|
    ) {
 | 
						|
        super();
 | 
						|
        value = value ?? new UIEventSource<T>(undefined)
 | 
						|
        this._value = value
 | 
						|
        this._values = values;
 | 
						|
        if (values.length <= 1) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        const id = DropDown._nextDropdownId;
 | 
						|
        DropDown._nextDropdownId++;
 | 
						|
 | 
						|
 | 
						|
        const el = document.createElement("form")
 | 
						|
        this._element = el;
 | 
						|
        el.id = "dropdown" + id;
 | 
						|
 | 
						|
        {
 | 
						|
            const labelEl = Translations.W(label)?.ConstructElement()
 | 
						|
            if (labelEl !== undefined) {
 | 
						|
                const labelHtml = document.createElement("label")
 | 
						|
                labelHtml.appendChild(labelEl)
 | 
						|
                labelHtml.htmlFor = el.id;
 | 
						|
                el.appendChild(labelHtml)
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        options = options ?? {}
 | 
						|
        options.select_class = options.select_class ?? 'w-full bg-indigo-100 p-1 rounded hover:bg-indigo-200'
 | 
						|
 | 
						|
 | 
						|
        {
 | 
						|
            const select = document.createElement("select")
 | 
						|
            select.classList.add(...(options.select_class.split(" ") ?? []))
 | 
						|
            for (let i = 0; i < values.length; i++) {
 | 
						|
                const option = document.createElement("option")
 | 
						|
                option.value = "" + i
 | 
						|
                option.appendChild(Translations.W(values[i].shown).ConstructElement())
 | 
						|
                select.appendChild(option)
 | 
						|
            }
 | 
						|
            el.appendChild(select)
 | 
						|
 | 
						|
 | 
						|
            select.onchange = (() => {
 | 
						|
                var index = select.selectedIndex;
 | 
						|
                value.setData(values[index].value);
 | 
						|
            });
 | 
						|
 | 
						|
            value.addCallbackAndRun(selected => {
 | 
						|
                for (let i = 0; i < values.length; i++) {
 | 
						|
                    const value = values[i].value;
 | 
						|
                    if (value === selected) {
 | 
						|
                        select.selectedIndex = i;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            })
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        this.onClick(() => {
 | 
						|
        }) // by registering a click, the click event is consumed and doesn't bubble further to other elements, e.g. checkboxes
 | 
						|
    }
 | 
						|
 | 
						|
    GetValue(): UIEventSource<T> {
 | 
						|
        return this._value;
 | 
						|
    }
 | 
						|
 | 
						|
    IsValid(t: T): boolean {
 | 
						|
        for (const value of this._values) {
 | 
						|
            if (value.value === t) {
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return false
 | 
						|
    }
 | 
						|
 | 
						|
    protected InnerConstructElement(): HTMLElement {
 | 
						|
        return this._element;
 | 
						|
    }
 | 
						|
 | 
						|
} |