Skip to content

Commit fb4000d

Browse files
committed
rustdoc-search: fix back/forward interaction after reload
1 parent a10328f commit fb4000d

File tree

2 files changed

+63
-58
lines changed

2 files changed

+63
-58
lines changed

src/librustdoc/html/static/js/main.js

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ function preLoadCss(cssUrl) {
253253
const out = nonnull(nonnull(window.searchState.outputElement()).parentElement);
254254
const hdr = document.createElement("div");
255255
hdr.className = "main-heading search-results-main-heading";
256-
const params = searchState.getQueryStringParams();
256+
const params = window.searchState.getQueryStringParams();
257257
const autofocusParam = params.search === "" ? "autofocus" : "";
258258
hdr.innerHTML = `<nav class="sub">
259259
<form class="search-form">
@@ -429,6 +429,66 @@ function preLoadCss(cssUrl) {
429429
};
430430
}
431431

432+
// Push and pop states are used to add search results to the browser
433+
// history.
434+
if (browserSupportsHistoryApi()) {
435+
// Store the previous <title> so we can revert back to it later.
436+
const previousTitle = document.title;
437+
438+
window.addEventListener("popstate", e => {
439+
const params = window.searchState.getQueryStringParams();
440+
// Revert to the previous title manually since the History
441+
// API ignores the title parameter.
442+
document.title = previousTitle;
443+
// Synchronize search bar with query string state and
444+
// perform the search. This will empty the bar if there's
445+
// nothing there, which lets you really go back to a
446+
// previous state with nothing in the bar.
447+
const inputElement = window.searchState.inputElement();
448+
if (params.search !== undefined && inputElement !== null) {
449+
loadSearch();
450+
inputElement.value = params.search;
451+
// Some browsers fire "onpopstate" for every page load
452+
// (Chrome), while others fire the event only when actually
453+
// popping a state (Firefox), which is why search() is
454+
// called both here and at the end of the startSearch()
455+
// function.
456+
e.preventDefault();
457+
window.searchState.showResults();
458+
if (params.search === "") {
459+
window.searchState.focus();
460+
}
461+
} else {
462+
// When browsing back from search results the main page
463+
// visibility must be reset.
464+
window.searchState.hideResults();
465+
}
466+
});
467+
}
468+
469+
// This is required in firefox to avoid this problem: Navigating to a search result
470+
// with the keyboard, hitting enter, and then hitting back would take you back to
471+
// the doc page, rather than the search that should overlay it.
472+
// This was an interaction between the back-forward cache and our handlers
473+
// that try to sync state between the URL and the search input. To work around it,
474+
// do a small amount of re-init on page show.
475+
window.onpageshow = () => {
476+
const inputElement = window.searchState.inputElement();
477+
const qSearch = window.searchState.getQueryStringParams().search;
478+
if (qSearch !== undefined && inputElement !== null) {
479+
if (inputElement.value === "") {
480+
inputElement.value = qSearch;
481+
}
482+
window.searchState.showResults();
483+
if (qSearch === "") {
484+
loadSearch();
485+
window.searchState.focus();
486+
}
487+
} else {
488+
window.searchState.hideResults();
489+
}
490+
};
491+
432492
const params = window.searchState.getQueryStringParams();
433493
if (params.search !== undefined) {
434494
window.searchState.setLoadingSearch();
@@ -1752,12 +1812,12 @@ function preLoadCss(cssUrl) {
17521812
// tablets), it's fixed-position, appears in the left side margin,
17531813
// and it can be activated by resizing the sidebar into nothing.
17541814
let sidebarButton = document.getElementById("sidebar-button");
1755-
if (!sidebarButton) {
1815+
const body = document.querySelector(".main-heading");
1816+
if (!sidebarButton && body) {
17561817
sidebarButton = document.createElement("div");
17571818
sidebarButton.id = "sidebar-button";
17581819
const path = `${window.rootPath}${window.currentCrate}/all.html`;
17591820
sidebarButton.innerHTML = `<a href="${path}" title="show sidebar"></a>`;
1760-
const body = document.querySelector(".main-heading");
17611821
body.insertBefore(sidebarButton, body.firstChild);
17621822
}
17631823
if (sidebarButton) {

src/librustdoc/html/static/js/search.js

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5322,61 +5322,6 @@ function registerSearchEvents() {
53225322
inputElement.addEventListener("focus", () => {
53235323
putBackSearch();
53245324
});
5325-
5326-
// Push and pop states are used to add search results to the browser
5327-
// history.
5328-
if (browserSupportsHistoryApi()) {
5329-
// Store the previous <title> so we can revert back to it later.
5330-
const previousTitle = document.title;
5331-
5332-
window.addEventListener("popstate", e => {
5333-
// @ts-expect-error
5334-
const params = searchState.getQueryStringParams();
5335-
// Revert to the previous title manually since the History
5336-
// API ignores the title parameter.
5337-
document.title = previousTitle;
5338-
// When browsing forward to search results the previous
5339-
// search will be repeated, so the currentResults are
5340-
// cleared to ensure the search is successful.
5341-
currentResults = null;
5342-
// Synchronize search bar with query string state and
5343-
// perform the search. This will empty the bar if there's
5344-
// nothing there, which lets you really go back to a
5345-
// previous state with nothing in the bar.
5346-
if (params.search !== undefined) {
5347-
inputElement.value = params.search;
5348-
// Some browsers fire "onpopstate" for every page load
5349-
// (Chrome), while others fire the event only when actually
5350-
// popping a state (Firefox), which is why search() is
5351-
// called both here and at the end of the startSearch()
5352-
// function.
5353-
e.preventDefault();
5354-
search();
5355-
} else {
5356-
// When browsing back from search results the main page
5357-
// visibility must be reset.
5358-
// @ts-expect-error
5359-
searchState.hideResults();
5360-
}
5361-
});
5362-
}
5363-
5364-
// This is required in firefox to avoid this problem: Navigating to a search result
5365-
// with the keyboard, hitting enter, and then hitting back would take you back to
5366-
// the doc page, rather than the search that should overlay it.
5367-
// This was an interaction between the back-forward cache and our handlers
5368-
// that try to sync state between the URL and the search input. To work around it,
5369-
// do a small amount of re-init on page show.
5370-
window.onpageshow = () => {
5371-
// @ts-expect-error
5372-
const qSearch = searchState.getQueryStringParams().search;
5373-
if (qSearch !== undefined) {
5374-
if (inputElement.value === "") {
5375-
inputElement.value = qSearch;
5376-
}
5377-
search();
5378-
}
5379-
};
53805325
}
53815326

53825327
// @ts-expect-error

0 commit comments

Comments
 (0)