aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortdro <tdro@noreply.example.com>2024-08-14 00:00:00 +0000
committertdro <tdro@noreply.example.com>2024-08-14 00:00:00 +0000
commit99dcd03662cad97e37c735fb8f4b983204bc88cb (patch)
tree2330d772cd8da4c021b35d8b7d3c8b7f9e505479
parent0475142d247f358fa1def8fd04bda44ed0236d18 (diff)
downloadcanory-99dcd03662cad97e37c735fb8f4b983204bc88cb.tar.gz
canory-99dcd03662cad97e37c735fb8f4b983204bc88cb.tar.bz2
canory-99dcd03662cad97e37c735fb8f4b983204bc88cb.zip
static/js/fixedsearch: Clean up
-rw-r--r--assets/js/index.js138
-rw-r--r--static/js/fixedsearch.ts212
2 files changed, 158 insertions, 192 deletions
diff --git a/assets/js/index.js b/assets/js/index.js
index d64165a..0daf7d5 100644
--- a/assets/js/index.js
+++ b/assets/js/index.js
@@ -315,32 +315,44 @@
};
const submit = Submit();
function first(element) {
- if (element.firstChild.nextElementSibling) return element.firstChild.nextElementSibling.firstChild.nextElementSibling;
+ if (element) return element.firstElementChild;
}
function last(element) {
- return element.lastElementChild.firstChild.nextElementSibling;
+ if (element) return element.lastElementChild;
}
function next(element) {
- return element.activeElement.parentElement.nextElementSibling.firstChild.nextElementSibling.focus();
+ return element.parentElement.nextElementSibling.querySelector("a").focus();
}
function previous(element) {
- return element.activeElement.parentElement.previousElementSibling.firstChild.nextElementSibling.focus();
+ return element.parentElement.previousElementSibling.querySelector("a").focus();
}
function press(keyname) {
- document.dispatchevent(new keyboardevent("keydown", {
+ document.dispatchEvent(new KeyboardEvent("keydown", {
"key": keyname
}));
}
+ const Action = {
+ cancel: function() {
+ Dropdown().setAttribute("hidden", "");
+ Container().removeAttribute("data-focus");
+ },
+ reveal: function() {
+ Dropdown().removeAttribute("hidden");
+ Container().setAttribute("data-focus", "");
+ }
+ };
if (submit === null) return;
let selected;
submit.addEventListener("click", function(event) {
+ press("ArrowDown");
+ container.setAttribute("data-focus", "");
+ initialize();
if (selected) {
event.preventDefault();
selected.focus();
return selected.click();
}
- first(dropdown).focus();
- press("ArrowDown");
+ first(dropdown).querySelector("a").focus();
document.activeElement.click();
});
[
@@ -348,9 +360,7 @@
"click"
].forEach(function(event) {
form.addEventListener(event, function() {
- if (document.activeElement.nodeName === "A") {
- return selected = document.activeElement;
- }
+ if (document.activeElement.nodeName === "A") return selected = document.activeElement;
selected = undefined;
});
});
@@ -363,56 +373,52 @@
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 (document.activeElement == query) first(dropdown).querySelector("a").focus();
+ else if (document.activeElement == last(dropdown).querySelector("a")) query.focus();
+ else next(document.activeElement);
+ return;
}
if (event.keyCode == 38) {
event.preventDefault();
- if (document.activeElement == query) tail.focus();
- else if (document.activeElement == head) query.focus();
- else previous(document);
+ if (document.activeElement == query) last(dropdown).querySelector("a").focus();
+ else if (document.activeElement == first(dropdown).querySelector("a")) query.focus();
+ else previous(document.activeElement);
+ return;
}
if (event.keyCode == 13) {
if (dropdown && document.activeElement == query) {
event.preventDefault();
- head.focus();
- head.click();
+ first(dropdown).querySelector("a").focus();
+ first(dropdown).querySelector("a").click();
+ }
+ return;
+ }
+ if (form.contains(event.target)) {
+ if (event.keyCode == 27) {
+ event.preventDefault();
+ document.activeElement.blur();
+ return Action.cancel();
}
}
+ if (document.activeElement != query) {
+ query.focus();
+ }
});
if (event === "DOMContentLoaded") {
let scrolls = 0;
self.addEventListener("scroll", function() {
- if (scrolls > 3) {
+ if (scrolls > 75) {
scrolls = 0;
document.activeElement.blur();
- Dropdown().setAttribute("hidden", "");
- Container().removeAttribute("data-focus");
+ Action.cancel();
}
scrolls++;
});
self.addEventListener("click", function(event) {
if (!Form().contains(event.target) && !(document.activeElement === Query()) && !(document.activeElement === Submit())) {
- Dropdown().setAttribute("hidden", "");
- Container().removeAttribute("data-focus");
+ Action.cancel();
}
});
}
@@ -429,14 +435,14 @@
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);
+ if (document.currentScript) document.currentScript.parentNode.insertBefore(script, document.currentScript);
+ else document.head.appendChild(script);
script.src = url;
});
}
let data = {};
let boot = true;
+ let origin = document.querySelector("meta[name='base-url']");
const options = {
key: [
"title"
@@ -447,25 +453,24 @@
}
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);
+ 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) {
+ boot = false;
+ if (origin) origin = origin.content.replace(/\/+$/, "");
+ else origin = window.location.origin;
+ script(origin + "/js/fuzzysort.js").then(function() {
+ fetch(origin + "/index.json", function(request) {
appendItemsTo({}, JSON.parse(request.responseText));
+ Action.reveal();
search("", data.items, options);
- boot = false;
});
[
"keyup",
@@ -482,7 +487,7 @@
}).catch(function(error) {
console.error("ERROR: Failed to load fuzzy search", error);
});
- }
+ } else Action.reveal();
}
function escape(text) {
const escaped = document.createElement("textarea");
@@ -490,24 +495,33 @@
return escaped.innerHTML;
}
function search(term, data, options) {
- const results = fuzzysort.go(term, data, options);
+ if (typeof fuzzysort !== "object") return;
let items = "";
+ const results = fuzzysort.go(term, data, options);
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", "");
+ const li = document.createElement("li");
+ const a = document.createElement("a");
+ a.textContent = `${term} ${separator} No Results Found`;
+ li.appendChild(a);
+ items = li.outerHTML;
} else {
- dropdown.removeAttribute("hidden");
for(var string in results.slice(0, 10)){
const title = results[string].obj.title;
+ const href = results[string].obj.url;
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");
+ const li = document.createElement("li");
+ const a = document.createElement("a");
+ a.href = href;
+ a.tabIndex = 0;
+ a.innerHTML = highlight;
+ li.appendChild(a);
+ items = items + li.outerHTML;
}
}
- dropdown.innerHTML = items;
+ if (dropdown.innerHTML !== items) dropdown.innerHTML = items;
}
});
});
diff --git a/static/js/fixedsearch.ts b/static/js/fixedsearch.ts
index 9c56784..5ce648d 100644
--- a/static/js/fixedsearch.ts
+++ b/static/js/fixedsearch.ts
@@ -15,113 +15,82 @@
const Query = function () { return document.querySelector("search-box input") }; const query = Query();
const Submit = function () { return document.querySelector("search-box button") }; const submit = Submit();
- function first(element) {
- if (element.firstChild.nextElementSibling) return element.firstChild.nextElementSibling.firstChild.nextElementSibling;
- }
-
- function last(element) {
- return element.lastElementChild.firstChild.nextElementSibling;
- }
+ function first(element) { if (element) return element.firstElementChild; }
+ function last(element) { if (element) return element.lastElementChild; }
+ function next(element) { return element.parentElement.nextElementSibling.querySelector("a").focus(); }
+ function previous(element) { return element.parentElement.previousElementSibling.querySelector("a").focus(); }
+ function press(keyname) { document.dispatchEvent(new KeyboardEvent("keydown", { "key": keyname })); }
- 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 })); }
+ const Action = {
+ cancel: function () { Dropdown().setAttribute("hidden", ""); Container().removeAttribute("data-focus"); },
+ reveal: function () { Dropdown().removeAttribute("hidden"); Container().setAttribute("data-focus", ""); },
+ };
if (submit === null) return;
-
let selected;
submit.addEventListener("click", function (event) {
- if (selected) {
- event.preventDefault();
- selected.focus();
- return selected.click();
- }
- first(dropdown).focus();
press("ArrowDown");
+ container.setAttribute("data-focus", ""); initialize();
+ if (selected) { event.preventDefault(); selected.focus(); return selected.click(); }
+ first(dropdown).querySelector("a").focus();
document.activeElement.click();
});
["keyup", "click"].forEach(function (event) {
form.addEventListener(event, function () {
- if (document.activeElement.nodeName === "A") {
- return selected = document.activeElement;
- }
+ 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("focusin", function () { container.setAttribute("data-focus", ""); initialize(); });
+ form.addEventListener("submit", function (event) { event.preventDefault(); return false; });
form.addEventListener("keydown", function (event) {
- // ESC (27)
- if (form.contains(event.target)) {
- if (event.keyCode == 27) {
- document.activeElement.blur();
- dropdown.setAttribute("hidden", "");
- container.removeAttribute("data-focus");
- }
- }
-
- // BACKSPACE (8)
- if (event.keyCode == 8) {
- if (document.activeElement != query) {
- event.preventDefault();
- query.focus();
- }
- }
-
- const head = first(dropdown);
- const tail = last(dropdown);
-
- // DOWN (40)
- if (event.keyCode == 40) {
+ if (event.keyCode == 40) { // DOWN
event.preventDefault();
- if (document.activeElement == query) head.focus();
- else if (document.activeElement == tail) query.focus();
- else next(document);
+ if (document.activeElement == query) first(dropdown).querySelector("a").focus();
+ else if (document.activeElement == last(dropdown).querySelector("a")) query.focus();
+ else next(document.activeElement);
+ return;
}
- // UP (38)
- if (event.keyCode == 38) {
+ if (event.keyCode == 38) { // UP
event.preventDefault();
- if (document.activeElement == query) tail.focus();
- else if (document.activeElement == head) query.focus();
- else previous(document);
+ if (document.activeElement == query) last(dropdown).querySelector("a").focus();
+ else if (document.activeElement == first(dropdown).querySelector("a")) query.focus();
+ else previous(document.activeElement);
+ return;
}
- // ENTER (13)
- if (event.keyCode == 13) {
+ if (event.keyCode == 13) { // ENTER
if (dropdown && document.activeElement == query) {
event.preventDefault();
- head.focus();
- head.click();
+ first(dropdown).querySelector("a").focus();
+ first(dropdown).querySelector("a").click();
}
+ return;
}
+
+ if (form.contains(event.target)) {
+ if (event.keyCode == 27) { // ESC
+ event.preventDefault();
+ document.activeElement.blur();
+ return Action.cancel();
+ }
+ }
+
+ if (document.activeElement != query) { query.focus(); }
});
if (event === "DOMContentLoaded") {
let scrolls = 0;
self.addEventListener("scroll", function () {
- if (scrolls > 3) {
+ if (scrolls > 75) {
scrolls = 0;
document.activeElement.blur();
- Dropdown().setAttribute("hidden", "");
- Container().removeAttribute("data-focus");
+ Action.cancel();
}
scrolls++;
});
@@ -131,8 +100,7 @@
!(document.activeElement === Query()) &&
!(document.activeElement === Submit())
) {
- Dropdown().setAttribute("hidden", "");
- Container().removeAttribute("data-focus");
+ Action.cancel();
}
});
}
@@ -153,18 +121,15 @@
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);
+ if (document.currentScript) document.currentScript.parentNode.insertBefore(script, document.currentScript);
+ else document.head.appendChild(script);
script.src = url;
});
}
let data = {};
let boot = true;
+ let origin = document.querySelector("meta[name='base-url']");
const options = { key: ["title"] };
@@ -172,41 +137,33 @@
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);
+ 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(); }
- });
+ boot = false;
+ if (origin) origin = origin.content.replace(/\/+$/, "");
+ else origin = window.location.origin;
+ script(origin + "/js/fuzzysort.js")
+ .then(function () {
+ fetch(origin + "/index.json", function (request) {
+ appendItemsTo({}, JSON.parse(request.responseText));
+ Action.reveal();
+ search("", data.items, options);
+ });
+ ["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);
});
- }
+ }).catch(function (error) { console.error("ERROR: Failed to load fuzzy search", error); });
+ } else Action.reveal();
}
function escape(text) {
@@ -216,38 +173,33 @@
}
function search(term, data, options) {
- const results = fuzzysort.go(term, data, options);
+ if (typeof fuzzysort !== "object") return;
let items = "";
-
+ const results = fuzzysort.go(term, data, options);
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", "");
+ const li = document.createElement("li");
+ const a = document.createElement("a");
+ a.textContent = `${term} ${separator} No Results Found`;
+ li.appendChild(a);
+ items = li.outerHTML;
} 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>",
- );
-
+ const href = results[string].obj.url;
+ 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");
+ const li = document.createElement("li");
+ const a = document.createElement("a");
+ a.href = href;
+ a.tabIndex = 0;
+ a.innerHTML = highlight;
+ li.appendChild(a);
+ items = items + li.outerHTML;
}
}
- dropdown.innerHTML = items;
+ if (dropdown.innerHTML !== items) dropdown.innerHTML = items;
}
});
});