From 30d33a9eedca8ae4b2e6082b915579c309f8b52c Mon Sep 17 00:00:00 2001 From: tdro Date: Sat, 13 Jan 2024 20:33:21 -0500 Subject: static/js: Prepare custom URL changed event Set key on pager and always clear interval --- assets/js/index.js | 419 +++++++++++++++++++++++++++-------------------------- 1 file changed, 215 insertions(+), 204 deletions(-) (limited to 'assets') diff --git a/assets/js/index.js b/assets/js/index.js index 8eae4fb..83d3943 100644 --- a/assets/js/index.js +++ b/assets/js/index.js @@ -5,29 +5,31 @@ document.cookie.indexOf("disabled"); return console.warn("WARNING: Pager disabled due to cookie restrictions"); } + let url; let seek; - let settings = { - pager: {} + let pager = {}; + const key = "config.scroll.pager.urls"; + if (!localStorage[key]) localStorage[key] = JSON.stringify(pager); + const link = function() { + url = self.location.href.split("#")[0].split("?")[0]; }; - const key = "settings"; - const url = self.location.href.split("#")[0].split("?")[0]; - if (!localStorage[key]) localStorage[key] = JSON.stringify(settings); const scrollRestore = function(url) { if (history.scrollRestoration) history.scrollRestoration = "manual"; - settings = JSON.parse(localStorage[key]); + pager = JSON.parse(localStorage[key]); const hash = self.location.hash; const fragment = hash.slice(1) && document.getElementById(hash.slice(1)); const fragmentInURL = hash.length > 0; if (fragmentInURL && document.body.contains(fragment)) { - settings["pager"][url] = self.pageYOffset; - localStorage[key] = JSON.stringify(settings); + pager[url] = self.pageYOffset; + localStorage[key] = JSON.stringify(pager); fragment.scrollIntoView(); return self.addEventListener("DOMContentLoaded", function() { fragment.scrollIntoView(); }); } - if (settings["pager"][url] > 0) { - self.scrollTo(0, settings["pager"][url]); + if (pager[url] > 0) { + clearInterval(seek); + self.scrollTo(0, pager[url]); let i1 = 0; return seek = setInterval(function(position) { i1++; @@ -36,18 +38,18 @@ clearInterval(seek); self.scrollTo(0, position); } - }, 4, settings["pager"][url]); - } - settings["pager"][url] = self.pageYOffset; - localStorage[key] = JSON.stringify(settings); + }, 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; - settings = JSON.parse(localStorage[key]); - settings["pager"][url] = currentPosition; - localStorage[key] = JSON.stringify(settings); + pager = JSON.parse(localStorage[key]); + pager[url] = currentPosition; + localStorage[key] = JSON.stringify(pager); }; - const reverseTrack = function(back, up, event) { + const scrollReverse = function(back, up, event) { if (document.body.contains(up) && up.contains(event.target)) { event.preventDefault(); window.scrollTo(0, 0); @@ -62,18 +64,20 @@ self.addEventListener("click", function(event) { const up = document.getElementById("top"); const back = document.getElementById("back"); - reverseTrack(back, up, event); + scrollReverse(back, up, event); }); }); [ "DOMContentLoaded", "pageshow", - "hashchange" + "hashchange", + "URLChangedCustomEvent" ].forEach(function(event) { self.addEventListener(event, function(event) { if (event.type === "pageshow") { - return event.persisted && self.scrollTo(0, settings["pager"][url]); + return event.persisted && self.scrollTo(0, pager[url]); } + link(); scrollRestore(url); }); }); @@ -83,6 +87,7 @@ "scroll" ].forEach(function(event) { self.addEventListener(event, function() { + link(); scrollTrack(url); }); }); @@ -381,204 +386,205 @@ }); })(); (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 - })); - } - let selected; - submit.addEventListener("click", function(event) { - if (selected) { + [ + "DOMContentLoaded", + "URLChangedCustomEvent" + ].forEach(function(event) { + self.addEventListener(event, 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 + })); + } + let selected; + 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(); - 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; + 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(); + 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(); + } } - 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) { + let scrolls = 0; + self.addEventListener("scroll", function() { + if (scrolls > 3) { + scrolls = 0; document.activeElement.blur(); dropdown.setAttribute("hidden", ""); container.removeAttribute("data-focus"); } - } - if (event.keyCode == 8) { - if (document.activeElement != query) { - event.preventDefault(); - query.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"); } - } - 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(); - self.window.location = document.activeElement.href; + }); + let data = {}; + 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)); + }); + } + data = local; } - }); - 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"); - } - }); - let data = {}; - 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) { - fetchJson(remote.next_url, function(request) { - appendItemsTo(local, JSON.parse(request.responseText)); + 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; }); } - data = local; - } - function fetchJson(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 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); - } - script.src = url; - }); - } - let firstRun = true; - function initialize() { - if (firstRun) { - loadScript(window.location.origin + "/js/fuzzysort.js").then(function() { - firstRun = false; - fetchJson("/index.json", function(request) { - appendItemsTo({}, JSON.parse(request.responseText)); - }); - const options = { - key: [ - "title" - ] - }; - query.addEventListener("keyup", function() { - search(query.value, data.items, options); - }); - query.addEventListener("focusin", function() { + let boot = true; + function initialize() { + if (boot) { + script(window.location.origin + "/js/fuzzysort.js").then(function() { + boot = false; + fetch("/index.json", function(request) { + appendItemsTo({}, JSON.parse(request.responseText)); + }); + 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(function(error) { + console.error("ERROR: Failed to load fuzzy search", error); }); - search(query.value, data.items, options); - }).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 = '
  • '.concat(escape(term), " ").concat(separator, " No Results Found
  • "); - 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)), "", ""); - if (highlight === null) { - highlight = title; + 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 = '
  • '.concat(escape(term), " ").concat(separator, " No Results Found
  • "); + 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)), "", ""); + if (highlight === null) highlight = title; + items = items + '\n
  • \n').concat(highlight, "\n
  • \n"); } - items = items + '\n
  • \n').concat(highlight, "\n
  • \n"); } + dropdown.innerHTML = items; } - dropdown.innerHTML = items; - } + }); }); })(); (function() { @@ -667,7 +673,7 @@ style: "long" }); function viewport(element, options = { - offset: 100 + 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; @@ -745,8 +751,13 @@ } }; const substitution = setInterval(date, 4); - self.addEventListener("scroll", function() { - date("viewport"); + [ + "scroll", + "URLChangedCustomEvent" + ].forEach(function(event) { + self.addEventListener(event, function() { + date("viewport"); + }); }); self.addEventListener("DOMContentLoaded", function() { setTimeout(function() { -- cgit v1.2.3