Add a spinner when search is in progress

This commit is contained in:
Guillaume Gomez 2025-02-21 14:25:58 +01:00
parent d64a863223
commit 2fa13cf4e0
5 changed files with 47 additions and 13 deletions

View file

@ -344,9 +344,34 @@ mark.fade-out {
max-width: var(--content-max-width); max-width: var(--content-max-width);
} }
#searchbar-outer.searching #searchbar {
padding-right: 30px;
}
#searchbar-outer .spinner-wrapper {
display: none;
}
#searchbar-outer.searching .spinner-wrapper {
display: block;
}
.search-wrapper {
position: relative;
}
.spinner-wrapper {
--spinner-margin: 2px;
position: absolute;
margin-block-start: calc(var(--searchbar-margin-block-start) + var(--spinner-margin));
right: var(--spinner-margin);
top: 0;
bottom: var(--spinner-margin);
padding: 6px;
background-color: var(--bg);
}
#searchbar { #searchbar {
width: 100%; width: 100%;
margin-block-start: 5px; margin-block-start: var(--searchbar-margin-block-start);
margin-block-end: 0; margin-block-end: 0;
margin-inline-start: auto; margin-inline-start: auto;
margin-inline-end: auto; margin-inline-end: auto;

View file

@ -11,6 +11,7 @@
--menu-bar-height: 50px; --menu-bar-height: 50px;
--mono-font: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace; --mono-font: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace;
--code-font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */ --code-font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */
--searchbar-margin-block-start: 5px;
} }
/* Themes */ /* Themes */

View file

@ -22,6 +22,7 @@ window.search = window.search || {};
} }
const search_wrap = document.getElementById('search-wrapper'), const search_wrap = document.getElementById('search-wrapper'),
searchbar_outer = document.getElementById('searchbar-outer'),
searchbar = document.getElementById('searchbar'), searchbar = document.getElementById('searchbar'),
searchresults = document.getElementById('searchresults'), searchresults = document.getElementById('searchresults'),
searchresults_outer = document.getElementById('searchresults-outer'), searchresults_outer = document.getElementById('searchresults-outer'),
@ -262,12 +263,13 @@ window.search = window.search || {};
doc_urls = config.doc_urls; doc_urls = config.doc_urls;
searchindex = elasticlunr.Index.load(config.index); searchindex = elasticlunr.Index.load(config.index);
searchbar.removeAttribute("disabled"); searchbar_outer.classList.remove('searching');
searchbar.focus(); searchbar.focus();
const searchterm = searchbar.value.trim(); const searchterm = searchbar.value.trim();
if (searchterm !== "") { if (searchterm !== '') {
searchbar.classList.add("active"); searchbar.classList.add('active');
doSearch(searchterm); doSearch(searchterm);
} }
} }
@ -414,10 +416,12 @@ window.search = window.search || {};
} }
} }
function loadScript(url, id) { function loadSearchScript(url, id) {
if (document.getElementById(id)) { if (document.getElementById(id)) {
return; return;
} }
searchbar_outer.classList.add('searching');
const script = document.createElement('script'); const script = document.createElement('script');
script.src = url; script.src = url;
script.id = id; script.id = id;
@ -430,7 +434,7 @@ window.search = window.search || {};
function showSearch(yes) { function showSearch(yes) {
if (yes) { if (yes) {
loadScript(path_to_root + '{{ resource "searchindex.js" }}', 'search-index'); loadSearchScript(path_to_root + '{{ resource "searchindex.js" }}', 'search-index');
search_wrap.classList.remove('hidden'); search_wrap.classList.remove('hidden');
searchicon.setAttribute('aria-expanded', 'true'); searchicon.setAttribute('aria-expanded', 'true');
} else { } else {
@ -511,10 +515,11 @@ window.search = window.search || {};
function doSearch(searchterm) { function doSearch(searchterm) {
// Don't search the same twice // Don't search the same twice
if (current_searchterm == searchterm) { if (current_searchterm === searchterm) {
return; return;
} }
if (searchindex == null) { searchbar_outer.classList.add('searching');
if (searchindex === null) {
return; return;
} }
@ -538,6 +543,7 @@ window.search = window.search || {};
// Display results // Display results
showResults(true); showResults(true);
searchbar_outer.classList.remove('searching');
} }
// Exported functions // Exported functions

View file

@ -186,7 +186,12 @@
{{#if search_enabled}} {{#if search_enabled}}
<div id="search-wrapper" class="hidden"> <div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer"> <form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header" disabled> <div class="search-wrapper">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
<div class="spinner-wrapper">
<i class="fa fa-spinner fa-spin"></i>
</div>
</div>
</form> </form>
<div id="searchresults-outer" class="searchresults-outer hidden"> <div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div> <div id="searchresults-header" class="searchresults-header"></div>

View file

@ -32,16 +32,13 @@ wait-for-text: ("#searchresults-header", "2 search results for 'strikethrough':"
// Now we test search shortcuts and more page changes. // Now we test search shortcuts and more page changes.
go-to: |DOC_PATH| + "index.html" go-to: |DOC_PATH| + "index.html"
// First we ensure that the search input is disabled and hidden.
assert: "#searchbar:disabled"
// This check is to ensure that the search bar is inside the search wrapper. // This check is to ensure that the search bar is inside the search wrapper.
assert: "#search-wrapper #searchbar" assert: "#search-wrapper #searchbar"
assert-css: ("#search-wrapper", {"display": "none"}) assert-css: ("#search-wrapper", {"display": "none"})
// Now we make the search input appear with the `S` shortcut. // Now we make the search input appear with the `S` shortcut.
press-key: 'S' press-key: 'S'
wait-for: "#searchbar:not(:disabled)" wait-for-css: ("#search-wrapper", {"display": "block"})
assert-css: ("#search-wrapper", {"display": "block"})
// We ensure the search bar has the focus. // We ensure the search bar has the focus.
assert: "#searchbar:focus" assert: "#searchbar:focus"