UNPKG

@virtualstate/app-history

Version:

Native JavaScript [app-history](https://github.com/WICG/app-history) implementation

163 lines (155 loc) 5.61 kB
import { fetch } from "./fetch.js"; import { addEventListener } from "../../event-target/global.js"; import { Response } from "@opennetwork/http-representation"; import { ok } from "../util.js"; import { v4 } from "../../util/uuid-or-random.js"; import { parseDOM } from "../../util/parse-dom.js"; const SUBPAGE_MARKER = v4(); export async function demo1(appHistory) { addSubpageEventListener(); let delayChecked = false; const elements = { "#add-delay": { ...createElement("button"), get checked() { return delayChecked; } }, "main": { ...createElement("main"), replaceWith(element) { elements["main"] = { ...element, replaceWith: this.replaceWith }; } } }; const document = { querySelector(query) { return elements[query]; }, body: { children: [ createElement("p") ] }, createElement, documentTransition: { start() { } }, title: "" }; function createElement(localName) { return { localName, textContent: "", innerHTML: "", style: { contain: "" }, replaceWith(element) { } }; } // const useSET = document.querySelector("#use-set"); // if (!document.documentTransition) { // useSET.checked = false; // } const addDelay = document.querySelector("#add-delay"); const sharedElements = [...document.body.children].filter(el => el.localName !== "main"); for (const el of sharedElements) { el.style.contain = "paint"; } appHistory.addEventListener("navigateerror", console.error); appHistory.addEventListener("navigate", e => { console.log(e); if (!e.canTransition || e.hashChange) { return; } e.transitionWhile((async () => { e.signal.addEventListener("abort", () => { // console.log(e.signal); const newMain = document.createElement("main"); newMain.textContent = "You pressed the browser stop button!"; document.querySelector("main").replaceWith(newMain); console.log("Hello?"); }); if (addDelay.checked) { await delay(2_000, { signal: e.signal }); } // if (useSET.checked) { // await document.documentTransition.prepare({ // rootTransition: getTransition(e), // sharedElements // }); // document.documentTransition.start({ sharedElements }); // } const body = await (await fetch(e.destination.url, { signal: e.signal })).text(); const { title, main } = await getResult(body); document.title = title; document.querySelector("main").replaceWith(main); // if (useSET.checked) { // await document.documentTransition.start(); // } })()); }); async function getResult(htmlString) { const { innerHTML, title } = await parseDOM(htmlString, "main"); const main = createElement("main"); main.innerHTML = innerHTML; return { title, main }; } // function getTransition(e) { // if (e.navigationType === "reload" || e.navigationType === "replace") { // return "explode"; // } // if (e.navigationType === "traverse" && e.destination.index < appHistory.current.index) { // return "reveal-right"; // } // return "reveal-left"; // } function delay(ms, event) { return new Promise((resolve, reject) => { setTimeout(resolve, ms); event?.signal?.addEventListener("abort", reject); }); } await appHistory.navigate("subpage.html").finished; const main = document.querySelector("main"); ok(main); ok(main.innerHTML); // console.log(main.innerHTML); ok(main.innerHTML.includes(SUBPAGE_MARKER)); } function addSubpageEventListener() { addEventListener("fetch", (event) => { const { pathname } = new URL(event.request.url); if (pathname !== "/subpage.html") return; return event.respondWith(new Response(` <!DOCTYPE html> <html lang="en"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>App history demo: subpage</title> <link rel="stylesheet" href="style.css"> <h1><a href="https://github.com/WICG/app-history/">App history</a> demo</h1> <main> <p>I am <code>subpage.html</code>!</p> <p>You can use either your browser back button, or the following link, to go back to index.html. Either will perform a single-page navigation, in browsers that support app history!</p> <p><a href="/">Back to index.html</a>.</p> <p><button onclick="history.back()">history.back()</button></p> <p>Page id: ${SUBPAGE_MARKER}</p> </main> <p>If you see this, you did a normal multi-page navigation, not an app history-mediated single-page navigation.</p> <footer><a href="https://glitch.com/edit/#!/gigantic-honored-octagon?path=index.html">View source and edit on Glitch</a></footer> `, { status: 200, headers: { 'Content-Type': 'text/html' } })); }); } //# sourceMappingURL=demo-1.js.map