site.lyte.dev/static/preload.mjs

88 lines
2.4 KiB
JavaScript

const cache = {}
const main = document.querySelector("html > body > main")
const originalMain = main.innerHTML
cache[window.location.href] = [originalMain, document.title]
history.replaceState([window.location.href, 0, 0], "")
const MINUTE_MS = 1000 * 60
async function putCache(href) {
if (cache[href] === undefined && href != window.location.href) {
cache[href] = ["", ""]
console.debug(`Preloading ${href}...`)
const html = await (await fetch(href)).text()
const doc = new DOMParser().parseFromString(html, "text/html")
cache[href] = [doc.querySelector("html > body > main").innerHTML, doc.title]
console.debug(`Preloaded ${href}`)
setTimeout(() => {
delete cache[href]
console.debug(`Cleared cached page: ${href}`)
}, 5 * MINUTE_MS)
}
}
function loadCache(href) {
if (cache[href]) {
const [html, title] = cache[href]
if (html != "" || title != "") {
main.innerHTML = html
document.title = title
return true
}
}
return false
}
function preloadinate() {
// TODO: some kind of expiration?
document.querySelectorAll("a").forEach(el => {
// TODO: this would ideally happen in the background (service worker)?
if (el.href.indexOf("#") == -1 && el.href.indexOf(".") == -1 && (el.href.startsWith("https://lyte.dev") || el.href.startsWith("http://localhost:1313"))) {
const router = async function(ev) {
if (el.href == window.location.href) {
ev.preventDefault()
return false
}
if (cache[el.href] && cache[el.href][0] != "") {
const rep = [window.location.href, window.scrollX, window.scrollY]
history.replaceState(rep, "")
console.log("replaceState: ", rep)
if (!loadCache(el.href)) {
window.location.href = el.href
window.location.reload()
return true
}
window.scrollTo(0, 0)
history.pushState([el.href, 0, 0], "", el.href)
preloadinate()
ev.preventDefault()
return false
} else {
ev.preventDefault()
await putCache(el.href)
return router(ev)
}
}
el.addEventListener("mouseover", (_ev) => putCache(el.href))
el.addEventListener("click", router)
}
})
}
window.addEventListener("popstate", ev => {
if (ev.state) {
const [href, x, y] = ev.state
if (!loadCache(href)) {
window.location.reload()
}
requestAnimationFrame(() => {
console.log(`Scrolling to ${x}, ${y}`)
window.scrollTo(x, y)
})
preloadinate()
} else {
}
})
window.addEventListener("load", preloadinate);