From a9c6ab86f6f44253a61f17316801b01facf458a9 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Mon, 9 Dec 2024 10:27:01 +0300 Subject: [PATCH] docs: add search widget to options page --- docs/manual.nix | 4 +++- docs/static/script/search.js | 39 ++++++++++++++++++++++++++++++++++++ docs/static/style.scss | 18 +++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 docs/static/script/search.js diff --git a/docs/manual.nix b/docs/manual.nix index 113fb78..4becdf2 100644 --- a/docs/manual.nix +++ b/docs/manual.nix @@ -62,7 +62,8 @@ in # Copy anchor scripts to the script directory in document root. cp -vt "$dest"/script \ ${./static/script}/anchor-min.js \ - ${./static/script}/anchor-use.js + ${./static/script}/anchor-use.js \ + ${./static/script}/search.js substituteInPlace ./options.md \ --subst-var-by OPTIONS_JSON ./config-options.json @@ -100,6 +101,7 @@ in --script highlightjs/loader.js \ --script script/anchor-use.js \ --script script/anchor-min.js \ + --script script/search.js \ --toc-depth 2 \ --section-toc-depth 1 \ manual.md \ diff --git a/docs/static/script/search.js b/docs/static/script/search.js new file mode 100644 index 0000000..618ec4a --- /dev/null +++ b/docs/static/script/search.js @@ -0,0 +1,39 @@ +document.addEventListener("DOMContentLoaded", () => { + // The search widget should only be visible if we're in the options page. Else, we + // want it hidden. + if (window.location.pathname.endsWith("options.html")) { + const searchBar = document.createElement("div"); + searchBar.id = "search-bar"; + searchBar.innerHTML = ` + +
+ `; + + document.body.prepend(searchBar); + + const dtElements = document.querySelectorAll("dt"); + const ddElements = document.querySelectorAll("dd"); + + if (dtElements.length === 0 || ddElements.length === 0) { + console.warn( + "No
or
elements found. Ensure your HTML contains the correct structure.", + ); + } + + // handle input and filter visible options + document + .getElementById("search-input") + .addEventListener("input", (event) => { + const query = event.target.value.toLowerCase(); + dtElements.forEach((dt, index) => { + const optionId = + dt.querySelector("a")?.id.toLowerCase() || ""; + const isMatch = optionId.includes(query); + + // toggle visibility based on the query match + dt.classList.toggle("hidden", !isMatch); + ddElements[index]?.classList.toggle("hidden", !isMatch); + }); + }); + } +}); diff --git a/docs/static/style.scss b/docs/static/style.scss index 718302f..3b14873 100644 --- a/docs/static/style.scss +++ b/docs/static/style.scss @@ -233,6 +233,24 @@ li { } } +#search-bar { + position: sticky; + top: 0; + background: white; + padding: 10px; + border-bottom: 1px solid #ccc; + z-index: 1000; +} +#search-input { + width: 100%; + padding: 8px; + border: 1px solid #ccc; + border-radius: 4px; +} +.hidden { + display: none; +} + div.titlepage { margin: 40px 0;