aboutsummaryrefslogtreecommitdiff
path: root/assets/js/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'assets/js/index.js')
-rw-r--r--assets/js/index.js1200
1 files changed, 769 insertions, 431 deletions
diff --git a/assets/js/index.js b/assets/js/index.js
index cc61f84..d698127 100644
--- a/assets/js/index.js
+++ b/assets/js/index.js
@@ -3,41 +3,56 @@
if (cookiesDisabled) {
document.cookie = "disabled";
document.cookie.indexOf("disabled");
- return console.log("Pager is disabled due to cookie restrictions.");
+ return console.warn("WARNING: Pager disabled due to cookie restrictions");
}
- let settings = {
- pager: {}
+ let seek;
+ let pager = {};
+ const key = "config.scroll.pager.urls";
+ if (!localStorage[key]) localStorage[key] = JSON.stringify(pager);
+ let url = function() {
+ return self.location.href.split("#")[0].split("?")[0];
};
- const url = self.location.href.split("#")[0].split("?")[0];
- const scrollRestore = (url)=>{
+ const scrollHash = function(url) {
+ const hash = self.location.hash;
+ const fragment = hash.slice(1) && document.getElementById(hash.slice(1));
+ const fragmented = hash.length > 0;
+ const hashed = fragmented && document.body.contains(fragment);
+ if (hashed) {
+ self.location.hash = hash;
+ self.location.href = hash;
+ if ("scroll-margin-top" in document.body.style === false && fragment.textContent !== "") {
+ self.scrollBy(0, -6 * parseFloat(getComputedStyle(document.documentElement).fontSize));
+ }
+ }
+ return hashed;
+ };
+ const scrollRestore = function(url) {
if (history.scrollRestoration) history.scrollRestoration = "manual";
- if (localStorage["settings"]) {
- settings = JSON.parse(localStorage["settings"]);
- }
- const fragment = document.getElementById(location.hash.slice(1));
- const fragmentInURL = self.location.hash.length > 0;
- if (fragmentInURL && document.body.contains(fragment)) {
- settings["pager"][url] = self.pageYOffset;
- localStorage["settings"] = JSON.stringify(settings);
- fragment.scrollIntoView();
- self.addEventListener("load", function() {
- fragment.scrollIntoView();
- });
- return;
- }
- if (settings["pager"][url] > 0) {
- self.scrollTo(0, settings["pager"][url]);
- return;
- }
- settings["pager"][url] = self.pageYOffset;
- localStorage["settings"] = JSON.stringify(settings);
+ if (scrollHash(url)) return;
+ pager = JSON.parse(localStorage[key]);
+ if (pager[url] > 0) {
+ clearInterval(seek);
+ self.scrollTo(0, pager[url]);
+ let i1 = 0;
+ return seek = setInterval(function(position) {
+ i1++;
+ if (i1 > 100) clearInterval(seek);
+ if (document.documentElement.scrollHeight >= position + document.documentElement.clientHeight) {
+ clearInterval(seek);
+ self.scrollTo(0, position);
+ }
+ }, 4, pager[url]);
+ } else self.scrollTo(0, 0);
+ pager[url] = self.pageYOffset;
+ localStorage[key] = JSON.stringify(pager);
};
- const scrollTrack = (url)=>{
+ const scrollTrack = function(url) {
const currentPosition = self.pageYOffset;
- settings["pager"][url] = currentPosition;
- localStorage["settings"] = JSON.stringify(settings);
+ pager = JSON.parse(localStorage[key]);
+ pager[url] = currentPosition;
+ localStorage[key] = JSON.stringify(pager);
};
- const backTrack = (back, up, event)=>{
+ const scrollReverse = function(back, up, event) {
if (document.body.contains(up) && up.contains(event.target)) {
event.preventDefault();
window.scrollTo(0, 0);
@@ -48,19 +63,106 @@
history.go(-1);
}
};
- self.addEventListener("DOMContentLoaded", function() {
- scrollRestore(url);
- self.addEventListener("click", function(event) {
- const up = document.getElementById("top");
- const back = document.getElementById("back");
- backTrack(back, up, event);
+ [
+ "DOMContentLoaded",
+ "pageshow",
+ "hashchange",
+ "URLChangedCustomEvent"
+ ].forEach(function(event) {
+ self.addEventListener(event, function(event) {
+ if (event.type === "pageshow") {
+ return event.persisted && self.scrollTo(0, pager[url()]);
+ }
+ if (event.type === "DOMContentLoaded") {
+ self.addEventListener("click", function(event) {
+ const up = document.getElementById("top");
+ const back = document.getElementById("back");
+ scrollReverse(back, up, event);
+ });
+ }
+ scrollRestore(url());
});
});
+ [
+ "click",
+ "touchstart",
+ "scroll"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ scrollTrack(url());
+ });
+ });
+})();
+(function() {
+ const cookiesDisabled = !navigator.cookieEnabled;
+ if (cookiesDisabled) {
+ document.cookie = "disabled";
+ document.cookie.indexOf("disabled");
+ return console.warn("WARNING: Update check disabled due to cookie restrictions");
+ }
+ function fetch(url, method, callback) {
+ const http = new XMLHttpRequest();
+ http.onreadystatechange = function() {
+ if (http.readyState === 4 && http.status === 200) {
+ if (callback) callback(http);
+ }
+ };
+ http.open(method, url);
+ http.setRequestHeader("Pragma", "no-cache");
+ http.setRequestHeader("Cache-Control", "no-cache");
+ http.send();
+ return http;
+ }
+ const key = "config.update";
+ let stamps = {};
+ if (!sessionStorage[key + ".urls"]) sessionStorage[key + ".urls"] = JSON.stringify(stamps);
+ function update() {
+ const url = self.location.href.split("#")[0].split("?")[0];
+ const indicator = document.querySelector("a[data-update]");
+ if (indicator === null || indicator.dataset.update === "refresh") return;
+ indicator.cloneNode();
+ fetch(url, "HEAD", function(request) {
+ const local = document.querySelector('meta[name="last-modified"]').content || document.lastModified;
+ const remote = request.getResponseHeader("last-modified") || '';
+ const modified = Date.parse(remote || local) > Date.parse(local);
+ const drift = Date.parse(remote || local) - Date.parse(local);
+ if (drift < 10000) return;
+ stamps = JSON.parse(sessionStorage[key + ".urls"]);
+ if (stamps[url] === remote) return;
+ stamps[url] = remote;
+ sessionStorage[key + ".urls"] = JSON.stringify(stamps);
+ if (remote && modified) {
+ fetch(url, "GET", function() {
+ indicator.href = url.replace(/^https:/, "http:");
+ indicator.removeAttribute("id");
+ indicator.dataset.update = "refresh";
+ console.log("INFO: R: " + remote);
+ console.log("INFO: L: " + local);
+ console.log("INFO: D: " + drift);
+ console.log("INFO: M: " + modified);
+ });
+ }
+ });
+ }
+ let scrolled;
+ let delay = 1000;
+ let delayed = 0;
self.addEventListener("scroll", function() {
- scrollTrack(url);
+ if (scrolled) clearTimeout(scrolled);
+ scrolled = setTimeout(function() {
+ update();
+ delay = delay + delayed;
+ delayed = delay - delayed;
+ }, delay);
});
- self.addEventListener("hashchange", function() {
- scrollRestore(url);
+ [
+ "focus",
+ "load",
+ "URLChangedCustomEvent"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ update();
+ });
});
})();
(function() {
@@ -95,217 +197,92 @@
}
})();
(function() {
- self.addEventListener("DOMContentLoaded", function() {
- let mouseoverTimer;
- let lastTouchTimestamp;
- const prefetches = new Set();
- const prefetchElement = document.createElement("link");
- const isSupported = prefetchElement.relList && prefetchElement.relList.supports && prefetchElement.relList.supports("prefetch") && window.IntersectionObserver && "isIntersecting" in IntersectionObserverEntry.prototype;
- const allowQueryString = "instantAllowQueryString" in document.body.dataset;
- const allowExternalLinks = "instantAllowExternalLinks" in document.body.dataset;
- const useWhitelist = "instantWhitelist" in document.body.dataset;
- const mousedownShortcut = "instantMousedownShortcut" in document.body.dataset;
- let delayOnHover = 65;
- let useMousedown = false;
- let useMousedownOnly = false;
- let useViewport = false;
- if ("instantIntensity" in document.body.dataset) {
- const intensity = document.body.dataset.instantIntensity;
- if (intensity.substr(0, "mousedown".length) == "mousedown") {
- useMousedown = true;
- if (intensity == "mousedown-only") {
- useMousedownOnly = true;
- }
- } else if (intensity.substr(0, "viewport".length) == "viewport") {
- if (!(navigator.connection && (navigator.connection.saveData || navigator.connection.effectiveType && navigator.connection.effectiveType.includes("2g")))) {
- if (intensity == "viewport") {
- if (document.documentElement.clientWidth * document.documentElement.clientHeight < 450000) {
- useViewport = true;
- }
- } else if (intensity == "viewport-all") {
- useViewport = true;
- }
- }
- } else {
- const milliseconds = parseInt(intensity);
- if (!isNaN(milliseconds)) {
- delayOnHover = milliseconds;
- }
- }
- }
- if (isSupported) {
- const eventListenersOptions = {
- capture: true,
- passive: true
+ if (typeof Element !== "undefined") {
+ if (!Element.prototype.matches) {
+ Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
+ }
+ if (!Element.prototype.closest) {
+ Element.prototype.closest = function(s) {
+ var el = this;
+ do {
+ if (el.matches(s)) return el;
+ el = el.parentElement || el.parentNode;
+ }while (el !== null && el.nodeType === 1)
+ return null;
};
- if (!useMousedownOnly) {
- document.addEventListener("touchstart", touchstartListener, eventListenersOptions);
- }
- if (!useMousedown) {
- document.addEventListener("mouseover", mouseoverListener, eventListenersOptions);
- } else if (!mousedownShortcut) {
- document.addEventListener("mousedown", mousedownListener, eventListenersOptions);
- }
- if (mousedownShortcut) {
- document.addEventListener("mousedown", mousedownShortcutListener, eventListenersOptions);
- }
- if (useViewport) {
- let triggeringFunction;
- if (window.requestIdleCallback) {
- triggeringFunction = function(callback) {
- requestIdleCallback(callback, {
- timeout: 1500
- });
- };
- } else {
- triggeringFunction = function(callback) {
- callback();
- };
- }
- triggeringFunction(function() {
- const intersectionObserver = new IntersectionObserver(function(entries) {
- entries.forEach(function(entry) {
- if (entry.isIntersecting) {
- const linkElement = entry.target;
- intersectionObserver.unobserve(linkElement);
- preload(linkElement.href);
- }
- });
- });
- document.querySelectorAll("a").forEach(function(linkElement) {
- if (isPreloadable(linkElement)) {
- intersectionObserver.observe(linkElement);
- }
- });
- });
- }
}
- function touchstartListener(event) {
- lastTouchTimestamp = performance.now();
- const linkElement = event.target.closest("a");
- if (!isPreloadable(linkElement)) {
- return;
- }
- preload(linkElement.href);
- }
- function mouseoverListener(event) {
- if (performance.now() - lastTouchTimestamp < 1111) {
- return;
- }
- const linkElement = event.target.closest("a");
- if (!isPreloadable(linkElement)) {
- return;
- }
- linkElement.addEventListener("mouseout", mouseoutListener, {
- passive: true
+ }
+ function fetch(url, method, callback) {
+ const http = new XMLHttpRequest();
+ http.onreadystatechange = function() {
+ if (http.readyState === 4 && http.status === 200) {
+ if (callback) callback(http);
+ }
+ };
+ http.open(method, url);
+ http.send();
+ return http;
+ }
+ self.addEventListener("DOMContentLoaded", function() {
+ [
+ "mouseout",
+ "mousedown",
+ "touchstart"
+ ].forEach(function(event) {
+ self.addEventListener(event, function(event) {
+ const url = event.target.closest("a");
+ if (preloadable(url) === undefined) return;
+ preload(url.href);
});
- mouseoverTimer = setTimeout(function() {
- preload(linkElement.href);
- mouseoverTimer = undefined;
- }, delayOnHover);
- }
- function mousedownListener(event) {
- const linkElement = event.target.closest("a");
- if (!isPreloadable(linkElement)) {
- return;
- }
- preload(linkElement.href);
- }
- function mouseoutListener(event) {
- if (event.relatedTarget && event.target.closest("a") == event.relatedTarget.closest("a")) {
- return;
- }
- if (mouseoverTimer) {
- clearTimeout(mouseoverTimer);
- mouseoverTimer = undefined;
- }
- }
- function mousedownShortcutListener(event) {
- if (performance.now() - lastTouchTimestamp < 1111) {
- return;
- }
- const linkElement = event.target.closest("a");
- if (event.which > 1 || event.metaKey || event.ctrlKey) {
- return;
- }
- if (!linkElement) {
- return;
- }
- linkElement.addEventListener("click", function(event) {
- if (event.detail == 1337) {
+ });
+ function preloadable(url) {
+ switch(true){
+ case url === null || url.href === null:
return;
- }
- event.preventDefault();
- }, {
- capture: true,
- passive: false,
- once: true
- });
- const customEvent = new MouseEvent("click", {
- view: window,
- bubbles: true,
- cancelable: false,
- detail: 1337
- });
- linkElement.dispatchEvent(customEvent);
- }
- function isPreloadable(linkElement) {
- if (!linkElement || !linkElement.href) {
- return;
- }
- if (useWhitelist && !("instant" in linkElement.dataset)) {
- return;
- }
- if (!allowExternalLinks && linkElement.origin != location.origin && !("instant" in linkElement.dataset)) {
- return;
- }
- if (![
- "http:",
- "https:"
- ].includes(linkElement.protocol)) {
- return;
- }
- if (linkElement.protocol == "http:" && location.protocol == "https:") {
- return;
- }
- if (!allowQueryString && linkElement.search && !("instant" in linkElement.dataset)) {
- return;
- }
- if (linkElement.hash && linkElement.pathname + linkElement.search == location.pathname + location.search) {
- return;
- }
- if ("noInstant" in linkElement.dataset) {
- return;
+ case url.origin !== location.origin:
+ return;
+ case [
+ "http:",
+ "https:"
+ ].includes(url.protocol) === null:
+ return;
+ case url.protocol === "http:" && location.protocol === "https:":
+ return;
+ case url.hash && url.pathname + url.search == location.pathname + location.search:
+ return;
+ default:
+ return true;
}
- return true;
}
function preload(url) {
- if (prefetches.has(url)) {
- return;
- }
const prefetcher = document.createElement("link");
- prefetcher.rel = "prefetch";
+ prefetcher.rel = "custom-prefetch";
prefetcher.href = url;
+ const selector = 'link[rel="'.concat(prefetcher.rel, '"][href="').concat(prefetcher.href, '"]');
+ const prefetched = document.head.contains(document.querySelector(selector));
+ if (prefetched) {
+ return;
+ }
document.head.appendChild(prefetcher);
- prefetches.add(url);
+ fetch(url, "GET", function() {});
}
});
})();
(function() {
- const hide = (triggers)=>{
- for(let i = 0; i < triggers.length; i++){
- triggers[i].checked = false;
+ const hide = function(triggers) {
+ for(let i1 = 0; i1 < triggers.length; i1++){
+ triggers[i1].checked = false;
}
};
- const hideIfClickedOutside = (menus, triggers, event)=>{
- for(let i = 0; i < menus.length; i++){
- const active = triggers[i].checked === true;
- const outside = !menus[i].contains(event.target);
+ const hideIfClickedOutside = function(menus, triggers, event) {
+ for(let i1 = 0; i1 < menus.length; i1++){
+ const active = triggers[i1].checked === true;
+ const outside = !menus[i1].contains(event.target);
if (outside && active) hide(triggers);
}
};
self.addEventListener("scroll", function() {
- const triggers = document.querySelectorAll("micro-metadata-menu input");
+ const triggers = document.querySelectorAll("menu input");
hide(triggers);
});
[
@@ -313,196 +290,512 @@
"touchstart"
].forEach(function(event) {
self.addEventListener(event, function(event) {
- const menus = document.querySelectorAll("micro-metadata-menu");
- const triggers = document.querySelectorAll("micro-metadata-menu input");
+ const menus = document.querySelectorAll("menu");
+ const triggers = document.querySelectorAll("menu input");
hideIfClickedOutside(menus, triggers, event);
});
});
})();
(function() {
- self.addEventListener("DOMContentLoaded", function() {
- const form = document.getElementById("search-form");
- const query = document.getElementById("search-input");
- const submit = document.getElementById("search-submit");
- const dropdown = document.getElementById("search-results");
- const container = document.getElementById("search-frame");
- function first(element) {
- return element.firstChild.nextElementSibling.firstChild.nextElementSibling;
- }
- function last(element) {
- return element.lastElementChild.firstChild.nextElementSibling;
- }
- function next(element) {
- return element.activeElement.parentElement.nextElementSibling.firstChild.nextElementSibling.focus();
- }
- function previous(element) {
- return element.activeElement.parentElement.previousElementSibling.firstChild.nextElementSibling.focus();
- }
- function press(keyname) {
- document.dispatchEvent(new KeyboardEvent("keydown", {
- "key": keyname
- }));
- }
- submit.addEventListener("click", function(event) {
- first(dropdown).focus();
- press("ArrowDown");
- });
- form.addEventListener("focusin", function() {
- container.setAttribute("data-focus", "");
- initialize();
- });
- form.addEventListener("submit", function(event) {
- event.preventDefault();
- return false;
- });
- form.addEventListener("keydown", function(event) {
- const head = first(dropdown);
- const tail = last(dropdown);
- if (query.contains(event.target)) {
- if (event.keyCode == 27) {
- document.activeElement.blur();
- dropdown.setAttribute("hidden", "");
- container.removeAttribute("data-focus");
+ [
+ "DOMContentLoaded",
+ "URLChangedCustomEvent"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ const container = document.querySelector("search-box");
+ const dropdown = document.querySelector("search-box ul");
+ const form = document.querySelector("search-box form");
+ const query = document.querySelector("search-box input");
+ const submit = document.querySelector("search-box button");
+ function first(element) {
+ if (element.firstChild.nextElementSibling) {
+ return element.firstChild.nextElementSibling.firstChild.nextElementSibling;
}
}
- if (event.keyCode == 40) {
- event.preventDefault();
- if (document.activeElement == query) head.focus();
- else if (document.activeElement == tail) query.focus();
- else next(document);
+ function last(element) {
+ return element.lastElementChild.firstChild.nextElementSibling;
}
- if (event.keyCode == 38) {
- event.preventDefault();
- if (document.activeElement == query) tail.focus();
- else if (document.activeElement == head) query.focus();
- else previous(document);
+ function next(element) {
+ return element.activeElement.parentElement.nextElementSibling.firstChild.nextElementSibling.focus();
}
- if (event.keyCode == 8) {
- if (document.activeElement != query) {
+ function previous(element) {
+ return element.activeElement.parentElement.previousElementSibling.firstChild.nextElementSibling.focus();
+ }
+ function press(keyname) {
+ document.dispatchEvent(new KeyboardEvent("keydown", {
+ "key": keyname
+ }));
+ }
+ let selected;
+ if (submit === null) return;
+ submit.addEventListener("click", function(event) {
+ if (selected) {
event.preventDefault();
- query.focus();
+ selected.focus();
+ return selected.click();
}
- }
- if (event.keyCode == 13) {
- if (dropdown && document.activeElement == query) {
+ first(dropdown).focus();
+ press("ArrowDown");
+ document.activeElement.click();
+ });
+ [
+ "keyup",
+ "click"
+ ].forEach(function(event) {
+ form.addEventListener(event, function() {
+ if (document.activeElement.nodeName === "A") {
+ return selected = document.activeElement;
+ }
+ selected = undefined;
+ });
+ });
+ form.addEventListener("focusin", function() {
+ container.setAttribute("data-focus", "");
+ initialize();
+ });
+ form.addEventListener("submit", function(event) {
+ event.preventDefault();
+ return false;
+ });
+ form.addEventListener("keydown", function(event) {
+ if (form.contains(event.target)) {
+ if (event.keyCode == 27) {
+ document.activeElement.blur();
+ dropdown.setAttribute("hidden", "");
+ container.removeAttribute("data-focus");
+ }
+ }
+ if (event.keyCode == 8) {
+ if (document.activeElement != query) {
+ event.preventDefault();
+ query.focus();
+ }
+ }
+ const head = first(dropdown);
+ const tail = last(dropdown);
+ if (event.keyCode == 40) {
+ event.preventDefault();
+ if (document.activeElement == query) head.focus();
+ else if (document.activeElement == tail) query.focus();
+ else next(document);
+ }
+ if (event.keyCode == 38) {
event.preventDefault();
- head.focus();
- self.window.location = document.activeElement.href;
+ if (document.activeElement == query) tail.focus();
+ else if (document.activeElement == head) query.focus();
+ else previous(document);
+ }
+ if (event.keyCode == 13) {
+ if (dropdown && document.activeElement == query) {
+ event.preventDefault();
+ head.focus();
+ head.click();
+ }
+ }
+ });
+ let scrolls = 0;
+ self.addEventListener("scroll", function() {
+ if (scrolls > 3) {
+ scrolls = 0;
+ document.activeElement.blur();
+ dropdown.setAttribute("hidden", "");
+ container.removeAttribute("data-focus");
}
+ scrolls++;
+ });
+ self.addEventListener("click", function(event) {
+ if (!form.contains(event.target) && !(document.activeElement === query) && !(document.activeElement === submit)) {
+ dropdown.setAttribute("hidden", "");
+ container.removeAttribute("data-focus");
+ }
+ });
+ function fetch(url, callback) {
+ const http = new XMLHttpRequest();
+ http.onreadystatechange = function() {
+ if (http.readyState === 4 && http.status === 200 && callback) {
+ callback(http);
+ }
+ };
+ http.open("GET", url);
+ http.send();
+ }
+ function script(url) {
+ return new Promise(function(resolve, reject) {
+ const script = document.createElement("script");
+ script.onerror = reject;
+ script.onload = resolve;
+ if (document.currentScript) {
+ document.currentScript.parentNode.insertBefore(script, document.currentScript);
+ } else document.head.appendChild(script);
+ script.src = url;
+ });
}
- });
- let scrolls = 0;
- self.addEventListener("scroll", function() {
- if (scrolls > 3) {
- scrolls = 0;
- document.activeElement.blur();
- dropdown.setAttribute("hidden", "");
- container.removeAttribute("data-focus");
+ let data = {};
+ let boot = true;
+ const options = {
+ key: [
+ "title"
+ ]
+ };
+ function isEmpty(obj) {
+ return Object.keys(obj).length === 0;
+ }
+ function appendItemsTo(local, remote) {
+ const paginated = Object.keys(remote).includes("next_url");
+ if (isEmpty(local)) {
+ local = remote;
+ } else {
+ local.items = local.items.concat(remote.items);
+ }
+ if (paginated) {
+ fetch(remote.next_url, function(request) {
+ appendItemsTo(local, JSON.parse(request.responseText));
+ });
+ } else search(query.value, data.items, options);
+ data = local;
+ }
+ function initialize() {
+ if (boot) {
+ script(window.location.origin + "/js/fuzzysort.js").then(function() {
+ fetch("/index.json", function(request) {
+ appendItemsTo({}, JSON.parse(request.responseText));
+ search("", data.items, options);
+ boot = false;
+ });
+ [
+ "keyup",
+ "focusin"
+ ].forEach(function(event) {
+ query.addEventListener(event, function() {
+ if (data.items) search(query.value, data.items, options);
+ else {
+ boot = true;
+ initialize();
+ }
+ });
+ });
+ }).catch(function(error) {
+ console.error("ERROR: Failed to load fuzzy search", error);
+ });
+ }
+ }
+ function escape(text) {
+ const escaped = document.createElement("textarea");
+ escaped.textContent = text;
+ return escaped.innerHTML;
+ }
+ function search(term, data, options) {
+ const results = fuzzysort.go(term, data, options);
+ let items = "";
+ if (results.length === 0 && term.length >= 0) {
+ let separator = "—";
+ if (term.length === 0) separator = "";
+ items = '<li><a tabindex="0">'.concat(escape(term), " ").concat(separator, " No Results Found</a></li>");
+ dropdown.removeAttribute("hidden");
+ container.setAttribute("data-focus", "");
+ } else {
+ dropdown.removeAttribute("hidden");
+ for(var string in results.slice(0, 10)){
+ const title = results[string].obj.title;
+ let highlight = fuzzysort.highlight(fuzzysort.single(escape(term), escape(title)), "<span>", "</span>");
+ if (highlight === null) highlight = title;
+ items = items + '\n<li>\n<a href="'.concat(results[string].obj.url, '" tabindex="0">').concat(highlight, "</a>\n</li>\n");
+ }
+ }
+ dropdown.innerHTML = items;
}
- scrolls++;
});
- document.addEventListener("click", function(event) {
- if (!form.contains(event.target)) {
- dropdown.setAttribute("hidden", "");
- container.removeAttribute("data-focus");
+ });
+})();
+(function() {
+ function viewport(element) {
+ const options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {
+ offset: {
+ top: -50,
+ left: 0,
+ bottom: -50,
+ right: 0
+ }
+ };
+ const view = element.getBoundingClientRect();
+ return view.top >= -options.offset.top && view.left >= -options.offset.left && view.bottom <= (self.innerHeight || document.documentElement.clientHeight) + options.offset.bottom && view.right <= (self.innerWidth || document.documentElement.clientWidth) + options.offset.right;
+ }
+ [
+ "scroll",
+ "DOMContentLoaded"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ let first = true;
+ let videos = document.querySelectorAll("video");
+ for(i = 0; i < videos.length; i++){
+ videos[i].autoplay = true;
+ videos[i].controls = true;
+ videos[i].loop = true;
+ videos[i].muted = true;
+ videos[i].playsinline = true;
+ videos[i].setAttribute("autoplay", true);
+ videos[i].setAttribute("controls", true);
+ videos[i].setAttribute("loop", true);
+ videos[i].setAttribute("muted", true);
+ videos[i].setAttribute("playsinline", true);
+ const onscreen = viewport(videos[i]);
+ if (first && onscreen) {
+ videos[i].play();
+ first = false;
+ } else {
+ videos[i].pause();
+ }
}
});
- let data = {};
- function isEmpty(obj) {
- return Object.keys(obj).length === 0;
+ });
+})();
+(function() {
+ if (typeof Element !== "undefined") {
+ if (!Element.prototype.matches) {
+ Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
+ }
+ if (!Element.prototype.closest) {
+ Element.prototype.closest = function(s) {
+ var el = this;
+ do {
+ if (el.matches(s)) return el;
+ el = el.parentElement || el.parentNode;
+ }while (el !== null && el.nodeType === 1)
+ return null;
+ };
}
- function appendItemsTo(local, remote) {
- const paginated = Object.keys(remote).includes("next_url");
- if (isEmpty(local)) {
- local = remote;
- } else {
- local.items = local.items.concat(remote.items);
- }
- if (paginated) {
- fetchJson(remote.next_url, local);
- }
- data = local;
+ }
+ const disabled = "0s";
+ function walk(children, callback) {
+ for(let i1 = 0; i1 < children.length; i1++){
+ callback(children[i1]);
+ walk(children[i1].children, callback);
}
- function fetchJson(url, store) {
- const httpRequest = new XMLHttpRequest();
- httpRequest.onreadystatechange = function() {
- if (httpRequest.readyState === 4 && httpRequest.status === 200) {
- appendItemsTo(store, JSON.parse(httpRequest.responseText));
+ }
+ self.addEventListener("mousemove", function(event) {
+ if (typeof event.target.closest !== "function") return;
+ tree = event.target.closest("figure") || event.target.closest("article");
+ if (tree !== null) {
+ walk(tree.children, function(element) {
+ const delay = self.getComputedStyle(element).getPropertyValue("transition-delay");
+ if (delay !== disabled) {
+ element.style.setProperty("visibility", "hidden");
}
- };
- httpRequest.open("GET", url);
- httpRequest.send();
- }
- function loadScript(url) {
- return new Promise(function(resolve, reject) {
- const script = document.createElement("script");
- script.onerror = reject;
- script.onload = resolve;
- if (document.currentScript) {
- document.currentScript.parentNode.insertBefore(script, document.currentScript);
- } else {
- document.head.appendChild(script);
+ });
+ walk(tree.children, function(element) {
+ const delay = self.getComputedStyle(element).getPropertyValue("transition-delay");
+ if (delay !== disabled) {
+ element.style.removeProperty("visibility");
}
- script.src = url;
});
}
- let firstRun = true;
- function initialize() {
- if (firstRun) {
- loadScript(window.location.origin + "/js/fuzzysort.js").then(()=>{
- firstRun = false;
- fetchJson("/index.json", {});
- const options = {
- key: [
- "title"
- ]
- };
- query.addEventListener("keyup", function() {
- search(query.value, data.items, options);
- });
- query.addEventListener("focusin", function() {
- search(query.value, data.items, options);
- });
- search(query.value, data.items, options);
- }).catch((error)=>{
- console.log("Error failed to load fuzzy sort: " + error);
+ });
+})();
+(function() {
+ const cookiesDisabled = !navigator.cookieEnabled;
+ if (cookiesDisabled) {
+ document.cookie = "disabled";
+ document.cookie.indexOf("disabled");
+ return console.warn("WARNING: Cannot persist form state due to cookie restrictions");
+ }
+ const storage = document.createEvent("Event");
+ storage.initEvent("storage", true, true);
+ [
+ "pageshow",
+ "URLChangedCustomEvent",
+ "DOMContentLoaded"
+ ].forEach(function(event) {
+ self.addEventListener(event, function(event) {
+ const input = Array.prototype.slice.call(document.querySelectorAll("form input"));
+ const select = Array.prototype.slice.call(document.querySelectorAll("form select"));
+ const textarea = Array.prototype.slice.call(document.querySelectorAll("form textarea"));
+ const summary = Array.prototype.slice.call(document.querySelectorAll("details summary"));
+ const states = input.concat(select).concat(textarea);
+ for(var i1 = 0; i1 < states.length; i1++){
+ const state = states[i1];
+ const sync = i1 === states.length - 1;
+ if (localStorage[state.id]) {
+ if (state.type === "radio" || state.type === "checkbox") {
+ if (localStorage[state.id] === "on") state.checked = true;
+ } else state.value = localStorage[state.id];
+ }
+ if (sync) self.dispatchEvent(storage);
+ state.addEventListener("change", function(event) {
+ localStorage[event.target.id] = event.target.value;
+ const group = document.querySelectorAll("input[name='".concat(event.target.name, "']"));
+ for(var j = 0; j < group.length; j++){
+ const member = group[j];
+ if ((member.type === "radio" || member.type === "checkbox") && !member.checked) {
+ localStorage[member.id] = "off";
+ }
+ }
+ self.dispatchEvent(new Event("storage"));
});
}
- }
- function escape(text) {
- const escaped = document.createElement("textarea");
- escaped.textContent = text;
- return escaped.innerHTML;
- }
- function search(term, data, options) {
- const results = fuzzysort.go(term, data, options);
- let items = "";
- if (results.length === 0 && term.length >= 0) {
- let separator = "—";
- if (term.length === 0) separator = "";
- items = `
- <li>
- <a href="javascript: void(0)" tabindex="0">${escape(term)} ${separator} No Results Found</a>
- </li>
- `;
- dropdown.removeAttribute("hidden");
- container.setAttribute("data-focus", "");
- } else {
- dropdown.removeAttribute("hidden");
- for(const string in results.slice(0, 10)){
- const title = results[string].obj.title;
- let highlight = fuzzysort.highlight(fuzzysort.single(escape(term), escape(title)), "<span>", "</span>");
- if (highlight === null) {
- highlight = title;
+ for(var k = 0; k < summary.length; k++){
+ let child = summary[k];
+ let details = child.parentElement;
+ if (details.id && details.nodeName === "DETAILS") {
+ sessionStorage[details.id] === "false" && details.removeAttribute("open");
+ sessionStorage[details.id] === "true" && details.setAttribute("open", true);
+ child.addEventListener("click", function(event) {
+ let child = event.target.nodeName === "SUMMARY" && event.target || event.target.parentElement;
+ let details = child.parentElement;
+ if (details.id && details.nodeName === "DETAILS") {
+ sessionStorage[details.id] = !details.open;
+ }
+ });
+ }
+ }
+ });
+ });
+ [
+ "storage"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ let stylesheet;
+ stylesheet = document.querySelector('link[href$="default-simple.css"]');
+ if (localStorage["config.layout.simple"] === "on") stylesheet.rel = "stylesheet";
+ if (localStorage["config.layout.default"] === "on") stylesheet.rel = "alternate stylesheet";
+ stylesheet = document.querySelector('link[href$="default-fast.css"]');
+ if (localStorage["config.navigation.fast"] === "on") stylesheet.rel = "stylesheet";
+ if (localStorage["config.navigation.slow"] === "on") stylesheet.rel = "alternate stylesheet";
+ for(var i1 = 0; i1 < document.styleSheets.length; i1++){
+ let stylesheet = document.styleSheets[i1];
+ for(var k = 0; k < stylesheet.rules.length; k++){
+ let media = stylesheet.rules[k].media;
+ if (media && media.mediaText.includes("prefers-color-scheme")) {
+ if (localStorage["config.theme.light"] === "on") {
+ media.mediaText = "(prefers-color-scheme: dark)";
+ if (getComputedStyle(document.body).getPropertyValue("color-scheme") === "dark") {
+ media.mediaText = "(prefers-color-scheme: light)";
+ }
+ }
+ if (localStorage["config.theme.auto"] === "on") {
+ media.mediaText = "(prefers-color-scheme: dark)";
+ }
+ if (localStorage["config.theme.dark"] === "on") {
+ media.mediaText = "(prefers-color-scheme: light)";
+ if (getComputedStyle(document.body).getPropertyValue("color-scheme") === "light") {
+ media.mediaText = "(prefers-color-scheme: dark)";
+ }
+ }
}
- items = items + `
- <li>
- <a href="${results[string].obj.url}" tabindex="0">${highlight}</a>
- </li>
- `;
}
}
- dropdown.innerHTML = items;
+ });
+ });
+ const early = setInterval(persistence, 4);
+ function persistence() {
+ if (document.styleSheets.length > 0) {
+ self.dispatchEvent(storage);
+ clearInterval(early);
+ }
+ }
+ self.addEventListener("DOMContentLoaded", function() {
+ self.dispatchEvent(storage);
+ clearInterval(early);
+ });
+})();
+(function() {
+ const timeout = 300;
+ const state = "on";
+ const key = "config.navigation.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) {
+ if (filter(url, http) === false) return self.location.href = url;
+ 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
+ }));
+ });
+ }
}
});
})();
@@ -512,56 +805,101 @@
numeric: "always",
style: "long"
});
- const date = ()=>{
- [
- ...document.querySelectorAll("time")
- ].forEach((element)=>{
- try {
- const time = new Date(element.dateTime) || new Date();
- const interval = (new Date().getTime() - time.getTime()) / 1000;
- const seconds = Math.floor(interval);
- const minutes = Math.floor(seconds / 60);
- const hours = Math.floor(minutes / 60);
- const days = Math.floor(hours / 24);
- if (Math.sign(seconds) === 1) {
- if (seconds <= 60) {
- return element.textContent = relative.format(-1 * seconds, "second");
- }
- if (minutes <= 120) {
- return element.textContent = relative.format(-1 * minutes, "minute");
- }
- if (hours <= 48) {
- return element.textContent = relative.format(-1 * hours, "hour");
- }
- if (days <= 60) {
- return element.textContent = relative.format(-1 * days, "day");
+ function viewport(element) {
+ const options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {
+ offset: 250
+ };
+ const view = element.getBoundingClientRect();
+ return view.top >= -options.offset && view.left >= -options.offset && view.bottom <= (self.innerHeight || document.documentElement.clientHeight) + options.offset && view.right <= (self.innerWidth || document.documentElement.clientWidth) + options.offset;
+ }
+ const date = function(update) {
+ const elements = document.querySelectorAll("time");
+ for(let i1 = 0; i1 < elements.length; ++i1){
+ const offscreen = !viewport(elements[i1]);
+ const hidden = elements[i1].offsetParent === null;
+ if (update === "viewport" && (offscreen || hidden)) continue;
+ (function(element) {
+ try {
+ if (element.dataset.type === "disabled") return;
+ const time = new Date(element.dateTime) || new Date();
+ const interval = (new Date().getTime() - time.getTime()) / 1000;
+ const seconds = Math.round(interval);
+ const minutes = Math.round(seconds / 60);
+ const hours = Math.round(minutes / 60);
+ const days = Math.round(hours / 24);
+ const past = Math.sign(seconds) === 1;
+ const future = Math.sign(seconds) === -1;
+ let tiny = function(string, place) {
+ return string.split(" ").slice(0, place).join(" ") + string.split(" ")[place].charAt(0);
+ };
+ if (element.dataset.type === "default") {
+ tiny = function(string) {
+ return string;
+ };
}
- }
- if (Math.sign(seconds) === -1) {
- if (-1 * days >= 60) {
- return element.textContent = relative.format(-1 * days, "day");
+ if (element.dataset.type === "localDate") {
+ return element.textContent = new Intl.DateTimeFormat([], {
+ dateStyle: "medium"
+ }).format(time).replace(",", "");
}
- if (-1 * hours >= 48) {
- return element.textContent = relative.format(-1 * hours, "hour");
+ if (element.dataset.type === "localTime") {
+ return element.textContent = new Intl.DateTimeFormat([], {
+ hour12: false,
+ timeStyle: "short"
+ }).format(time) + " " + new Intl.DateTimeFormat([], {
+ timeZoneName: "short"
+ }).format(time).split(" ")[1];
}
- if (-1 * minutes >= 120) {
- return element.textContent = relative.format(-1 * minutes, "minute");
+ if (past) {
+ if (seconds <= 60) {
+ return element.textContent = tiny(relative.format(-1 * seconds, "second"), 1);
+ }
+ if (minutes <= 120) {
+ return element.textContent = tiny(relative.format(-1 * minutes, "minute"), 1);
+ }
+ if (hours <= 48) {
+ return element.textContent = tiny(relative.format(-1 * hours, "hour"), 1);
+ }
+ if (days <= 7) {
+ return element.textContent = tiny(relative.format(-1 * days, "day"), 1);
+ }
}
- if (-1 * seconds >= 0) {
- return element.textContent = relative.format(-1 * seconds, "second");
+ if (future) {
+ if (-1 * days >= 4) {
+ return element.textContent = tiny(relative.format(-1 * days, "day"), 2);
+ }
+ if (-1 * hours >= 3) {
+ return element.textContent = tiny(relative.format(-1 * hours, "hour"), 2);
+ }
+ if (-1 * minutes >= 2) {
+ return element.textContent = tiny(relative.format(-1 * minutes, "minute"), 2);
+ }
+ if (-1 * seconds >= 1) {
+ return element.textContent = tiny(relative.format(-1 * seconds, "second"), 2);
+ }
}
+ } catch (error) {
+ console.error("ERROR: Relative time resolution failed", error);
}
- } catch (error) {
- console.error("Error: Unable to resolve relative time format!", error);
- }
- });
+ })(elements[i1]);
+ }
};
const substitution = setInterval(date, 4);
- self.addEventListener("load", ()=>{
- setTimeout(()=>{
+ [
+ "scroll",
+ "URLChangedCustomEvent"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ date("viewport");
+ });
+ });
+ self.addEventListener("DOMContentLoaded", function() {
+ setTimeout(function() {
clearInterval(substitution);
- setInterval(date, 1000);
+ setInterval(function() {
+ date("viewport");
+ }, 1000);
}, 1000);
});
})();
-console.log("Surface Control: Complete"); \ No newline at end of file
+console.log("INFO: Surface Control Complete"); \ No newline at end of file