diff --git a/public/assets/css/search.css b/public/assets/css/search.css index 0440309..526ef42 100644 --- a/public/assets/css/search.css +++ b/public/assets/css/search.css @@ -60,6 +60,19 @@ header h1 { gap: var(--padding); } +#results > p { + text-align: center; +} + +#results > p.error { + color: red; +} + +#results > p.error::before { + content: "oh crap, "; + font-weight: bold; +} + .card { --padding-multiplier: 1.2; flex: none; @@ -130,6 +143,30 @@ header h1 { #search input:focus { outline: solid 5px rgba(var(--palette-contrast),.2); } + + /* ---- */ + + #results::-webkit-scrollbar { + width: 10px; + } + + #results::-webkit-scrollbar-track { + background-color: rgba(var(--palette-contrast),.04); + } + + #results::-webkit-scrollbar-thumb { + background: var(--swatch-contrast); + } + + #results::-webkit-scrollbar-thumb:hover { + background: var(--swatch-background); + outline: solid 2px rgba(var(--palette-contrast),1); + } + + #results::-webkit-scrollbar-thumb:active { + background: rgba(var(--palette-contrast),.1); + outline: solid 2px rgba(var(--palette-contrast),1); + } } @media (prefers-color-scheme: dark) { diff --git a/public/assets/js/modules/Search.mjs b/public/assets/js/modules/Search.mjs index e7f2dab..14d83ad 100644 --- a/public/assets/js/modules/Search.mjs +++ b/public/assets/js/modules/Search.mjs @@ -5,36 +5,76 @@ export default class Search { this.endpoint = new URL("api/search",window.location.href); this.lastQuery = ""; - this.timeout = null; + this.throttle = null; - this.results = { - element: results, - set content(html) { - this.results?.insertAdjacentHTML("beforeend",html); - } - }; - input?.addEventListener("keydown",event => this.keyEvent(event)) ?? false; + this.results = results; + this.input = input; + this.input?.addEventListener("keyup",event => this.keyEvent(event)) ?? false; + } + + clearResults() { + while(this.results.firstChild) { + this.results.removeChild(this.results.lastChild); + } + } + + output(html) { + this.clearResults(); + if(typeof html === "string") { + this.results.insertAdjacentHTML("beforeEnd",html); + return; + } + this.results.appendChild(html); + } + + status(text,classList = false) { + const element = document.createElement("p"); + if(classList !== false) { + element.classList = classList; + } + + element.innerText = text; + this.output(element); } async search(query) { const url = new URL(this.endpoint); url.searchParams.set("q",query); - const timeout = setTimeout(() => this.showSpinner(),1000); - const api = await fetch(url); - - return result; + const timeout = new Promise(reject => setTimeout(() => reject("Request timed out"),3000)); + const api = fetch(url); + + const result = Promise.race([api,timeout]); + result.then(response => { + if(!response.ok) { + this.status("something went wrong on my side","error"); + console.error("Response from server:",response); + return; + } + this.output(response.text); + }); + result.catch(error => this.status(error,"error")); } + // Wait until the user stops typing for a few miliseconds queue(query) { - clearTimeout(this.timeout); - this.timeout = setTimeout(() => this.search(query),500); + clearTimeout(this.throttle); + this.throttle = setTimeout(() => this.search(query),500); } async keyEvent(event) { - if(event.target.value === this.lastQuery) { + const query = event.target.value; + if(query.length < 1) { + this.status("search results will appear here as you type"); + return; + } + + if(query === this.lastQuery) { return false; } - this.queue(event.target.value); + + this.lastQuery = query; + this.status("searching.."); + this.queue(query); } } \ No newline at end of file diff --git a/public/assets/js/search.js b/public/assets/js/search.js index 01011be..5294587 100644 --- a/public/assets/js/search.js +++ b/public/assets/js/search.js @@ -1,25 +1,7 @@ import { default as Search } from "./modules/Search.mjs"; -// import { default as Monkey } from "./modules/monkeydo/Monkeydo.mjs"; -const searchField = document.getElementById("search"); +const searchBox = document.getElementById("search")?.children[0] ?? false; const resultsContainer = document.getElementById("results"); -const search = new Search(searchField,resultsContainer); -window.addEventListener("keydown",() => searchField.focus()); - -/* const monkey = new Monkey({ - keyPress: (key) => searchField.dispatchEvent(new KeyboardEvent("keydown",{"key":key})), - log: (message) => console.log(message) -}); - -monkey.load(JSON.stringify({ - tasks: [ - [200,"log","hello friend"], - [200,"keyPress","h"], - [400,"keyPress","e"], - [100,"keyPress","l"], - [500,"keyPress","l"], - [700,"keyPress","o"] - ] -})).then(() => monkey.do()); -*/ \ No newline at end of file +new Search(searchBox,resultsContainer); +window.addEventListener("keydown",() => searchBox.focus()); \ No newline at end of file diff --git a/public/search.html b/public/search.html index a8cc2c0..a39ed83 100644 --- a/public/search.html +++ b/public/search.html @@ -18,22 +18,15 @@
-
+ +

search results will appear here as you type