diff options
Diffstat (limited to 'assets/js/index.js')
-rw-r--r-- | assets/js/index.js | 1153 |
1 files changed, 814 insertions, 339 deletions
diff --git a/assets/js/index.js b/assets/js/index.js index 1c2715b..d698127 100644 --- a/assets/js/index.js +++ b/assets/js/index.js @@ -1,52 +1,168 @@ -// deno-fmt-ignore-file -// deno-lint-ignore-file -// This code was bundled using `deno bundle` and it's not recommended to edit it manually - (function() { - const url = self.location.href.split("#")[0]; - let settings = { - pager: {} + const cookiesDisabled = !navigator.cookieEnabled; + if (cookiesDisabled) { + document.cookie = "disabled"; + document.cookie.indexOf("disabled"); + return console.warn("WARNING: Pager disabled due to cookie restrictions"); + } + 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]; }; - self.addEventListener("DOMContentLoaded", function() { - if (history.scrollRestoration) history.scrollRestoration = "manual"; - if (localStorage["settings"]) { - settings = JSON.parse(localStorage["settings"]); + 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)); + } } - if (self.location.hash.length > 0) { - settings["pager"][url] = self.pageYOffset; - localStorage["settings"] = JSON.stringify(settings); - document.getElementById(location.hash.slice(1)).scrollIntoView(); - self.addEventListener("load", function() { - document.getElementById(location.hash.slice(1)).scrollIntoView(); - }); - return; + return hashed; + }; + const scrollRestore = function(url) { + if (history.scrollRestoration) history.scrollRestoration = "manual"; + 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 = function(url) { + const currentPosition = self.pageYOffset; + pager = JSON.parse(localStorage[key]); + pager[url] = currentPosition; + localStorage[key] = JSON.stringify(pager); + }; + const scrollReverse = function(back, up, event) { + if (document.body.contains(up) && up.contains(event.target)) { + event.preventDefault(); + window.scrollTo(0, 0); } - if (settings["pager"][url] > 0) { - self.scrollTo(0, settings["pager"][url]); - return; + if (document.body.contains(back) && back.contains(event.target)) { + if (history.length < 2) return; + event.preventDefault(); + history.go(-1); } - settings["pager"][url] = self.pageYOffset; - localStorage["settings"] = JSON.stringify(settings); + }; + [ + "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()); + }); }); - self.addEventListener("scroll", function() { - const currentPosition = self.pageYOffset; - settings["pager"][url] = currentPosition; - localStorage["settings"] = JSON.stringify(settings); + [ + "click", + "touchstart", + "scroll" + ].forEach(function(event) { + self.addEventListener(event, function() { + scrollTrack(url()); + }); }); - self.addEventListener("DOMContentLoaded", function() { - const up = document.getElementById("top"); - const back = document.getElementById("back"); - self.addEventListener("click", function(event) { - if (document.body.contains(up) && up.contains(event.target)) { - event.preventDefault(); - window.scrollTo(0, 0); - } - if (document.body.contains(back) && back.contains(event.target)) { - if (history.length < 2) return; - event.preventDefault(); - history.go(-1); +})(); +(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() { + if (scrolled) clearTimeout(scrolled); + scrolled = setTimeout(function() { + update(); + delay = delay + delayed; + delayed = delay - delayed; + }, delay); + }); + [ + "focus", + "load", + "URLChangedCustomEvent" + ].forEach(function(event) { + self.addEventListener(event, function() { + update(); + }); }); })(); (function() { @@ -81,350 +197,709 @@ } })(); (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 (typeof Element !== "undefined") { + if (!Element.prototype.matches) { + Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; } - if (isSupported) { - const eventListenersOptions = { - capture: true, - passive: true + 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; + } + 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); + }); + }); + function preloadable(url) { + switch(true){ + case url === null || url.href === null: + 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; } - preload(linkElement.href); } - function mouseoverListener(event) { - if (performance.now() - lastTouchTimestamp < 1111) { - return; - } - const linkElement = event.target.closest("a"); - if (!isPreloadable(linkElement)) { + function preload(url) { + const prefetcher = document.createElement("link"); + 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; } - linkElement.addEventListener("mouseout", mouseoutListener, { - passive: true - }); - mouseoverTimer = setTimeout(function() { - preload(linkElement.href); - mouseoverTimer = undefined; - }, delayOnHover); + document.head.appendChild(prefetcher); + fetch(url, "GET", function() {}); } - function mousedownListener(event) { - const linkElement = event.target.closest("a"); - if (!isPreloadable(linkElement)) { - return; - } - preload(linkElement.href); + }); +})(); +(function() { + const hide = function(triggers) { + for(let i1 = 0; i1 < triggers.length; i1++){ + triggers[i1].checked = false; } - function mouseoutListener(event) { - if (event.relatedTarget && event.target.closest("a") == event.relatedTarget.closest("a")) { - return; + }; + 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("menu input"); + hide(triggers); + }); + [ + "click", + "touchstart" + ].forEach(function(event) { + self.addEventListener(event, function(event) { + const menus = document.querySelectorAll("menu"); + const triggers = document.querySelectorAll("menu input"); + hideIfClickedOutside(menus, triggers, event); + }); + }); +})(); +(function() { + [ + "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 (mouseoverTimer) { - clearTimeout(mouseoverTimer); - mouseoverTimer = undefined; + function last(element) { + return element.lastElementChild.firstChild.nextElementSibling; } - } - function mousedownShortcutListener(event1) { - if (performance.now() - lastTouchTimestamp < 1111) { - return; + function next(element) { + return element.activeElement.parentElement.nextElementSibling.firstChild.nextElementSibling.focus(); } - const linkElement = event1.target.closest("a"); - if (event1.which > 1 || event1.metaKey || event1.ctrlKey) { - return; + function previous(element) { + return element.activeElement.parentElement.previousElementSibling.firstChild.nextElementSibling.focus(); } - if (!linkElement) { - return; + function press(keyname) { + document.dispatchEvent(new KeyboardEvent("keydown", { + "key": keyname + })); } - linkElement.addEventListener("click", function(event) { - if (event.detail == 1337) { - return; + let selected; + if (submit === null) return; + submit.addEventListener("click", function(event) { + if (selected) { + event.preventDefault(); + selected.focus(); + return selected.click(); } + 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(); - }, { - capture: true, - passive: false, - once: true + return false; }); - const customEvent = new MouseEvent("click", { - view: window, - bubbles: true, - cancelable: false, - detail: 1337 + 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(); + 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(); + } + } }); - 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; + 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; + }); } - if (linkElement.protocol == "http:" && location.protocol == "https:") { - return; + let data = {}; + let boot = true; + const options = { + key: [ + "title" + ] + }; + function isEmpty(obj) { + return Object.keys(obj).length === 0; } - if (!allowQueryString && linkElement.search && !("instant" in linkElement.dataset)) { - return; + 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); + }); + } } - if (linkElement.hash && linkElement.pathname + linkElement.search == location.pathname + location.search) { - return; + 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; } - if ("noInstant" in linkElement.dataset) { - return; + }); + }); +})(); +(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(); + } } - return true; + }); + }); +})(); +(function() { + if (typeof Element !== "undefined") { + if (!Element.prototype.matches) { + Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; } - function preload(url) { - if (prefetches.has(url)) { - return; - } - const prefetcher = document.createElement("link"); - prefetcher.rel = "prefetch"; - prefetcher.href = url; - document.head.appendChild(prefetcher); - prefetches.add(url); + 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; + }; + } + } + const disabled = "0s"; + function walk(children, callback) { + for(let i1 = 0; i1 < children.length; i1++){ + callback(children[i1]); + walk(children[i1].children, callback); + } + } + 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"); + } + }); + walk(tree.children, function(element) { + const delay = self.getComputedStyle(element).getPropertyValue("transition-delay"); + if (delay !== disabled) { + element.style.removeProperty("visibility"); + } + }); } }); })(); (function() { - self.addEventListener("DOMContentLoaded", function() { - const form = document.getElementById("search-form"); - const query = document.getElementById("search-input"); - document.getElementById("search-submit"); - const dropdown = document.getElementById("search-results"); - const container = document.getElementById("search-frame"); - form.addEventListener("focusin", function() { - initialize(); - }); - form.addEventListener("submit", function(event) { - event.preventDefault(); - return false; - }); - form.addEventListener("keydown", function(event) { - const head = dropdown.firstChild.nextElementSibling.firstChild.nextElementSibling; - const tail = dropdown.lastElementChild.firstChild.nextElementSibling; - if (query.contains(event.target)) { - if (event.keyCode == 27) { - document.activeElement.blur(); - dropdown.setAttribute("hidden", ""); - } - } - if (event.keyCode == 40) { - event.preventDefault(); - if (document.activeElement == query) head.focus(); - else if (document.activeElement == tail) query.focus(); - else { - document.activeElement.parentElement.nextElementSibling.firstChild.nextElementSibling.focus(); + 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")); + }); } - if (event.keyCode == 38) { - event.preventDefault(); - if (document.activeElement == query) tail.focus(); - else if (document.activeElement == head) query.focus(); - else { - document.activeElement.parentElement.previousElementSibling.firstChild.nextElementSibling.focus(); + 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; + } + }); } } - if (event.keyCode == 8) { - if (document.activeElement != query) { - event.preventDefault(); - query.focus(); + }); + }); + [ + "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)"; + } + } + } } } - if (event.keyCode == 13) { - if (dropdown && document.activeElement == query) { - event.preventDefault(); - head.focus(); - self.window.location = document.activeElement.href; + }); + }); + 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; } } - }); - let scrolls = 0; - self.addEventListener("scroll", function() { - if (scrolls > 3) { - scrolls = 0; - document.activeElement.blur(); - dropdown.setAttribute("hidden", ""); - container.removeAttribute("data-focus"); + }; + 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]); } - scrolls++; - }); - document.addEventListener("click", function(event) { - if (!form.contains(event.target)) { - dropdown.setAttribute("hidden", ""); - container.removeAttribute("data-focus"); + } + 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); } - }); - function fetch_JSON(path, callback) { - const httpRequest = new XMLHttpRequest(); - httpRequest.onreadystatechange = function() { - if (httpRequest.readyState === 4) { - if (httpRequest.status === 200) { - const data = JSON.parse(httpRequest.responseText); - if (callback) callback(data); - } - } - }; - httpRequest.open("GET", path); - httpRequest.send(); } - function load_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; - }); + while(live.documentElement.attributes.length > 0){ + live.documentElement.removeAttribute(live.documentElement.attributes[live.documentElement.attributes.length - 1].name); } - let first_run = true; - function initialize() { - if (first_run) { - load_script(window.location.origin + "/js/fuzzysort.js").then(()=>{ - first_run = false; - fetch_JSON("/index.json", function(data) { - 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); + 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 + })); }); } } - 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">${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)){ - let highlight = fuzzysort.highlight(fuzzysort.single(term, results[string].obj.title), "<span>", "</span>"); - if (highlight === null) { - highlight = results[string].obj.title; + }); +})(); +(function() { + const relative = new Intl.RelativeTimeFormat("en", { + localeMatcher: "best fit", + numeric: "always", + style: "long" + }); + 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 (element.dataset.type === "localDate") { + return element.textContent = new Intl.DateTimeFormat([], { + dateStyle: "medium" + }).format(time).replace(",", ""); } - items = items + ` - <li> - <a href="${results[string].obj.url}" tabindex="0">${highlight}</a> - </li> - `; + 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 (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 (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); } - } - dropdown.innerHTML = items; + })(elements[i1]); } + }; + const substitution = setInterval(date, 4); + [ + "scroll", + "URLChangedCustomEvent" + ].forEach(function(event) { + self.addEventListener(event, function() { + date("viewport"); + }); + }); + self.addEventListener("DOMContentLoaded", function() { + setTimeout(function() { + clearInterval(substitution); + setInterval(function() { + date("viewport"); + }, 1000); + }, 1000); }); })(); -console.log("Surface Control: OK"); +console.log("INFO: Surface Control Complete");
\ No newline at end of file |