1{# 2 Override the default searchbox from RTD theme to provide the ability to select a search method 3 (ex. built-in search, Google Custom Search, ...) 4#} 5{%- if ('singlehtml' not in builder) %} 6<div class="search-container" role="search"> 7 <form id="rtd-search-form" class="wy-form" action="{{ pathto('search') }}" method="get"> 8 <input type="search" name="q" placeholder="{{ _('Search docs') }}" 9 aria-label="{{ _('Search docs') }}" /> 10 {%- if google_searchengine_id is defined %} 11 <span id="search-se-settings-icon" class="fa fa-gear" role="button" tabindex="0" 12 title="Search settings" aria-label="Search settings" 13 aria-haspopup="true" aria-controls="search-se-menu" aria-expanded="false" 14 onclick="toggleSearchEngineSettingsMenu()"> 15 </span> 16 <div id="search-se-menu" role="menu" aria-labelledby="search-se-settings-icon"> 17 <ul> 18 <li id="search-se-menuitem-sphinx" role="menuitemradio" tabindex="-1" 19 aria-label="Built-in search" onclick="switchSearchEngine('sphinx')"> 20 Built-in search <span class="fa fa-check"> 21 </li> 22 <li id="search-se-menuitem-google" role="menuitemradio" tabindex="-1" 23 aria-label="Google search" onclick="switchSearchEngine('google')"> 24 Google search <span class="fa fa-check"> 25 </li> 26 </div> 27 {%- endif %} 28 <input type="hidden" name="check_keywords" value="yes" /> 29 <input type="hidden" name="area" value="default" /> 30 </form> 31</div> 32{%- if google_searchengine_id is defined %} 33<script> 34(function () { 35 var form = document.getElementById("rtd-search-form"); 36 var searchMenu = document.getElementById("search-se-menu"); 37 var isBrowsingLatest = window.location.pathname.startsWith("/latest"); 38 var preferenceKey = "search-se-" + (isBrowsingLatest ? "latest" : "default"); 39 var query = new URLSearchParams(window.location.search).get("q"); 40 41 if (query !== null) { 42 form.q.value = query; 43 form.q.focus(); 44 } 45 46 // Load the saved search preference. Defaults to Google when browsing "/latest" documentation, 47 // built-in Sphinx search otherwise. 48 var engine = localStorage.getItem(preferenceKey); 49 if (engine === null) { 50 engine = isBrowsingLatest ? "google" : "sphinx"; 51 } 52 setActiveSearchEngine(engine); 53 54 setSearchEngineSettingsMenuVisibility = function (visible) { 55 searchMenu.style.display = visible ? "block" : "none"; 56 document 57 .getElementById("search-se-settings-icon") 58 .setAttribute("aria-expanded", visible ? "true" : "false"); 59 }; 60 setSearchEngineSettingsMenuVisibility(false); 61 62 window.toggleSearchEngineSettingsMenu = function () { 63 isVisible = searchMenu.style.display === "block"; 64 setSearchEngineSettingsMenuVisibility(!isVisible); 65 }; 66 67 function setActiveSearchEngine(engine) { 68 if(engine === "sphinx") { 69 form.action = "{{ pathto('search') }}"; 70 form.q.placeholder = "Search docs (built-in search)"; 71 } else { 72 form.action = "{{ pathto('gsearch') }}"; 73 form.q.placeholder = "Search docs (powered by Google)"; 74 } 75 76 var selectedElement = document.getElementById("search-se-menuitem-" + engine); 77 var otherElement = document.getElementById( 78 "search-se-menuitem-" + (engine === "sphinx" ? "google" : "sphinx") 79 ); 80 81 selectedElement.classList.add("selected"); 82 selectedElement.setAttribute("aria-checked", "true"); 83 otherElement.classList.remove("selected"); 84 otherElement.setAttribute("aria-checked", "false"); 85 } 86 87 window.switchSearchEngine = function (engine) { 88 setActiveSearchEngine(engine); 89 localStorage.setItem(preferenceKey, engine); 90 setSearchEngineSettingsMenuVisibility(false); 91 form.q.focus(); 92 if (form.q.value !== "") { 93 form.submit(); 94 } 95 }; 96 97 // Close the dropdown if the user clicks outside of it 98 window.onclick = function (event) { 99 if (!event.target.matches("#search-se-settings-icon")) { 100 if (searchMenu.style.display === "block") { 101 setSearchEngineSettingsMenuVisibility(false); 102 } 103 } 104 }; 105 106 document.addEventListener("keydown", function (event) { 107 if(searchMenu.style.display === "none") return; 108 109 let menuItems = document.querySelectorAll('[role="menuitemradio"]'); 110 let currentIndex = Array.from(menuItems).findIndex((item) => item === document.activeElement); 111 112 if (event.key === "ArrowDown" || event.key === "ArrowUp") { 113 let nextIndex = event.key === "ArrowDown" ? currentIndex + 1 : currentIndex - 1; 114 115 if (nextIndex >= menuItems.length) nextIndex = 0; 116 if (nextIndex < 0) nextIndex = menuItems.length - 1; 117 118 menuItems[nextIndex].focus(); 119 event.preventDefault(); 120 } else if (event.key === "Enter") { 121 let activeItem = document.activeElement; 122 if (activeItem && activeItem.getAttribute("role") === "menuitemradio") { 123 activeItem.click(); 124 event.preventDefault(); 125 } 126 } 127 }); 128})(); 129</script> 130{%- endif %} 131{%- endif %}