aboutsummaryrefslogtreecommitdiff
path: root/assets
diff options
context:
space:
mode:
authortdro <tdro@noreply.example.com>2024-02-12 20:15:17 -0500
committertdro <tdro@noreply.example.com>2024-02-12 20:15:17 -0500
commitd23d5bc6dae8035357f1dea088392ab3d2546f8e (patch)
treeb050a87ebf4f073aa2bc8c5b08c2735039994dc0 /assets
parentb541593793efc19639835200f185d273620770e6 (diff)
downloadcanory-d23d5bc6dae8035357f1dea088392ab3d2546f8e.tar.gz
canory-d23d5bc6dae8035357f1dea088392ab3d2546f8e.tar.bz2
canory-d23d5bc6dae8035357f1dea088392ab3d2546f8e.zip
static/js: Add custom DOM filter
Fallback to native navigation if transition in 300ms is not guaranteed
Diffstat (limited to 'assets')
-rw-r--r--assets/js/index.js102
1 files changed, 102 insertions, 0 deletions
diff --git a/assets/js/index.js b/assets/js/index.js
index 91d3e61..15f720a 100644
--- a/assets/js/index.js
+++ b/assets/js/index.js
@@ -752,6 +752,108 @@
});
})();
(function() {
+ const timeout = 300;
+ const state = "on";
+ const key = "config.speed.fast";
+ function fetch(url, method, callback) {
+ const http = new XMLHttpRequest();
+ http.onreadystatechange = function() {
+ if (callback && http.readyState === 4) {
+ if (http.status === 200) callback(http);
+ else {
+ console.error("ERROR: Unable to navigate", http);
+ self.location.href = url;
+ }
+ }
+ };
+ http.open(method, url);
+ http.timeout = timeout;
+ http.send();
+ return http;
+ }
+ function styles(node) {
+ return node.nodeName === "LINK" && node.rel && node.rel.includes("stylesheet");
+ }
+ function scripts(node) {
+ return node.nodeName === "SCRIPT" && node.hasAttribute("src");
+ }
+ function filter(url, http) {
+ let live = document;
+ let node = live.head.childNodes.length;
+ let next = new DOMParser().parseFromString(http.responseText, "text/html");
+ if (next.doctype === null || !http.getResponseHeader("content-type").includes("text/html")) return false;
+ while(node--){
+ if (styles(live.head.childNodes[node]) || scripts(live.head.childNodes[node])) {} else {
+ live.head.removeChild(live.head.childNodes[node]);
+ }
+ }
+ while(next.head.firstChild){
+ if (styles(next.head.firstChild) || scripts(next.head.firstChild)) {
+ next.head.removeChild(next.head.firstChild);
+ } else {
+ live.head.appendChild(next.head.firstChild);
+ }
+ }
+ while(live.documentElement.attributes.length > 0){
+ live.documentElement.removeAttribute(live.documentElement.attributes[live.documentElement.attributes.length - 1].name);
+ }
+ while(next.documentElement.attributes.length > 0){
+ live.documentElement.setAttribute(next.documentElement.attributes[next.documentElement.attributes.length - 1].name, next.documentElement.attributes[next.documentElement.attributes.length - 1].value);
+ next.documentElement.removeAttribute(next.documentElement.attributes[next.documentElement.attributes.length - 1].name);
+ }
+ live.body.parentElement.replaceChild(next.body, live.body);
+ }
+ function persist() {
+ let persist = document.createElement("link");
+ persist.rel = "location";
+ persist.target = JSON.stringify(self.location);
+ document.head.appendChild(persist);
+ }
+ self.addEventListener("DOMContentLoaded", function() {
+ if (localStorage[key] !== state) return;
+ persist();
+ });
+ self.addEventListener("popstate", function(event) {
+ if (localStorage[key] !== state) return;
+ const link = JSON.parse(document.querySelector('link[rel="location"]').target);
+ const url = event.target.location;
+ const hashed = link.pathname === url.pathname;
+ if (hashed) return;
+ fetch(url, "GET", function(http) {
+ filter(url.href, http);
+ persist();
+ self.document.dispatchEvent(new CustomEvent("URLChangedCustomEvent", {
+ bubbles: true
+ }));
+ });
+ });
+ self.addEventListener("click", function(event) {
+ if (localStorage[key] !== state) return;
+ const links = document.querySelectorAll("a");
+ for(let i1 = 0; i1 < links.length; i1++){
+ const active = links[i1].contains(event.target);
+ const change = self.location.href !== links[i1].href;
+ const view = links[i1].attributes.hasOwnProperty("download") === false;
+ const local = self.location.origin === links[i1].origin && links[i1].target !== "_self";
+ const hashed = self.location.pathname === links[i1].pathname && links[i1].href.includes("#");
+ if (active && local && change && view && hashed === false) {
+ event.preventDefault();
+ const url = links[i1].href;
+ links[i1].style.cursor = "wait";
+ fetch(url, "GET", function(http) {
+ links[i1].removeAttribute("style");
+ if (filter(url, http) === false) return self.location.href = url;
+ history.pushState({}, "", links[i1].href);
+ persist();
+ self.document.dispatchEvent(new CustomEvent("URLChangedCustomEvent", {
+ bubbles: true
+ }));
+ });
+ }
+ }
+ });
+})();
+(function() {
const relative = new Intl.RelativeTimeFormat("en", {
localeMatcher: "best fit",
numeric: "always",