zephyr/doc/_templates/searchbox.html
Benjamin Cabé 7e253ff937 doc: Make search engine configurable
Add UI to select preferred search engine when Google Programmable Search is
enabled. The user's preference is saved using local storage.

This also makes the search input field of type "search" for better UX (in
particular on mobile).

Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2023-12-15 04:34:48 -05:00

130 lines
4.8 KiB
HTML

{#
Override the default searchbox from RTD theme to provide the ability to select a search method
(ex. built-in search, Google Custom Search, ...)
#}
{%- if ('singlehtml' not in builder) %}
<div class="search-container" role="search">
<form id="rtd-search-form" class="wy-form" action="{{ pathto('search') }}" method="get">
<input type="search" name="q" placeholder="{{ _('Search docs') }}"
aria-label="{{ _('Search docs') }}" />
{%- if google_searchengine_id is defined %}
<span id="search-se-settings-icon" class="fa fa-gear" role="button" tabindex="0"
title="Search settings" aria-label="Search settings"
aria-haspopup="true" aria-controls="search-se-menu" aria-expanded="false"
onclick="toggleSearchEngineSettingsMenu()">
</span>
<div id="search-se-menu" role="menu" aria-labelledby="search-se-settings-icon">
<ul>
<li id="search-se-menuitem-sphinx" role="menuitemradio" tabindex="-1"
aria-label="Built-in search" onclick="switchSearchEngine('sphinx')">
Built-in search <span class="fa fa-check">
</li>
<li id="search-se-menuitem-google" role="menuitemradio" tabindex="-1"
aria-label="Google search" onclick="switchSearchEngine('google')">
Google search <span class="fa fa-check">
</li>
</div>
{%- endif %}
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
{%- if google_searchengine_id is defined %}
<script>
(function () {
var form = document.getElementById("rtd-search-form");
var searchMenu = document.getElementById("search-se-menu");
var isBrowsingLatest = window.location.pathname.startsWith("/latest");
var preferenceKey = "search-se-" + (isBrowsingLatest ? "latest" : "default");
var query = new URLSearchParams(window.location.search).get("q");
if (query !== null) {
form.q.value = query;
form.q.focus();
}
// Load the saved search preference. Defaults to Google when browsing "/latest" documentation,
// built-in Sphinx search otherwise.
var engine = localStorage.getItem(preferenceKey);
if (engine === null) {
engine = isBrowsingLatest ? "google" : "sphinx";
}
setActiveSearchEngine(engine);
setSearchEngineSettingsMenuVisibility = function (visible) {
searchMenu.style.display = visible ? "block" : "none";
document
.getElementById("search-se-settings-icon")
.setAttribute("aria-expanded", visible ? "true" : "false");
};
window.toggleSearchEngineSettingsMenu = function () {
isVisible = searchMenu.style.display === "block";
setSearchEngineSettingsMenuVisibility(!isVisible);
};
function setActiveSearchEngine(engine) {
if(engine === "sphinx") {
form.action = "{{ pathto('search') }}";
form.q.placeholder = "Search docs (built-in search)";
} else {
form.action = "{{ pathto('gsearch') }}";
form.q.placeholder = "Search docs (powered by Google)";
}
var selectedElement = document.getElementById("search-se-menuitem-" + engine);
var otherElement = document.getElementById(
"search-se-menuitem-" + (engine === "sphinx" ? "google" : "sphinx")
);
selectedElement.classList.add("selected");
selectedElement.setAttribute("aria-checked", "true");
otherElement.classList.remove("selected");
otherElement.setAttribute("aria-checked", "false");
}
window.switchSearchEngine = function (engine) {
setActiveSearchEngine(engine);
localStorage.setItem(preferenceKey, engine);
setSearchEngineSettingsMenuVisibility(false);
form.q.focus();
if (form.q.value !== "") {
form.submit();
}
};
// Close the dropdown if the user clicks outside of it
window.onclick = function (event) {
if (!event.target.matches("#search-se-settings-icon")) {
if (searchMenu.style.display === "block") {
setSearchEngineSettingsMenuVisibility(false);
}
}
};
document.addEventListener("keydown", function (event) {
if(searchMenu.style.display === "none") return;
let menuItems = document.querySelectorAll('[role="menuitemradio"]');
let currentIndex = Array.from(menuItems).findIndex((item) => item === document.activeElement);
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
let nextIndex = event.key === "ArrowDown" ? currentIndex + 1 : currentIndex - 1;
if (nextIndex >= menuItems.length) nextIndex = 0;
if (nextIndex < 0) nextIndex = menuItems.length - 1;
menuItems[nextIndex].focus();
event.preventDefault();
} else if (event.key === "Enter") {
let activeItem = document.activeElement;
if (activeItem && activeItem.getAttribute("role") === "menuitemradio") {
activeItem.click();
event.preventDefault();
}
}
});
})();
</script>
{%- endif %}
{%- endif %}