Pax1601 2f125e3d0e Completed plugins framework
More work required to define all interfaces for the useful classes in the @types folder
2023-09-15 23:07:15 +02:00

176 lines
5.2 KiB
TypeScript

export class Dropdown {
#container: HTMLElement;
#options: HTMLElement;
#value: HTMLElement;
#callback: CallableFunction;
#defaultValue: string;
#optionsList: string[] = [];
#index: number = 0;
#hidden: boolean = false;
constructor(ID: string | null, callback: CallableFunction, options: string[] | null = null, defaultText?: string) {
if (ID === null)
this.#container = this.#createElement(defaultText);
else
this.#container = document.getElementById(ID) as HTMLElement;
this.#options = this.#container.querySelector(".ol-select-options") as HTMLElement;
this.#value = this.#container.querySelector(".ol-select-value") as HTMLElement;
this.#defaultValue = this.#value.innerText;
this.#callback = callback;
if (options != null) this.setOptions(options);
this.#value.addEventListener("click", (ev) => { this.#toggle(); });
document.addEventListener("click", (ev) => {
if (!(this.#value.contains(ev.target as Node) || this.#options.contains(ev.target as Node) || this.#container.contains(ev.target as Node))) {
this.close();
}
});
this.#options.classList.add("ol-scrollable");
}
getContainer() {
return this.#container;
}
setOptions(optionsList: string[], sortAlphabetically: boolean = true) {
this.#optionsList = optionsList.sort();
if (this.#optionsList.length == 0) {
optionsList = ["No options available"]
this.#value.innerText = "No options available";
}
this.#options.replaceChildren(...optionsList.map((option: string, idx: number) => {
var div = document.createElement("div");
var button = document.createElement("button");
button.textContent = option;
div.appendChild(button);
if (option === this.#defaultValue)
this.#index = idx;
button.addEventListener("click", (e: MouseEvent) => {
e.stopPropagation();
this.selectValue(idx);
});
return div;
}));
}
setOptionsElements(optionsElements: HTMLElement[]) {
this.#optionsList = [];
this.#options.replaceChildren(...optionsElements);
}
getOptionElements() {
return this.#options.children;
}
addOptionElement(optionElement: HTMLElement) {
this.#options.appendChild(optionElement);
}
selectText(text: string) {
const index = [].slice.call(this.#options.children).findIndex((opt: Element) => opt.querySelector("button")?.innerText === text);
if (index > -1) {
this.selectValue(index);
}
}
selectValue(idx: number) {
if (idx < this.#optionsList.length) {
var option = this.#optionsList[idx];
var el = document.createElement("div");
el.classList.add("ol-ellipsed");
el.innerText = option;
this.#value.replaceChildren();
this.#value.appendChild(el);
this.#index = idx;
this.close();
this.#callback(option);
return true;
}
else
return false;
}
reset() {
this.#options.replaceChildren();
this.#value.innerText = this.#defaultValue;
}
getValue() {
return this.#value.innerText;
}
setValue(value: string) {
var index = this.#optionsList.findIndex((option) => { return option === value });
if (index > -1)
this.selectValue(index);
}
forceValue(value: string) {
var el = document.createElement("div");
el.classList.add("ol-ellipsed");
el.innerText = value;
this.#value.replaceChildren();
this.#value.appendChild(el);
this.close();
}
getIndex() {
return this.#index;
}
clip() {
const options = this.#options;
const bounds = options.getBoundingClientRect();
this.#container.dataset.position = (bounds.bottom > window.innerHeight) ? "top" : "";
}
close() {
this.#container.classList.remove("is-open");
this.#container.dataset.position = "";
}
open() {
this.#container.classList.add("is-open");
this.#options.classList.toggle("scrollbar-visible", this.#options.scrollHeight > this.#options.clientHeight);
this.clip();
}
show() {
this.#container.classList.remove("hide");
this.#hidden = false;
}
hide() {
this.#container.classList.add("hide");
this.#hidden = true;
}
isHidden() {
return this.#hidden;
}
#toggle() {
this.#container.classList.contains("is-open")? this.close(): this.open();
}
#createElement(defaultText: string | undefined) {
var div = document.createElement("div");
div.classList.add("ol-select");
var value = document.createElement("div");
value.classList.add("ol-select-value");
value.innerText = defaultText? defaultText: "";
var options = document.createElement("div");
options.classList.add("ol-select-options");
div.append(value, options);
return div;
}
}