diff options
| author | tdro <tdro@noreply.example.com> | 2024-08-14 00:00:00 +0000 |
|---|---|---|
| committer | tdro <tdro@noreply.example.com> | 2024-08-14 00:00:00 +0000 |
| commit | 99dcd03662cad97e37c735fb8f4b983204bc88cb (patch) | |
| tree | 2330d772cd8da4c021b35d8b7d3c8b7f9e505479 | |
| parent | 0475142d247f358fa1def8fd04bda44ed0236d18 (diff) | |
| download | canory-99dcd03662cad97e37c735fb8f4b983204bc88cb.tar.gz canory-99dcd03662cad97e37c735fb8f4b983204bc88cb.tar.bz2 canory-99dcd03662cad97e37c735fb8f4b983204bc88cb.zip | |
static/js/fixedsearch: Clean up
| -rw-r--r-- | assets/js/index.js | 138 | ||||
| -rw-r--r-- | static/js/fixedsearch.ts | 212 |
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; } }); }); |
