diff options
| author | Guillaume Gomez <guillaume.gomez@huawei.com> | 2022-01-19 22:36:15 +0100 |
|---|---|---|
| committer | Guillaume Gomez <guillaume.gomez@huawei.com> | 2022-04-30 13:12:41 +0200 |
| commit | 9625ed8be7fa66c3ee5f78180a3d5911817096f6 (patch) | |
| tree | eca2280b9a9644ab284bed1e27ec5024b084a6c7 /src/librustdoc/html/static/js/main.js | |
| parent | 76d4862fdd131b6f79dc0a31857f888d26bcdb27 (diff) | |
| download | rust-9625ed8be7fa66c3ee5f78180a3d5911817096f6.tar.gz rust-9625ed8be7fa66c3ee5f78180a3d5911817096f6.zip | |
Move settings into full JS
Diffstat (limited to 'src/librustdoc/html/static/js/main.js')
| -rw-r--r-- | src/librustdoc/html/static/js/main.js | 179 |
1 files changed, 145 insertions, 34 deletions
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 9e5de9a843a..7ac835b3270 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -57,11 +57,20 @@ function resourcePath(basename, extension) { return getVar("root-path") + basename + getVar("resource-suffix") + extension; } +function hideMain() { + addClass(document.getElementById(MAIN_ID), "hidden"); +} + +function showMain() { + removeClass(document.getElementById(MAIN_ID), "hidden"); +} + (function () { window.rootPath = getVar("root-path"); window.currentCrate = getVar("current-crate"); window.searchJS = resourcePath("search", ".js"); window.searchIndexJS = resourcePath("search-index", ".js"); + window.settingsJS = resourcePath("settings", ".js"); const sidebarVars = document.getElementById("sidebar-vars"); if (sidebarVars) { window.sidebarCurrent = { @@ -104,6 +113,9 @@ function getVirtualKey(ev) { const THEME_PICKER_ELEMENT_ID = "theme-picker"; const THEMES_ELEMENT_ID = "theme-choices"; const MAIN_ID = "main-content"; +const SETTINGS_BUTTON_ID = "settings-menu"; +const ALTERNATIVE_DISPLAY_ID = "alternative-display"; +const NOT_DISPLAYED_ID = "not-displayed"; function getThemesElement() { return document.getElementById(THEMES_ELEMENT_ID); @@ -113,6 +125,10 @@ function getThemePickerElement() { return document.getElementById(THEME_PICKER_ELEMENT_ID); } +function getSettingsButton() { + return document.getElementById(SETTINGS_BUTTON_ID); +} + // Returns the current URL without any query parameter or hash. function getNakedUrl() { return window.location.href.split("?")[0].split("#")[0]; @@ -136,6 +152,10 @@ function hideThemeButtonState() { themePicker.style.borderBottomLeftRadius = "3px"; } +window.hideSettings = function() { + // Does nothing by default. +}; + // Set up the theme picker list. (function () { if (!document.location.href.startsWith("file:///")) { @@ -182,14 +202,120 @@ function hideThemeButtonState() { }); }()); +/** + * This function inserts `newNode` after `referenceNode`. It doesn't work if `referenceNode` + * doesn't have a parent node. + * + * @param {DOM} newNode + * @param {DOM} referenceNode + */ +function insertAfter(newNode, referenceNode) { + referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); +} + +/** + * This function creates a new `<section>` with the given `id` and `classes` if it doesn't already + * exist. + * + * More information about this in `switchDisplayedElement` documentation. + * + * @param {string} id + * @param {string} classes + */ +function getOrCreateSection(id, classes) { + let el = document.getElementById(id); + + if (!el) { + el = document.createElement("section"); + el.id = id; + el.className = classes; + insertAfter(el, document.getElementById(MAIN_ID)); + } + return el; +} + +/** + * Returns the `<section>` element which contains the displayed element. + * + * @return {DOM} + */ +function getAlternativeDisplayElem() { + return getOrCreateSection(ALTERNATIVE_DISPLAY_ID, "content hidden"); +} + +/** + * Returns the `<section>` element which contains the not-displayed elements. + * + * @return {DOM} + */ +function getNotDisplayedElem() { + return getOrCreateSection(NOT_DISPLAYED_ID, "hidden"); +} + +/** + * To nicely switch between displayed "extra" elements (such as search results or settings menu) + * and to alternate between the displayed and not displayed elements, we hold them in two different + * `<section>` elements. They work in pair: one hold the not displayed elements while the other + * contains the displayed element (there can be only one at the same time!). So basically, we switch + * elements between the two `<section>` elements. + * + * @param {DOM} elemToDisplay + */ +function switchDisplayedElement(elemToDisplay) { + const el = getAlternativeDisplayElem(); + + if (el.children.length > 0) { + getNotDisplayedElem().appendChild(el.firstElementChild); + } + if (elemToDisplay === null) { + addClass(el, "hidden"); + showMain(); + return; + } + el.appendChild(elemToDisplay); + hideMain(); + removeClass(el, "hidden"); +} + +function browserSupportsHistoryApi() { + return window.history && typeof window.history.pushState === "function"; +} + +// eslint-disable-next-line no-unused-vars +function loadCss(cssFileName) { + const link = document.createElement("link"); + link.href = resourcePath(cssFileName, ".css"); + link.type = "text/css"; + link.rel = "stylesheet"; + document.getElementsByTagName("head")[0].appendChild(link); +} + (function() { "use strict"; + function loadScript(url) { + const script = document.createElement('script'); + script.src = url; + document.head.append(script); + } + + + getSettingsButton().onclick = function(event) { + event.preventDefault(); + loadScript(window.settingsJS); + }; + window.searchState = { loadingText: "Loading search results...", input: document.getElementsByClassName("search-input")[0], outputElement: function() { - return document.getElementById("search"); + let el = document.getElementById("search"); + if (!el) { + el = document.createElement("section"); + el.id = "search"; + getNotDisplayedElem().appendChild(el); + } + return el; }, title: document.title, titleBeforeSearch: document.title, @@ -208,6 +334,9 @@ function hideThemeButtonState() { searchState.timeout = null; } }, + isDisplayed: function() { + return searchState.outputElement().parentElement.id === ALTERNATIVE_DISPLAY_ID; + }, // Sets the focus on the search bar at the top of the page focus: function() { searchState.input.focus(); @@ -220,20 +349,15 @@ function hideThemeButtonState() { if (search === null || typeof search === 'undefined') { search = searchState.outputElement(); } - addClass(main, "hidden"); - removeClass(search, "hidden"); + switchDisplayedElement(search); searchState.mouseMovedAfterSearch = false; document.title = searchState.title; }, - hideResults: function(search) { - if (search === null || typeof search === 'undefined') { - search = searchState.outputElement(); - } - addClass(search, "hidden"); - removeClass(main, "hidden"); + hideResults: function() { + switchDisplayedElement(null); document.title = searchState.titleBeforeSearch; // We also remove the query parameter from the URL. - if (searchState.browserSupportsHistoryApi()) { + if (browserSupportsHistoryApi()) { history.replaceState(null, window.currentCrate + " - Rust", getNakedUrl() + window.location.hash); } @@ -248,20 +372,11 @@ function hideThemeButtonState() { }); return params; }, - browserSupportsHistoryApi: function() { - return window.history && typeof window.history.pushState === "function"; - }, setup: function() { const search_input = searchState.input; if (!searchState.input) { return; } - function loadScript(url) { - const script = document.createElement('script'); - script.src = url; - document.head.append(script); - } - let searchLoaded = false; function loadSearch() { if (!searchLoaded) { @@ -303,23 +418,20 @@ function hideThemeButtonState() { } const toggleAllDocsId = "toggle-all-docs"; - const main = document.getElementById(MAIN_ID); let savedHash = ""; function handleHashes(ev) { - let elem; - const search = searchState.outputElement(); - if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) { + if (ev !== null && searchState.isDisplayed() && ev.newURL) { // This block occurs when clicking on an element in the navbar while // in a search. - searchState.hideResults(search); + switchDisplayedElement(null); const hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1); - if (searchState.browserSupportsHistoryApi()) { + if (browserSupportsHistoryApi()) { // `window.location.search`` contains all the query parameters, not just `search`. history.replaceState(null, "", getNakedUrl() + window.location.search + "#" + hash); } - elem = document.getElementById(hash); + const elem = document.getElementById(hash); if (elem) { elem.scrollIntoView(); } @@ -389,14 +501,17 @@ function hideThemeButtonState() { } function handleEscape(ev) { + searchState.clearInputTimeout(); const help = getHelpElement(false); - const search = searchState.outputElement(); if (help && !hasClass(help, "hidden")) { displayHelp(false, ev, help); - } else if (search && !hasClass(search, "hidden")) { - searchState.clearInputTimeout(); + } else { + switchDisplayedElement(null); + if (browserSupportsHistoryApi()) { + history.replaceState(null, window.currentCrate + " - Rust", + getNakedUrl() + window.location.hash); + } ev.preventDefault(); - searchState.hideResults(search); } searchState.defocus(); hideThemeButtonState(); @@ -733,10 +848,6 @@ function hideThemeButtonState() { innerToggle.children[0].innerText = labelForToggleButton(sectionIsCollapsed); } - function insertAfter(newNode, referenceNode) { - referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); - } - (function() { const toggles = document.getElementById(toggleAllDocsId); if (toggles) { |
