/** * This module is used to handle user's interaction with the search form. */ import { DeclarationDataCenter } from "./declaration-data.js"; const SEARCH_FORM = document.querySelector("#search_form"); const SEARCH_INPUT = SEARCH_FORM.querySelector("input[name=q]"); // Create an `div#search_results` to hold all search results. let sr = document.createElement("div"); sr.id = "search_results"; SEARCH_FORM.appendChild(sr); /** * Attach `selected` class to the the selected search result. */ function handleSearchCursorUpDown(down) { const sel = sr.querySelector(`.selected`); if (sel) { sel.classList.remove("selected"); const toSelect = down ? sel.nextSibling || sr.firstChild : sel.previousSibling || sr.lastChild; toSelect && toSelect.classList.add("selected"); } else { const toSelect = down ? sr.firstChild : sr.lastChild; toSelect && toSelect.classList.add("selected"); } } /** * Perform search (when enter is pressed). */ function handleSearchEnter() { const sel = sr.querySelector(`.selected`) || sr.firstChild; sel.click(); } /** * Allow user to navigate search results with up/down arrow keys, and choose with enter. */ SEARCH_INPUT.addEventListener("keydown", (ev) => { switch (ev.key) { case "Down": case "ArrowDown": ev.preventDefault(); handleSearchCursorUpDown(true); break; case "Up": case "ArrowUp": ev.preventDefault(); handleSearchCursorUpDown(false); break; case "Enter": ev.preventDefault(); handleSearchEnter(); break; } }); /** * Remove all children of a DOM node. */ function removeAllChildren(node) { while (node.firstChild) { node.removeChild(node.lastChild); } } /** * Search autocompletion. */ SEARCH_INPUT.addEventListener("input", async (ev) => { const text = ev.target.value; // If no input clear all. if (!text) { sr.removeAttribute("state"); removeAllChildren(sr); return; } // searching sr.setAttribute("state", "loading"); const dataCenter = await DeclarationDataCenter.init(); const result = dataCenter.search(text, false); // in case user has updated the input. if (ev.target.value != text) return; // update search results removeAllChildren(sr); for (const { name, docLink } of result) { const d = sr.appendChild(document.createElement("a")); d.innerText = name; d.title = name; d.href = docLink; } sr.setAttribute("state", "done"); });