@virtualstate/app-history
Version:
Native JavaScript [app-history](https://github.com/WICG/app-history) implementation
163 lines (155 loc) • 5.61 kB
JavaScript
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