about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/html/static/main.js266
-rw-r--r--src/librustdoc/html/static/search.js76
2 files changed, 167 insertions, 175 deletions
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 7d7825f0f65..cb7408502eb 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -80,10 +80,6 @@ function getSearchInput() {
     return document.getElementsByClassName("search-input")[0];
 }
 
-function getSearchElement() {
-    return document.getElementById("search");
-}
-
 var THEME_PICKER_ELEMENT_ID = "theme-picker";
 var THEMES_ELEMENT_ID = "theme-choices";
 
@@ -172,30 +168,123 @@ function hideThemeButtonState() {
 (function() {
     "use strict";
 
-    var disableShortcuts = getSettingValue("disable-shortcuts") === "true";
-    window.search_input = getSearchInput();
-    var searchTimeout = null;
-    var toggleAllDocsId = "toggle-all-docs";
+    window.searchState = {
+      loadingText: "Loading search results...",
+      input: getSearchInput(),
+      outputElement: function() {
+        return document.getElementById("search");
+      },
+      title: null,
+      titleBeforeSearch: document.title,
+      timeout: null,
+      // On the search screen, so you remain on the last tab you opened.
+      //
+      // 0 for "In Names"
+      // 1 for "In Parameters"
+      // 2 for "In Return Types"
+      currentTab: 0,
+      mouseMovedAfterSearch: true,
+      clearInputTimeout: function() {
+        if (searchState.timeout !== null) {
+            clearTimeout(searchState.timeout);
+            searchState.timeout = null;
+        }
+      },
+      showResults: function(search) {
+        if (search === null || typeof search === 'undefined') {
+            search = searchState.outputElement();
+        }
+        addClass(main, "hidden");
+        removeClass(search, "hidden");
+        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");
+        document.title = searchState.titleBeforeSearch;
+        // We also remove the query parameter from the URL.
+        if (searchState.browserSupportsHistoryApi()) {
+            history.replaceState("", window.currentCrate + " - Rust",
+                getNakedUrl() + window.location.hash);
+        }
+      },
+      getQueryStringParams: function() {
+        var params = {};
+        window.location.search.substring(1).split("&").
+            map(function(s) {
+                var pair = s.split("=");
+                params[decodeURIComponent(pair[0])] =
+                    typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
+            });
+        return params;
+      },
+      putBackSearch: function(search_input) {
+        var search = searchState.outputElement();
+        if (search_input.value !== "" && hasClass(search, "hidden")) {
+            searchState.showResults(search);
+            if (searchState.browserSupportsHistoryApi()) {
+                var extra = "?search=" + encodeURIComponent(search_input.value);
+                history.replaceState(search_input.value, "",
+                    getNakedUrl() + extra + window.location.hash);
+            }
+            document.title = searchState.title;
+        }
+      },
+      browserSupportsHistoryApi: function() {
+          return window.history && typeof window.history.pushState === "function";
+      },
+      setupLoader: function() {
+        function loadScript(url) {
+            var script = document.createElement('script');
+            script.src = url;
+            document.head.append(script);
+        }
 
-    // On the search screen, so you remain on the last tab you opened.
-    //
-    // 0 for "In Names"
-    // 1 for "In Parameters"
-    // 2 for "In Return Types"
-    window.currentTab = 0;
+        var searchLoaded = false;
+        function loadSearch() {
+            if (!searchLoaded) {
+                searchLoaded = true;
+                loadScript(window.searchJS);
+            }
+        }
 
-    window.mouseMovedAfterSearch = true;
+        // `crates{version}.js` should always be loaded before this script, so we can use it safely.
+        addSearchOptions(window.ALL_CRATES);
+        addSidebarCrates(window.ALL_CRATES);
 
-    var titleBeforeSearch = document.title;
-    window.searchTitle = null;
+        searchState.input.addEventListener("focus", function() {
+            searchState.input.origPlaceholder = searchState.input.placeholder;
+            searchState.input.placeholder = "Type your search here.";
+            loadSearch();
+        });
+        searchState.input.addEventListener("blur", function() {
+            searchState.input.placeholder = searchState.input.origPlaceholder;
+        });
+        searchState.input.removeAttribute('disabled');
 
-    window.clearInputTimeout = function() {
-        if (searchTimeout !== null) {
-            clearTimeout(searchTimeout);
-            searchTimeout = null;
+        var crateSearchDropDown = document.getElementById("crate-search");
+        // `crateSearchDropDown` can be null in case there is only crate because in that case, the
+        // crate filter dropdown is removed.
+        if (crateSearchDropDown) {
+            crateSearchDropDown.addEventListener("focus", loadSearch);
+        }
+        var params = searchState.getQueryStringParams();
+        if (params.search !== undefined) {
+            loadSearch();
         }
+      },
     };
 
+    if (searchState.input) {
+        searchState.input.onfocus = function() {
+            searchState.putBackSearch(this);
+        };
+    }
+
     function getPageId() {
         if (window.location.hash) {
             var tmp = window.location.hash.replace(/^#/, "");
@@ -237,61 +326,23 @@ function hideThemeButtonState() {
         document.getElementsByTagName("body")[0].style.marginTop = "";
     }
 
-    window.showSearchResults = function(search) {
-        if (search === null || typeof search === 'undefined') {
-            search = getSearchElement();
-        }
-        addClass(main, "hidden");
-        removeClass(search, "hidden");
-        mouseMovedAfterSearch = false;
-        document.title = searchTitle;
-    };
-
-    window.hideSearchResults = function(search) {
-        if (search === null || typeof search === 'undefined') {
-            search = getSearchElement();
-        }
-        addClass(search, "hidden");
-        removeClass(main, "hidden");
-        document.title = titleBeforeSearch;
-        // We also remove the query parameter from the URL.
-        if (browserSupportsHistoryApi()) {
-            history.replaceState("", window.currentCrate + " - Rust",
-                getNakedUrl() + window.location.hash);
-        }
-    };
-
-    window.getQueryStringParams = function() {
-        var params = {};
-        window.location.search.substring(1).split("&").
-            map(function(s) {
-                var pair = s.split("=");
-                params[decodeURIComponent(pair[0])] =
-                    typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
-            });
-        return params;
-    };
-
-    window.browserSupportsHistoryApi = function() {
-        return window.history && typeof window.history.pushState === "function";
-    };
-
     function isHidden(elem) {
         return elem.offsetHeight === 0;
     }
 
+    var toggleAllDocsId = "toggle-all-docs";
     var main = document.getElementById("main");
     var savedHash = "";
 
     function handleHashes(ev) {
         var elem;
-        var search = getSearchElement();
+        var search = searchState.outputElement();
         if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
             // This block occurs when clicking on an element in the navbar while
             // in a search.
-            hideSearchResults(search);
+            searchState.hideResults(search);
             var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
-            if (browserSupportsHistoryApi()) {
+            if (searchState.browserSupportsHistoryApi()) {
                 // `window.location.search`` contains all the query parameters, not just `search`.
                 history.replaceState(hash, "",
                     getNakedUrl() + window.location.search + "#" + hash);
@@ -432,18 +483,19 @@ function hideThemeButtonState() {
 
     function handleEscape(ev) {
         var help = getHelpElement(false);
-        var search = getSearchElement();
+        var search = searchState.outputElement();
         if (hasClass(help, "hidden") === false) {
             displayHelp(false, ev, help);
         } else if (hasClass(search, "hidden") === false) {
-            clearInputTimeout();
+            searchState.clearInputTimeout();
             ev.preventDefault();
-            hideSearchResults(search);
+            searchState.hideResults(search);
         }
         defocusSearchBar();
         hideThemeButtonState();
     }
 
+    var disableShortcuts = getSettingValue("disable-shortcuts") === "true";
     function handleShortcut(ev) {
         // Don't interfere with browser shortcuts
         if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts === true) {
@@ -553,7 +605,9 @@ function hideThemeButtonState() {
     document.addEventListener("keypress", handleShortcut);
     document.addEventListener("keydown", handleShortcut);
 
-    document.addEventListener("mousemove", function() { mouseMovedAfterSearch = true; });
+    document.addEventListener("mousemove", function() {
+      searchState.mouseMovedAfterSearch = true;
+    });
 
     var handleSourceHighlight = (function() {
         var prev_line_id = 0;
@@ -561,7 +615,7 @@ function hideThemeButtonState() {
         var set_fragment = function(name) {
             var x = window.scrollX,
                 y = window.scrollY;
-            if (browserSupportsHistoryApi()) {
+            if (searchState.browserSupportsHistoryApi()) {
                 history.replaceState(null, null, "#" + name);
                 highlightSourceLines();
             } else {
@@ -1366,34 +1420,11 @@ function hideThemeButtonState() {
         };
     });
 
-    window.putBackSearch = function(search_input) {
-        var search = getSearchElement();
-        if (search_input.value !== "" && hasClass(search, "hidden")) {
-            showSearchResults(search);
-            if (browserSupportsHistoryApi()) {
-                var extra = "?search=" + encodeURIComponent(search_input.value);
-                history.replaceState(search_input.value, "",
-                    getNakedUrl() + extra + window.location.hash);
-            }
-            document.title = searchTitle;
-        }
-    };
-
-    function getSearchLoadingText() {
-        return "Loading search results...";
-    }
-
-    if (search_input) {
-        search_input.onfocus = function() {
-            putBackSearch(this);
-        };
-    }
-
-    var params = getQueryStringParams();
+    var params = searchState.getQueryStringParams();
     if (params && params.search) {
-        var search = getSearchElement();
-        search.innerHTML = "<h3 style=\"text-align: center;\">" + getSearchLoadingText() + "</h3>";
-        showSearchResults(search);
+        var search = searchState.outputElement();
+        search.innerHTML = "<h3 style=\"text-align: center;\">" + searchState.loadingText + "</h3>";
+        searchState.showResults(search);
     }
 
     var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
@@ -1509,55 +1540,14 @@ function hideThemeButtonState() {
         container.appendChild(div_infos);
 
         popup.appendChild(container);
-        insertAfter(popup, getSearchElement());
+        insertAfter(popup, searchState.outputElement());
         // So that it's only built once and then it'll do nothing when called!
         buildHelperPopup = function() {};
     }
 
-    function loadScript(url) {
-        var script = document.createElement('script');
-        script.src = url;
-        document.head.append(script);
-    }
-
-    function setupSearchLoader() {
-        var searchLoaded = false;
-        function loadSearch() {
-            if (!searchLoaded) {
-                searchLoaded = true;
-                loadScript(window.searchJS);
-            }
-        }
-
-        // `crates{version}.js` should always be loaded before this script, so we can use it safely.
-        addSearchOptions(window.ALL_CRATES);
-        addSidebarCrates(window.ALL_CRATES);
-
-        search_input.addEventListener("focus", function() {
-            search_input.origPlaceholder = search_input.placeholder;
-            search_input.placeholder = "Type your search here.";
-            loadSearch();
-        });
-        search_input.addEventListener("blur", function() {
-            search_input.placeholder = search_input.origPlaceholder;
-        });
-        search_input.removeAttribute('disabled');
-
-        var crateSearchDropDown = document.getElementById("crate-search");
-        // `crateSearchDropDown` can be null in case there is only crate because in that case, the
-        // crate filter dropdown is removed.
-        if (crateSearchDropDown) {
-            crateSearchDropDown.addEventListener("focus", loadSearch);
-        }
-        var params = getQueryStringParams();
-        if (params.search !== undefined) {
-            loadSearch();
-        }
-    }
-
     onHashChange(null);
     window.onhashchange = onHashChange;
-    setupSearchLoader();
+    searchState.setupLoader();
 }());
 
 function copy_path(but) {
diff --git a/src/librustdoc/html/static/search.js b/src/librustdoc/html/static/search.js
index c06de66d7f7..b8afbd175c5 100644
--- a/src/librustdoc/html/static/search.js
+++ b/src/librustdoc/html/static/search.js
@@ -39,7 +39,7 @@ var TY_KEYWORD = itemTypes.indexOf("keyword");
 // In the search display, allows to switch between tabs.
 function printTab(nb) {
     if (nb === 0 || nb === 1 || nb === 2) {
-        currentTab = nb;
+        searchState.currentTab = nb;
     }
     var nb_copy = nb;
     onEachLazy(document.getElementById("titles").childNodes, function(elem) {
@@ -114,14 +114,14 @@ function initSearch(rawSearchIndex) {
     var NO_TYPE_FILTER = -1;
     var currentResults, index, searchIndex;
     var ALIASES = {};
-    var params = getQueryStringParams();
+    var params = searchState.getQueryStringParams();
 
     // Populate search bar with query string search term when provided,
     // but only if the input bar is empty. This avoid the obnoxious issue
     // where you start trying to do a search, and the index loads, and
     // suddenly your search is gone!
-    if (search_input.value === "") {
-        search_input.value = params.search || "";
+    if (searchState.input.value === "") {
+        searchState.input.value = params.search || "";
     }
 
     /**
@@ -898,12 +898,12 @@ function initSearch(rawSearchIndex) {
             }
             dst = dst[0];
             if (window.location.pathname === dst.pathname) {
-                hideSearchResults();
+                searchState.hideResults();
                 document.location.href = dst.href;
             }
         };
         var mouseover_func = function(e) {
-            if (mouseMovedAfterSearch) {
+            if (searchState.mouseMovedAfterSearch) {
                 var el = e.target;
                 // to retrieve the real "owner" of the event.
                 while (el.tagName !== "TR") {
@@ -927,7 +927,7 @@ function initSearch(rawSearchIndex) {
             });
         });
 
-        search_input.onkeydown = function(e) {
+        searchState.input.onkeydown = function(e) {
             // "actives" references the currently highlighted item in each search tab.
             // Each array in "actives" represents a tab.
             var actives = [[], [], []];
@@ -940,6 +940,7 @@ function initSearch(rawSearchIndex) {
                 current += 1;
             });
 
+            var currentTab = searchState.currentTab;
             if (e.which === 38) { // up
                 if (e.ctrlKey) { // Going through result tabs.
                     printTab(currentTab > 0 ? currentTab - 1 : 2);
@@ -1104,7 +1105,7 @@ function initSearch(rawSearchIndex) {
     }
 
     function makeTabHeader(tabNb, text, nbElems) {
-        if (currentTab === tabNb) {
+        if (searchState.currentTab === tabNb) {
             return "<button class=\"selected\">" + text +
                    " <div class=\"count\">(" + nbElems + ")</div></button>";
         }
@@ -1112,13 +1113,13 @@ function initSearch(rawSearchIndex) {
     }
 
     function showResults(results) {
-        var search = getSearchElement();
+        var search = searchState.outputElement();
         if (results.others.length === 1
             && getSettingValue("go-to-only-result") === "true"
             // By default, the search DOM element is "empty" (meaning it has no children not
             // text content). Once a search has been run, it won't be empty, even if you press
             // ESC or empty the search input (which also "cancels" the search).
-            && (!search.firstChild || search.firstChild.innerText !== getSearchLoadingText()))
+            && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText))
         {
             var elem = document.createElement("a");
             elem.href = results.others[0].href;
@@ -1128,7 +1129,7 @@ function initSearch(rawSearchIndex) {
             elem.click();
             return;
         }
-        var query = getQuery(search_input.value);
+        var query = getQuery(searchState.input.value);
 
         currentResults = query.id;
 
@@ -1139,6 +1140,7 @@ function initSearch(rawSearchIndex) {
         // Navigate to the relevant tab if the current tab is empty, like in case users search
         // for "-> String". If they had selected another tab previously, they have to click on
         // it again.
+        var currentTab = searchState.currentTab;
         if ((currentTab === 0 && ret_others[1] === 0) ||
                 (currentTab === 1 && ret_in_args[1] === 0) ||
                 (currentTab === 2 && ret_returned[1] === 0)) {
@@ -1161,7 +1163,7 @@ function initSearch(rawSearchIndex) {
             ret_others[0] + ret_in_args[0] + ret_returned[0] + "</div>";
 
         search.innerHTML = output;
-        showSearchResults(search);
+        searchState.showResults(search);
         initSearchNav();
         var elems = document.getElementById("titles").childNodes;
         elems[0].onclick = function() { printTab(0); };
@@ -1252,8 +1254,8 @@ function initSearch(rawSearchIndex) {
     }
 
     function search(e, forced) {
-        var params = getQueryStringParams();
-        var query = getQuery(search_input.value.trim());
+        var params = searchState.getQueryStringParams();
+        var query = getQuery(searchState.input.value.trim());
 
         if (e) {
             e.preventDefault();
@@ -1264,17 +1266,17 @@ function initSearch(rawSearchIndex) {
         }
         if (forced !== true && query.id === currentResults) {
             if (query.query.length > 0) {
-                putBackSearch(search_input);
+                searchState.putBackSearch(searchState.input);
             }
             return;
         }
 
         // Update document title to maintain a meaningful browser history
-        searchTitle = "Results for " + query.query + " - Rust";
+        searchState.title = "Results for " + query.query + " - Rust";
 
         // Because searching is incremental by character, only the most
         // recent search query is added to the browser history.
-        if (browserSupportsHistoryApi()) {
+        if (searchState.browserSupportsHistoryApi()) {
             var newURL = getNakedUrl() + "?search=" + encodeURIComponent(query.raw) +
                 window.location.hash;
             if (!history.state && !params.search) {
@@ -1408,37 +1410,37 @@ function initSearch(rawSearchIndex) {
 
     function registerSearchEvents() {
         var searchAfter500ms = function() {
-            clearInputTimeout();
-            if (search_input.value.length === 0) {
-                if (browserSupportsHistoryApi()) {
+            searchState.clearInputTimeout();
+            if (searchState.input.value.length === 0) {
+                if (searchState.browserSupportsHistoryApi()) {
                     history.replaceState("", window.currentCrate + " - Rust",
                         getNakedUrl() + window.location.hash);
                 }
-                hideSearchResults();
+                searchState.hideResults();
             } else {
-                searchTimeout = setTimeout(search, 500);
+                searchState.timeout = setTimeout(search, 500);
             }
         };
-        search_input.onkeyup = searchAfter500ms;
-        search_input.oninput = searchAfter500ms;
+        searchState.input.onkeyup = searchAfter500ms;
+        searchState.input.oninput = searchAfter500ms;
         document.getElementsByClassName("search-form")[0].onsubmit = function(e) {
             e.preventDefault();
-            clearInputTimeout();
+            searchState.clearInputTimeout();
             search();
         };
-        search_input.onchange = function(e) {
+        searchState.input.onchange = function(e) {
             if (e.target !== document.activeElement) {
                 // To prevent doing anything when it's from a blur event.
                 return;
             }
             // Do NOT e.preventDefault() here. It will prevent pasting.
-            clearInputTimeout();
+            searchState.clearInputTimeout();
             // zero-timeout necessary here because at the time of event handler execution the
             // pasted content is not in the input field yet. Shouldn’t make any difference for
             // change, though.
             setTimeout(search, 0);
         };
-        search_input.onpaste = search_input.onchange;
+        searchState.input.onpaste = searchState.input.onchange;
 
         var selectCrate = document.getElementById("crate-search");
         if (selectCrate) {
@@ -1450,12 +1452,12 @@ function initSearch(rawSearchIndex) {
 
         // Push and pop states are used to add search results to the browser
         // history.
-        if (browserSupportsHistoryApi()) {
+        if (searchState.browserSupportsHistoryApi()) {
             // Store the previous <title> so we can revert back to it later.
             var previousTitle = document.title;
 
             window.addEventListener("popstate", function(e) {
-                var params = getQueryStringParams();
+                var params = searchState.getQueryStringParams();
                 // Revert to the previous title manually since the History
                 // API ignores the title parameter.
                 document.title = previousTitle;
@@ -1468,7 +1470,7 @@ function initSearch(rawSearchIndex) {
                 // nothing there, which lets you really go back to a
                 // previous state with nothing in the bar.
                 if (params.search && params.search.length > 0) {
-                    search_input.value = params.search;
+                    searchState.input.value = params.search;
                     // Some browsers fire "onpopstate" for every page load
                     // (Chrome), while others fire the event only when actually
                     // popping a state (Firefox), which is why search() is
@@ -1476,10 +1478,10 @@ function initSearch(rawSearchIndex) {
                     // function.
                     search(e);
                 } else {
-                    search_input.value = "";
+                    searchState.input.value = "";
                     // When browsing back from search results the main page
                     // visibility must be reset.
-                    hideSearchResults();
+                    searchState.hideResults();
                 }
             });
         }
@@ -1491,9 +1493,9 @@ function initSearch(rawSearchIndex) {
         // that try to sync state between the URL and the search input. To work around it,
         // do a small amount of re-init on page show.
         window.onpageshow = function(){
-            var qSearch = getQueryStringParams().search;
-            if (search_input.value === "" && qSearch) {
-                search_input.value = qSearch;
+            var qSearch = searchState.getQueryStringParams().search;
+            if (searchState.input.value === "" && qSearch) {
+                searchState.input.value = qSearch;
             }
             search();
         };
@@ -1502,7 +1504,7 @@ function initSearch(rawSearchIndex) {
     index = buildIndex(rawSearchIndex);
     registerSearchEvents();
     // If there's a search term in the URL, execute the search now.
-    if (getQueryStringParams().search) {
+    if (searchState.getQueryStringParams().search) {
         search();
     }
 };