diff options
author | metamuffin <metamuffin@disroot.org> | 2023-10-24 07:40:51 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-10-24 07:40:51 +0200 |
commit | b462195f2dcfe457eae7791c14e4b834b2d5ab29 (patch) | |
tree | 492ba43952fa6798320f2b2bb4d4bd5484e2e4f2 /web/script/transition.ts | |
parent | 6e9ccad881a7f887599bc8f3f6b9ca2424a2cc5e (diff) | |
parent | 55f7f06cecd5b6f5661f6f22e8bb3e0448b9713a (diff) | |
download | jellything-b462195f2dcfe457eae7791c14e4b834b2d5ab29.tar jellything-b462195f2dcfe457eae7791c14e4b834b2d5ab29.tar.bz2 jellything-b462195f2dcfe457eae7791c14e4b834b2d5ab29.tar.zst |
Merge branch 'master' of codeberg.org:metamuffin/jellything
Diffstat (limited to 'web/script/transition.ts')
-rw-r--r-- | web/script/transition.ts | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/web/script/transition.ts b/web/script/transition.ts new file mode 100644 index 0000000..e0ee6f5 --- /dev/null +++ b/web/script/transition.ts @@ -0,0 +1,80 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2023 metamuffin <metamuffin.org> +*/ +/// <reference lib="dom" /> + +import { e } from "./jshelper/src/element.ts"; + +const duration = 200 +globalThis.addEventListener("DOMContentLoaded", () => { + patch_page() +}) + +globalThis.addEventListener("popstate", async (_e) => { + await transition_to(window.location.href, true) +}) + +let disable_transition = false +globalThis.addEventListener("navigationrequiresreload", () => { + disable_transition = true +}) + +function patch_page() { + document.querySelectorAll("a").forEach(el => { + el.addEventListener("click", async ev => { + ev.preventDefault() + await transition_to(el.href) + }) + }) +} + +async function transition_to(href: string, back?: boolean) { + if (disable_transition) return window.location.href = href + const trigger_load = prepare_load(href, back) + await fade(false) + trigger_load() + disable_transition = false; +} + +function show_error(mesg: string) { + document.body.append(e("span", { class: "jst-error" }, mesg)) +} + +function prepare_load(href: string, back?: boolean) { + const r_promise = fetch(href) + return async () => { + let rt = "" + try { + const r = await r_promise + if (!r.ok) return show_error("Error response. Try again.") + rt = await r.text() + } catch (e) { + if (e instanceof TypeError) return show_error("Navigation failed. Check your connection.") + return show_error("unknown error when fetching page") + } + const [head, body] = rt.split("<head>")[1].split("</head>") + if (!back) window.history.pushState({}, "", href) + document.head.innerHTML = head + document.body.outerHTML = body + globalThis.dispatchEvent(new Event("DOMContentLoaded")) + fade(true) + } +} + +function fade(dir: boolean) { + const overlay = document.createElement("div") + overlay.classList.add("jst-fade") + overlay.style.backgroundColor = dir ? "black" : "transparent" + overlay.style.animationName = dir ? "jst-fadeout" : "jst-fadein" + overlay.style.animationFillMode = "forwards" + overlay.style.animationDuration = `${duration}ms` + document.body.appendChild(overlay) + return new Promise<void>(res => { + setTimeout(() => { + if (dir) document.body.removeChild(overlay) + res() + }, duration) + }) +} |