vlw.se/assets/js/document.js
Victor Westerlund 140132fa72
feat: release 1.0.0 (#1)
* 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)
2024-04-01 10:22:25 +00:00

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 });
}