diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index b2500a1bc68..6dbf56681bd 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -17,6 +17,21 @@ $('.js-only').removeClass('js-only'); + function getQueryStringParams() { + 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; + } + + function browserSupportsHistoryApi() { + return window.history && typeof window.history.pushState === "function"; + } + function resizeShortBlocks() { if (resizeTimeout) { clearTimeout(resizeTimeout); @@ -97,10 +112,10 @@ }); function initSearch(searchIndex) { - var currentResults, index; + var currentResults, index, params = getQueryStringParams(); - // clear cached values from the search bar - $(".search-input")[0].value = ''; + // Populate search bar with query string search term when provided. + $(".search-input")[0].value = params.search || ''; /** * Executes the query and builds an index of results @@ -418,6 +433,7 @@ results = [], maxResults = 200, resultIndex; + var params = getQueryStringParams(); query = getQuery(); if (e) { @@ -428,6 +444,16 @@ return; } + // Because searching is incremental by character, only the most recent search query + // is added to the browser history. + if (browserSupportsHistoryApi()) { + if (!history.state && !params.search) { + history.pushState(query, "", "?search=" + encodeURIComponent(query.query)); + } else { + history.replaceState(query, "", "?search=" + encodeURIComponent(query.query)); + } + } + resultIndex = execQuery(query, 20000, index); len = resultIndex.length; for (i = 0; i < len; i += 1) { @@ -536,6 +562,27 @@ clearTimeout(keyUpTimeout); keyUpTimeout = setTimeout(search, 100); }); + // Push and pop states are used to add search results to the browser history. + if (browserSupportsHistoryApi()) { + $(window).on('popstate', function(e) { + var params = getQueryStringParams(); + // When browsing back from search results the main page visibility must be reset. + if (!params.search) { + $('#main.content').removeClass('hidden'); + $('#search.content').addClass('hidden'); + } + // When browsing forward to search results the previous search will be repeated, + // so the currentResults are cleared to ensure the search is successful. + currentResults = null; + // Synchronize search bar with query string state and perform the search. + $('.search-input').val(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 called + // both here and at the end of the startSearch() function. + search(); + }); + } + search(); } index = buildIndex(searchIndex);