Autodoc: add preference for / search

Closes #16081
This commit is contained in:
Ian Johnson 2023-06-27 00:19:40 -04:00 committed by Loris Cro
parent 7166407d8f
commit 4dacaa1e12
2 changed files with 158 additions and 43 deletions

View File

@ -25,8 +25,8 @@
--search-bg-color-focus: #ffffff;
--search-sh-color: rgba(0, 0, 0, 0.18);
--search-other-results-color: rgb(100, 100, 100);
--help-sh-color: rgba(0, 0, 0, 0.75);
--help-bg-color: #aaa;
--modal-sh-color: rgba(0, 0, 0, 0.75);
--modal-bg-color: #aaa;
}
html, body { margin: 0; padding: 0; height: 100%; }
@ -99,7 +99,7 @@
flex-shrink: 1;
}
.help-modal {
.modal-container {
z-index: 400;
}
@ -412,8 +412,8 @@
padding: 1px 1em;
}
/* help modal */
.help-modal {
/* modals */
.modal-container {
display: flex;
width: 100%;
height: 100%;
@ -426,29 +426,36 @@
backdrop-filter: blur(0.3em);
}
.help-modal > .modal {
.modal-container > .modal {
max-width: 97vw;
max-height: 97vh;
overflow: auto;
font-size: 1rem;
color: #fff;
background-color: var(--help-bg-color);
background-color: var(--modal-bg-color);
border: 0.125rem solid #000;
box-shadow: 0 0.5rem 2.5rem 0.3rem var(--help-sh-color);
box-shadow: 0 0.5rem 2.5rem 0.3rem var(--modal-sh-color);
}
.help-modal h1 {
.modal-container h1 {
margin: 0.75em 2.5em 1em 2.5em;
font-size: 1.5em;
text-align: center;
}
.help-modal dt, .help-modal dd {
.modal-container dt, .modal-container dd {
display: inline;
margin: 0 0.2em;
}
.help-modal dl {
.modal-container dl {
margin-left: 0.5em;
margin-right: 0.5em;
}
.prefs-list {
list-style: none;
padding: 0;
margin-left: 0.5em;
margin-right: 0.5em;
}
@ -539,8 +546,8 @@
--search-bg-color-focus: #000;
--search-sh-color: rgba(255, 255, 255, 0.28);
--search-other-results-color: rgba(255, 255, 255, 0.28);
--help-sh-color: rgba(142, 142, 142, 0.5);
--help-bg-color: #333;
--modal-sh-color: rgba(142, 142, 142, 0.5);
--modal-bg-color: #333;
}
.docs pre {
@ -677,13 +684,13 @@
</style>
</head>
<body class="canvas">
<div class="banner">
<div id="banner" class="banner">
This is a beta autodoc build; expect bugs and missing information.
<a href="https://github.com/ziglang/zig/wiki/How-to-contribute-to-Autodoc">Report an Issue</a>,
<a href="https://github.com/ziglang/zig/wiki/How-to-contribute-to-Autodoc">Contribute</a>,
<a href="https://github.com/ziglang/zig/wiki/How-to-read-the-standard-library-source-code">Learn more about stdlib source code</a>.
</div>
<div class="flex-main">
<div id="main" class="flex-main">
<div class="flex-filler"></div>
<div class="flex-left sidebar">
<nav>
@ -758,7 +765,7 @@
<div class="wrap">
<section class="docs" style="padding-top: 1.5rem; padding-bottom:0;">
<div style="position: relative">
<span id="searchPlaceholder"><kbd>/</kbd> or <kbd>s</kbd> to search, <kbd>?</kbd> for more options</span>
<span id="searchPlaceholder"><!-- populated by setPrefSlashSearch --></span>
<input type="search" class="search" id="search" autocomplete="off" spellcheck="false" disabled>
</div>
</section>
@ -872,20 +879,31 @@
</div>
</div>
<div id="helpModal" class="hidden">
<div class="help-modal">
<div class="modal-container">
<div class="modal">
<h1>Keyboard Shortcuts</h1>
<dl><dt><kbd>?</kbd></dt><dd>Toggle this help modal</dd></dl>
<dl><dt><kbd>s</kbd> or <kbd>/</kbd></dt><dd>Focus the search field</dd></dl>
<dl><dt id="searchKeys"><!-- populated by setPrefSlashSearch --></dt><dd>Focus the search field</dd></dl>
<div style="margin-left: 1em">
<dl><dt><kbd></kbd></dt><dd>Move up in search results</dd></dl>
<dl><dt><kbd></kbd></dt><dd>Move down in search results</dd></dl>
<dl><dt><kbd></kbd></dt><dd>Go to active search result</dd></dl>
</div>
<dl><dt><kbd>p</kbd></dt><dd>Open preferences</dd></dl>
<dl><dt><kbd>Esc</kbd></dt><dd>Clear focus; close this modal</dd></dl>
</div>
</div>
</div>
<div id="prefsModal" class="hidden">
<div class="modal-container">
<div class="modal">
<h1>Preferences</h1>
<ul class="prefs-list">
<li><input id="prefSlashSearch" type="checkbox"><label for="prefSlashSearch">Enable <kbd>/</kbd> for search</label></li>
</ul>
</div>
</div>
</div>
<script src="data.js"></script>
<script src="commonmark.js"></script>
<script src="main.js"></script>

View File

@ -8,6 +8,8 @@ const NAV_MODES = {
};
(function () {
const domBanner = document.getElementById("banner");
const domMain = document.getElementById("main");
const domStatus = document.getElementById("status");
const domSectNav = document.getElementById("sectNav");
const domListNav = document.getElementById("listNav");
@ -65,10 +67,18 @@ const NAV_MODES = {
const domTdZigVer = document.getElementById("tdZigVer");
const domHdrName = document.getElementById("hdrName");
const domHelpModal = document.getElementById("helpModal");
const domSearchKeys = document.getElementById("searchKeys");
const domPrefsModal = document.getElementById("prefsModal");
const domSearchPlaceholder = document.getElementById("searchPlaceholder");
const sourceFileUrlTemplate = "src/{{mod}}/{{file}}.html#L{{line}}"
const domLangRefLink = document.getElementById("langRefLink");
const domPrefSlashSearch = document.getElementById("prefSlashSearch");
const prefs = getLocalStorage();
loadPrefs();
domPrefSlashSearch.addEventListener("change", () => setPrefSlashSearch(domPrefSlashSearch.checked));
let searchTimer = null;
let searchTrimResults = true;
@ -127,21 +137,21 @@ const NAV_MODES = {
window.guideSearch = guidesSearchIndex;
parseGuides();
// identifiers can contain '?' so we want to allow typing
// the question mark when the search is focused instead of toggling the help modal
let canToggleHelpModal = true;
// identifiers can contain modal trigger characters so we want to allow typing
// such characters when the search is focused instead of toggling the modal
let canToggleModal = true;
domSearch.disabled = false;
domSearch.addEventListener("keydown", onSearchKeyDown, false);
domSearch.addEventListener("input", onSearchInput, false);
domSearch.addEventListener("focus", ev => {
domSearchPlaceholder.classList.add("hidden");
canToggleHelpModal = false;
canToggleModal = false;
});
domSearch.addEventListener("blur", ev => {
if (domSearch.value.length == 0)
domSearchPlaceholder.classList.remove("hidden");
canToggleHelpModal = true;
canToggleModal = true;
});
domSectSearchAllResultsLink.addEventListener('click', onClickSearchShowAllResults, false);
function onClickSearchShowAllResults(ev) {
@ -156,10 +166,13 @@ const NAV_MODES = {
}
// make the modal disappear if you click outside it
domHelpModal.addEventListener("click", ev => {
if (ev.target.className == "help-modal")
domHelpModal.classList.add("hidden");
});
function handleModalClick(ev) {
if (ev.target.classList.contains("modal-container")) {
hideModal(this);
}
}
domHelpModal.addEventListener("click", handleModalClick);
domPrefsModal.addEventListener("click", handleModalClick);
window.addEventListener("hashchange", onHashChange, false);
window.addEventListener("keydown", onWindowKeyDown, false);
@ -3996,8 +4009,12 @@ function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) {
// hide the modal if it's visible or return to the previous result page and unfocus the search
function onEscape(ev) {
if (!domHelpModal.classList.contains("hidden")) {
domHelpModal.classList.add("hidden");
if (isModalVisible(domHelpModal)) {
hideModal(domHelpModal);
ev.preventDefault();
ev.stopPropagation();
} else if (isModalVisible(domPrefsModal)) {
hideModal(domPrefsModal);
ev.preventDefault();
ev.stopPropagation();
} else {
@ -4110,8 +4127,10 @@ function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) {
onEscape(ev);
break;
case "/":
if (!getPrefSlashSearch()) break;
// fallthrough
case "s":
if (domHelpModal.classList.contains("hidden")) {
if (!isModalVisible(domHelpModal) && !isModalVisible(domPrefsModal)) {
if (ev.target == domSearch) break;
domSearch.focus();
@ -4123,28 +4142,65 @@ function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) {
}
break;
case "?":
if (!canToggleHelpModal) break;
if (!canToggleModal) break;
if (isModalVisible(domPrefsModal)) {
hideModal(domPrefsModal);
}
// toggle the help modal
if (!domHelpModal.classList.contains("hidden")) {
onEscape(ev);
if (isModalVisible(domHelpModal)) {
hideModal(domHelpModal);
} else {
ev.preventDefault();
ev.stopPropagation();
showHelpModal();
showModal(domHelpModal);
}
ev.preventDefault();
ev.stopPropagation();
break;
case "p":
if (!canToggleModal) break;
if (isModalVisible(domHelpModal)) {
hideModal(domHelpModal);
}
// toggle the preferences modal
if (isModalVisible(domPrefsModal)) {
hideModal(domPrefsModal);
} else {
showModal(domPrefsModal);
}
ev.preventDefault();
ev.stopPropagation();
}
}
function showHelpModal() {
domHelpModal.classList.remove("hidden");
domHelpModal.style.left =
window.innerWidth / 2 - domHelpModal.clientWidth / 2 + "px";
domHelpModal.style.top =
window.innerHeight / 2 - domHelpModal.clientHeight / 2 + "px";
domHelpModal.focus();
function isModalVisible(modal) {
return !modal.classList.contains("hidden");
}
function showModal(modal) {
modal.classList.remove("hidden");
modal.style.left =
window.innerWidth / 2 - modal.clientWidth / 2 + "px";
modal.style.top =
window.innerHeight / 2 - modal.clientHeight / 2 + "px";
const firstInput = modal.querySelector("input");
if (firstInput) {
firstInput.focus();
} else {
modal.focus();
}
domSearch.blur();
domBanner.inert = true;
domMain.inert = true;
}
function hideModal(modal) {
modal.classList.add("hidden");
domBanner.inert = false;
domMain.inert = false;
modal.blur();
}
function clearAsyncSearch() {
@ -4678,6 +4734,47 @@ function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) {
}
}
function getLocalStorage() {
if ("localStorage" in window) {
try {
return window.localStorage;
} catch (ignored) {
// localStorage may be disabled (SecurityError)
}
}
// If localStorage isn't available, persist preferences only for the current session
const sessionPrefs = {};
return {
getItem(key) {
return key in sessionPrefs ? sessionPrefs[key] : null;
},
setItem(key, value) {
sessionPrefs[key] = String(value);
},
};
}
function loadPrefs() {
const storedPrefSlashSearch = prefs.getItem("slashSearch");
if (storedPrefSlashSearch === null) {
// Slash search defaults to enabled for all browsers except Firefox
setPrefSlashSearch(navigator.userAgent.indexOf("Firefox") === -1);
} else {
setPrefSlashSearch(storedPrefSlashSearch === "true");
}
}
function getPrefSlashSearch() {
return prefs.getItem("slashSearch") === "true";
}
function setPrefSlashSearch(enabled) {
prefs.setItem("slashSearch", String(enabled));
domPrefSlashSearch.checked = enabled;
const searchKeys = enabled ? "<kbd>/</kbd> or <kbd>s</kbd>" : "<kbd>s</kbd>";
domSearchKeys.innerHTML = searchKeys;
domSearchPlaceholder.innerHTML = searchKeys + " to search, <kbd>?</kbd> for more options";
}
})();
function toggleExpand(event) {