mirror of
https://codeberg.org/vlw/vlw.se.git
synced 2025-09-13 21:13:40 +02:00

* wip: 2024-02-13T12:59:17+0100 (1707825557) * wip: 2024-02-21T03:16:48+0100 (1708481808) * wip: 2024-02-21T20:50:20+0100 (1708545020) * wip: 2024-02-21T20:50:20+0100 (1708545020) * wip: 2024-03-01T13:17:58+0100 (1709295478) * wip: 2024-03-06T12:06:58+0100 (1709723218) * wip: 2024-03-07T15:07:57+0100 (1709820477) * wip: 2024-03-09T01:36:44+0100 (1709944604) * wip: 2024-03-14T23:24:12+0100 (1710455052) * wip: 2024-03-28T18:27:40+0100 (1711646860) * wip: 2024-03-28T18:27:40+0100 (1711646860) * feat: create README * wip: 2024-04-01T12:21:45+0200 (1711966905)
72 lines
No EOL
2.5 KiB
JavaScript
Executable file
72 lines
No EOL
2.5 KiB
JavaScript
Executable file
new vv.Interactions("document");
|
|
|
|
const mainElement = document.querySelector(vv._env.MAIN);
|
|
|
|
// Crossfade pages on navigation
|
|
// Or maybe I shouldn't... hmmm
|
|
mainElement.addEventListener(vv.Navigation.events.LOADING, () => {
|
|
mainElement.classList.add("loading");
|
|
|
|
// Clean up modified transform-origin if set after search dialog animation
|
|
mainElement.style.removeProperty("transform-origin");
|
|
});
|
|
|
|
mainElement.addEventListener(vv.Navigation.events.LOADED, () => {
|
|
[...document.querySelectorAll("dialog")].forEach(element => element.close())
|
|
|
|
// Wait 200ms for the page fade-in animation to finish
|
|
setTimeout(() => mainElement.classList.remove("loading"), 200);
|
|
});
|
|
|
|
// Search dialog open/close logic
|
|
{
|
|
const CLASNAME_DIALOG_OPEN = "search-dialog-open";
|
|
// Offset in pixels from scroll position when scaling the main element
|
|
const TRANSFORM_ORIGIN_Y_PADDING = 350;
|
|
|
|
const dialog = document.querySelector("dialog.search");
|
|
|
|
// "Polyfill" for HTMLDialogELement open and close events
|
|
(new MutationObserver((mutations) => {
|
|
// There is only one search dialog elemenet
|
|
const target = mutations[0].target;
|
|
|
|
// Set or unset dialog open class on body depending on dialog visibility
|
|
target.hasAttribute("open")
|
|
? target.dispatchEvent(new Event("open"))
|
|
: target.dispatchEvent(new Event("close"));
|
|
|
|
}).observe(dialog, { attributes: true }));
|
|
|
|
dialog.addEventListener("open", () => {
|
|
// Scale main element from the current scroll position
|
|
mainElement.style.setProperty("transform-origin", `50% calc(${window.scrollY}px + ${TRANSFORM_ORIGIN_Y_PADDING}px)`);
|
|
|
|
document.body.classList.add(CLASNAME_DIALOG_OPEN);
|
|
});
|
|
dialog.addEventListener("close", () => document.body.classList.remove(CLASNAME_DIALOG_OPEN));
|
|
|
|
// Close search dialog if dialog is clicked outside inner content
|
|
dialog.addEventListener("click", (event) => event.target === dialog ? dialog.close() : null);
|
|
|
|
// Open search dialog when searchbox is clicked
|
|
document.querySelector("searchbox").addEventListener("click", () => dialog.showModal());
|
|
}
|
|
|
|
// Search logic
|
|
{
|
|
const searchResultsElement = document.querySelector("search-results");
|
|
const search = (query) => {
|
|
new vv.Navigation(`/search?q=${query}`, {
|
|
carrySearchParams: true
|
|
}).navigate(searchResultsElement);
|
|
};
|
|
|
|
// Run search on keyup
|
|
document.querySelector("search input").addEventListener("keyup", (event) => search(event.target.value));
|
|
|
|
// Trigger expand search box animation
|
|
document.querySelector("search input").addEventListener("keydown", () => {
|
|
searchResultsElement.closest("dialog").classList.add("active");
|
|
}, { once: true });
|
|
} |