111 lines
4.1 KiB
JavaScript
111 lines
4.1 KiB
JavaScript
// delete confirmation dialog and attachment to elements
|
|
const fireConfirmModal = (event) => {
|
|
Swal.fire({ title: 'Wirklich löschen?', showCancelButton: true, cancelButtonText: 'Abbrechen', icon: 'warning', confirmButtonText: "Löschen", showCloseButton: true })
|
|
.then((result) => { if (result.isConfirmed) { htmx.trigger(event.target, 'confirmed'); } });
|
|
}
|
|
|
|
|
|
document.querySelectorAll("button[hx-trigger='confirmed']").forEach((value) => value.addEventListener("click", fireConfirmModal));
|
|
|
|
document.addEventListener("htmx:afterSwap", () => {
|
|
document.querySelectorAll("button[hx-trigger='confirmed']").forEach((value) => value.addEventListener("click", fireConfirmModal));
|
|
});
|
|
|
|
// dropdown activation / deactivation
|
|
const toggleDropdown = (event) => {
|
|
const classList = event.target.closest('.dropdown').classList
|
|
if (!classList.contains('is-active')) {
|
|
Array.from(document.querySelectorAll('.dropdown')).forEach((d) => d.classList.remove('is-active'));
|
|
}
|
|
classList.toggle('is-active');
|
|
};
|
|
|
|
const closeDropdownsIfClickedOutside = (event) => {
|
|
const dropdowns = Array.from(document.querySelectorAll('.dropdown'));
|
|
if (dropdowns.every((v) => !v.contains(event.target))) {
|
|
dropdowns.forEach((d) => d.classList.remove('is-active'))
|
|
}
|
|
}
|
|
|
|
document.querySelectorAll(".dropdown-trigger .button").forEach((value) => value.addEventListener("click", toggleDropdown));
|
|
document.addEventListener("click", closeDropdownsIfClickedOutside);
|
|
|
|
document.addEventListener("htmx:afterSwap", () => {
|
|
document.querySelectorAll(".dropdown-trigger .button").forEach((value) => value.addEventListener("click", toggleDropdown));
|
|
document.addEventListener("click", closeDropdownsIfClickedOutside);
|
|
});
|
|
|
|
// light / dark mode interpretation for first load and switch behaviour respecting localStorage and CSS prefers-color-scheme
|
|
const getCurrentTheme = () => {
|
|
let current = localStorage.getItem("theme");
|
|
|
|
if (current === null) {
|
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
current = "dark";
|
|
} else {
|
|
current = "light";
|
|
}
|
|
}
|
|
|
|
return current;
|
|
}
|
|
|
|
const setThemeSwitcherIconTo = (name) =>
|
|
document.querySelector("#theme-switcher use")?.setAttribute("href", `/static/feather-sprite.svg#${name}`)
|
|
|
|
const switchTheme = () => {
|
|
const currentTheme = getCurrentTheme();
|
|
const newTheme = currentTheme === "light" ? "dark" : "light";
|
|
const newIcon = currentTheme === "light" ? "sun" : "moon";
|
|
|
|
document.documentElement.setAttribute("data-theme", newTheme);
|
|
setThemeSwitcherIconTo(newIcon);
|
|
localStorage.setItem("theme", newTheme);
|
|
}
|
|
|
|
const observer = new MutationObserver((mutationList) => {
|
|
const foundNavbar = mutationList.flatMap((record) => Array.from(record.addedNodes))
|
|
.some((node) => node.className?.includes("navbar"));
|
|
|
|
if (foundNavbar) {
|
|
document.getElementById("theme-switcher")?.addEventListener("click", switchTheme);
|
|
setThemeSwitcherIconTo(getCurrentTheme() === "light" ? "moon" : "sun");
|
|
}
|
|
});
|
|
|
|
observer.observe(document, { childList: true, subtree: true });
|
|
|
|
const isCurrentlyLight = getCurrentTheme() === "light";
|
|
document.documentElement.setAttribute("data-theme", isCurrentlyLight ? "light" : "dark");
|
|
document.getElementById("theme-switcher")?.addEventListener("click", switchTheme);
|
|
setThemeSwitcherIconTo(isCurrentlyLight ? "moon" : "sun");
|
|
|
|
// toast
|
|
htmx.on("showToast", (e) => {
|
|
const toast = document.getElementById("toast");
|
|
const toastProgress = document.getElementById("toast-progress");
|
|
document.getElementById("toast-message").innerText = e.detail.message;
|
|
|
|
toast.classList.add(`is-${e.detail.type}`);
|
|
toastProgress.classList.add(`has-background-${e.detail.type}-90`)
|
|
toast.classList.remove("is-hidden");
|
|
|
|
setTimeout(() => {
|
|
toast.classList.add("is-hidden");
|
|
toast.classList.remove(`is-${e.detail.type}`);
|
|
toastProgress.classList.remove(`has-background-${e.detail.type}-90`)
|
|
}, 3000);
|
|
})
|
|
|
|
const convertBool = (val) => {
|
|
if (val === "true" || val === true) return true;
|
|
if (val === "false" || val === false) return false;
|
|
return null;
|
|
}
|
|
|
|
_hyperscript.config.conversions["bool"] = convertBool;
|
|
|
|
_hyperscript.config.conversions["inverseBool"] = function(val) {
|
|
return !convertBool(val);
|
|
};
|