1
0
mirror of https://github.com/coalaura/whiskr.git synced 2025-09-09 09:19:54 +00:00
Files
whiskr/static/js/dropdown.js

124 lines
2.3 KiB
JavaScript
Raw Normal View History

2025-08-09 21:16:24 +02:00
(() => {
class Dropdown {
#_select;
#_dropdown;
#_selected;
#selected = false;
#options = [];
constructor(el) {
this.#_select = el;
this.#_select.querySelectorAll("option").forEach((option) => {
this.#options.push({
value: option.value,
label: option.textContent.trim(),
});
});
this.#build();
if (this.#options.length) {
this.#set(this.#options[0].value);
}
}
#build() {
// prepare and hide original select
this.#_select.style.display = "none";
const descriptor = Object.getOwnPropertyDescriptor(
HTMLSelectElement.prototype,
"value",
);
Object.defineProperty(this.#_select, "value", {
get: () => {
return descriptor.get.call(this.#_select);
},
set: (value) => {
descriptor.set.call(this.#_select, value);
this.#set(value);
},
});
// dropdown
this.#_dropdown = make("div", "dropdown");
this.#_dropdown.addEventListener("click", () => {
this.#_dropdown.classList.add("open");
});
// selected item
this.#_selected = make("div", "selected");
this.#_dropdown.appendChild(this.#_selected);
// option wrapper
const _options = make("div", "options");
this.#_dropdown.appendChild(_options);
// options
for (const option of this.#options) {
const _opt = make("div", "option");
_opt.textContent = option.label;
_opt.addEventListener("click", () => {
this.#set(option.value);
});
option.el = _opt;
}
// add to dom
this.#_select.after(this.#_dropdown);
this.#render();
}
#render() {
if (this.#selected === false) {
this.#_selected.textContent = "";
return;
}
const selection = this.#options[this.#selected];
this.#_selected.textContent = selection.label;
}
#set(value) {
console.log("value", value);
const index = this.#options.findIndex((option) => option.value === value);
if (this.#selected === index) {
return;
}
this.#selected = index !== -1 ? index : false;
this.#render();
}
}
document.body.addEventListener("click", (event) => {
const clicked = event.target.closest(".dropdown");
document.querySelectorAll(".dropdown").forEach((element) => {
if (element === clicked) {
return;
}
element.classList.remove("open");
});
});
window.dropdown = (el) => new Dropdown(el);
})();