summaryrefslogtreecommitdiffstats
path: root/src/librustdoc/html/static/js/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustdoc/html/static/js/main.js')
-rw-r--r--src/librustdoc/html/static/js/main.js184
1 files changed, 160 insertions, 24 deletions
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 33480fa41..152116089 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -47,10 +47,8 @@ function blurHandler(event, parentElem, hideCallback) {
}
}
-(function() {
- window.rootPath = getVar("root-path");
- window.currentCrate = getVar("current-crate");
-}());
+window.rootPath = getVar("root-path");
+window.currentCrate = getVar("current-crate");
function setMobileTopbar() {
// FIXME: It would be nicer to generate this text content directly in HTML,
@@ -183,9 +181,9 @@ function browserSupportsHistoryApi() {
}
// eslint-disable-next-line no-unused-vars
-function loadCss(cssFileName) {
+function loadCss(cssUrl) {
const link = document.createElement("link");
- link.href = resourcePath(cssFileName, ".css");
+ link.href = cssUrl;
link.type = "text/css";
link.rel = "stylesheet";
document.getElementsByTagName("head")[0].appendChild(link);
@@ -204,12 +202,13 @@ function loadCss(cssFileName) {
if (event.ctrlKey || event.altKey || event.metaKey) {
return;
}
+ window.hideAllModals(false);
addClass(getSettingsButton(), "rotate");
event.preventDefault();
// Sending request for the CSS and the JS files at the same time so it will
// hopefully be loaded when the JS will generate the settings content.
- loadCss("settings");
- loadScript(resourcePath("settings", ".js"));
+ loadCss(getVar("static-root-path") + getVar("settings-css"));
+ loadScript(getVar("static-root-path") + getVar("settings-js"));
};
window.searchState = {
@@ -286,7 +285,7 @@ function loadCss(cssFileName) {
function loadSearch() {
if (!searchLoaded) {
searchLoaded = true;
- loadScript(resourcePath("search", ".js"));
+ loadScript(getVar("static-root-path") + getVar("search-js"));
loadScript(resourcePath("search-index", ".js"));
}
}
@@ -303,13 +302,15 @@ function loadCss(cssFileName) {
const params = searchState.getQueryStringParams();
if (params.search !== undefined) {
- const search = searchState.outputElement();
- search.innerHTML = "<h3 class=\"search-loading\">" +
- searchState.loadingText + "</h3>";
- searchState.showResults(search);
+ searchState.setLoadingSearch();
loadSearch();
}
},
+ setLoadingSearch: () => {
+ const search = searchState.outputElement();
+ search.innerHTML = "<h3 class=\"search-loading\">" + searchState.loadingText + "</h3>";
+ searchState.showResults(search);
+ },
};
function getPageId() {
@@ -379,7 +380,7 @@ function loadCss(cssFileName) {
}
ev.preventDefault();
searchState.defocus();
- window.hidePopoverMenus();
+ window.hideAllModals(true); // true = reset focus for notable traits
}
function handleShortcut(ev) {
@@ -621,7 +622,7 @@ function loadCss(cssFileName) {
const innerToggle = document.getElementById(toggleAllDocsId);
removeClass(innerToggle, "will-expand");
onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
- if (!hasClass(e, "type-contents-toggle")) {
+ if (!hasClass(e, "type-contents-toggle") && !hasClass(e, "more-examples-toggle")) {
e.open = true;
}
});
@@ -725,12 +726,9 @@ function loadCss(cssFileName) {
});
};
- (function() {
- // To avoid checking on "rustdoc-line-numbers" value on every loop...
- if (getSettingValue("line-numbers") === "true") {
- window.rustdoc_add_line_numbers_to_examples();
- }
- }());
+ if (getSettingValue("line-numbers") === "true") {
+ window.rustdoc_add_line_numbers_to_examples();
+ }
let oldSidebarScrollPosition = null;
@@ -772,6 +770,7 @@ function loadCss(cssFileName) {
};
function showSidebar() {
+ window.hideAllModals(false);
window.rustdocMobileScrollLock();
const sidebar = document.getElementsByClassName("sidebar")[0];
addClass(sidebar, "shown");
@@ -790,6 +789,19 @@ function loadCss(cssFileName) {
// we need to switch away from mobile mode and make the main content area scrollable.
hideSidebar();
}
+ if (window.CURRENT_NOTABLE_ELEMENT) {
+ // As a workaround to the behavior of `contains: layout` used in doc togglers, the
+ // notable traits popup is positioned using javascript.
+ //
+ // This means when the window is resized, we need to redo the layout.
+ const base = window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE;
+ const force_visible = base.NOTABLE_FORCE_VISIBLE;
+ hideNotable(false);
+ if (force_visible) {
+ showNotable(base);
+ base.NOTABLE_FORCE_VISIBLE = true;
+ }
+ }
});
function handleClick(id, f) {
@@ -822,10 +834,123 @@ function loadCss(cssFileName) {
});
});
+ function showNotable(e) {
+ if (!window.NOTABLE_TRAITS) {
+ const data = document.getElementById("notable-traits-data");
+ if (data) {
+ window.NOTABLE_TRAITS = JSON.parse(data.innerText);
+ } else {
+ throw new Error("showNotable() called on page without any notable traits!");
+ }
+ }
+ if (window.CURRENT_NOTABLE_ELEMENT && window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE === e) {
+ // Make this function idempotent.
+ return;
+ }
+ window.hideAllModals(false);
+ const ty = e.getAttribute("data-ty");
+ const wrapper = document.createElement("div");
+ wrapper.innerHTML = "<div class=\"docblock\">" + window.NOTABLE_TRAITS[ty] + "</div>";
+ wrapper.className = "notable popover";
+ const focusCatcher = document.createElement("div");
+ focusCatcher.setAttribute("tabindex", "0");
+ focusCatcher.onfocus = hideNotable;
+ wrapper.appendChild(focusCatcher);
+ const pos = e.getBoundingClientRect();
+ // 5px overlap so that the mouse can easily travel from place to place
+ wrapper.style.top = (pos.top + window.scrollY + pos.height) + "px";
+ wrapper.style.left = 0;
+ wrapper.style.right = "auto";
+ wrapper.style.visibility = "hidden";
+ const body = document.getElementsByTagName("body")[0];
+ body.appendChild(wrapper);
+ const wrapperPos = wrapper.getBoundingClientRect();
+ // offset so that the arrow points at the center of the "(i)"
+ const finalPos = pos.left + window.scrollX - wrapperPos.width + 24;
+ if (finalPos > 0) {
+ wrapper.style.left = finalPos + "px";
+ } else {
+ wrapper.style.setProperty(
+ "--popover-arrow-offset",
+ (wrapperPos.right - pos.right + 4) + "px"
+ );
+ }
+ wrapper.style.visibility = "";
+ window.CURRENT_NOTABLE_ELEMENT = wrapper;
+ window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE = e;
+ wrapper.onpointerleave = function(ev) {
+ // If this is a synthetic touch event, ignore it. A click event will be along shortly.
+ if (ev.pointerType !== "mouse") {
+ return;
+ }
+ if (!e.NOTABLE_FORCE_VISIBLE && !elemIsInParent(event.relatedTarget, e)) {
+ hideNotable(true);
+ }
+ };
+ }
+
+ function notableBlurHandler(event) {
+ if (window.CURRENT_NOTABLE_ELEMENT &&
+ !elemIsInParent(document.activeElement, window.CURRENT_NOTABLE_ELEMENT) &&
+ !elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT) &&
+ !elemIsInParent(document.activeElement, window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE) &&
+ !elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE)
+ ) {
+ // Work around a difference in the focus behaviour between Firefox, Chrome, and Safari.
+ // When I click the button on an already-opened notable trait popover, Safari
+ // hides the popover and then immediately shows it again, while everyone else hides it
+ // and it stays hidden.
+ //
+ // To work around this, make sure the click finishes being dispatched before
+ // hiding the popover. Since `hideNotable()` is idempotent, this makes Safari behave
+ // consistently with the other two.
+ setTimeout(() => hideNotable(false), 0);
+ }
+ }
+
+ function hideNotable(focus) {
+ if (window.CURRENT_NOTABLE_ELEMENT) {
+ if (window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.NOTABLE_FORCE_VISIBLE) {
+ if (focus) {
+ window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.focus();
+ }
+ window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.NOTABLE_FORCE_VISIBLE = false;
+ }
+ const body = document.getElementsByTagName("body")[0];
+ body.removeChild(window.CURRENT_NOTABLE_ELEMENT);
+ window.CURRENT_NOTABLE_ELEMENT = null;
+ }
+ }
+
onEachLazy(document.getElementsByClassName("notable-traits"), e => {
e.onclick = function() {
- this.getElementsByClassName("notable-traits-tooltiptext")[0]
- .classList.toggle("force-tooltip");
+ this.NOTABLE_FORCE_VISIBLE = this.NOTABLE_FORCE_VISIBLE ? false : true;
+ if (window.CURRENT_NOTABLE_ELEMENT && !this.NOTABLE_FORCE_VISIBLE) {
+ hideNotable(true);
+ } else {
+ showNotable(this);
+ window.CURRENT_NOTABLE_ELEMENT.setAttribute("tabindex", "0");
+ window.CURRENT_NOTABLE_ELEMENT.focus();
+ window.CURRENT_NOTABLE_ELEMENT.onblur = notableBlurHandler;
+ }
+ return false;
+ };
+ e.onpointerenter = function(ev) {
+ // If this is a synthetic touch event, ignore it. A click event will be along shortly.
+ if (ev.pointerType !== "mouse") {
+ return;
+ }
+ showNotable(this);
+ };
+ e.onpointerleave = function(ev) {
+ // If this is a synthetic touch event, ignore it. A click event will be along shortly.
+ if (ev.pointerType !== "mouse") {
+ return;
+ }
+ if (!this.NOTABLE_FORCE_VISIBLE &&
+ !elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT)) {
+ hideNotable(true);
+ }
};
});
@@ -929,6 +1054,17 @@ function loadCss(cssFileName) {
}
/**
+ * Hide popover menus, notable trait tooltips, and the sidebar (if applicable).
+ *
+ * Pass "true" to reset focus for notable traits.
+ */
+ window.hideAllModals = function(switchFocus) {
+ hideSidebar();
+ window.hidePopoverMenus();
+ hideNotable(switchFocus);
+ };
+
+ /**
* Hide all the popover menus.
*/
window.hidePopoverMenus = function() {
@@ -959,7 +1095,7 @@ function loadCss(cssFileName) {
function showHelp() {
const menu = getHelpMenu(true);
if (menu.style.display === "none") {
- window.hidePopoverMenus();
+ window.hideAllModals();
menu.style.display = "";
}
}