about summary refs log tree commit diff
path: root/src/librustdoc/html/static/js/main.js
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume.gomez@huawei.com>2022-01-19 22:36:15 +0100
committerGuillaume Gomez <guillaume.gomez@huawei.com>2022-04-30 13:12:41 +0200
commit9625ed8be7fa66c3ee5f78180a3d5911817096f6 (patch)
treeeca2280b9a9644ab284bed1e27ec5024b084a6c7 /src/librustdoc/html/static/js/main.js
parent76d4862fdd131b6f79dc0a31857f888d26bcdb27 (diff)
downloadrust-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.js179
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) {