aboutsummaryrefslogtreecommitdiff
path: root/assets
diff options
context:
space:
mode:
authortdro <tdro@noreply.example.com>2024-01-13 20:33:21 -0500
committertdro <tdro@noreply.example.com>2024-01-13 20:33:21 -0500
commit30d33a9eedca8ae4b2e6082b915579c309f8b52c (patch)
tree3ade16a8c0ff1fa5d701d8bb8f0ad10701142b2d /assets
parent0e7a8c8c1984f5394fd825ac9405679648c88e99 (diff)
downloadcanory-30d33a9eedca8ae4b2e6082b915579c309f8b52c.tar.gz
canory-30d33a9eedca8ae4b2e6082b915579c309f8b52c.tar.bz2
canory-30d33a9eedca8ae4b2e6082b915579c309f8b52c.zip
static/js: Prepare custom URL changed event
Set key on pager and always clear interval
Diffstat (limited to 'assets')
-rw-r--r--assets/js/index.js419
1 files changed, 215 insertions, 204 deletions
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 = '<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;
+ 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");
}
- items = items + '\n<li>\n<a href="'.concat(results[string].obj.url, '" tabindex="0">').concat(highlight, "</a>\n</li>\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() {