]>
git.proxmox.com Git - rustc.git/blob - src/librustdoc/html/static/js/main.js
1 // Local js definitions:
2 /* global addClass, getSettingValue, hasClass, searchState */
3 /* global onEach, onEachLazy, removeClass */
4 /* global switchTheme, useSystemTheme */
6 if (!String
.prototype.startsWith
) {
7 String
.prototype.startsWith = function(searchString
, position
) {
8 position
= position
|| 0;
9 return this.indexOf(searchString
, position
) === position
;
12 if (!String
.prototype.endsWith
) {
13 String
.prototype.endsWith = function(suffix
, length
) {
14 var l
= length
|| this.length
;
15 return this.indexOf(suffix
, l
- suffix
.length
) !== -1;
19 if (!DOMTokenList
.prototype.add
) {
20 DOMTokenList
.prototype.add = function(className
) {
21 if (className
&& !hasClass(this, className
)) {
22 if (this.className
&& this.className
.length
> 0) {
23 this.className
+= " " + className
;
25 this.className
= className
;
31 if (!DOMTokenList
.prototype.remove
) {
32 DOMTokenList
.prototype.remove = function(className
) {
33 if (className
&& this.className
) {
34 this.className
= (" " + this.className
+ " ").replace(" " + className
+ " ", " ")
40 // Get a value from the rustdoc-vars div, which is used to convey data from
41 // Rust to the JS. If there is no such element, return null.
42 function getVar(name
) {
43 var el
= document
.getElementById("rustdoc-vars");
45 return el
.attributes
["data-" + name
].value
;
51 // Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL
52 // for a resource under the root-path, with the resource-suffix.
53 function resourcePath(basename
, extension
) {
54 return getVar("root-path") + basename
+ getVar("resource-suffix") + extension
;
58 window
.rootPath
= getVar("root-path");
59 window
.currentCrate
= getVar("current-crate");
60 window
.searchJS
= resourcePath("search", ".js");
61 window
.searchIndexJS
= resourcePath("search-index", ".js");
62 var sidebarVars
= document
.getElementById("sidebar-vars");
64 window
.sidebarCurrent
= {
65 name
: sidebarVars
.attributes
["data-name"].value
,
66 ty
: sidebarVars
.attributes
["data-ty"].value
,
67 relpath
: sidebarVars
.attributes
["data-relpath"].value
,
69 // FIXME: It would be nicer to generate this text content directly in HTML,
70 // but with the current code it's hard to get the right information in the right place.
71 var mobileLocationTitle
= document
.querySelector(".mobile-topbar h2.location");
72 var locationTitle
= document
.querySelector(".sidebar h2.location");
73 if (mobileLocationTitle
&& locationTitle
) {
74 mobileLocationTitle
.innerHTML
= locationTitle
.innerHTML
;
79 // Gets the human-readable string for the virtual-key code of the
80 // given KeyboardEvent, ev.
82 // This function is meant as a polyfill for KeyboardEvent#key,
83 // since it is not supported in IE 11 or Chrome for Android. We also test for
84 // KeyboardEvent#keyCode because the handleShortcut handler is
85 // also registered for the keydown event, because Blink doesn't fire
86 // keypress on hitting the Escape key.
88 // So I guess you could say things are getting pretty interoperable.
89 function getVirtualKey(ev
) {
90 if ("key" in ev
&& typeof ev
.key
!= "undefined") {
94 var c
= ev
.charCode
|| ev
.keyCode
;
98 return String
.fromCharCode(c
);
101 var THEME_PICKER_ELEMENT_ID
= "theme-picker";
102 var THEMES_ELEMENT_ID
= "theme-choices";
103 var MAIN_ID
= "main-content";
105 function getThemesElement() {
106 return document
.getElementById(THEMES_ELEMENT_ID
);
109 function getThemePickerElement() {
110 return document
.getElementById(THEME_PICKER_ELEMENT_ID
);
113 // Returns the current URL without any query parameter or hash.
114 function getNakedUrl() {
115 return window
.location
.href
.split("?")[0].split("#")[0];
118 function showThemeButtonState() {
119 var themePicker
= getThemePickerElement();
120 var themeChoices
= getThemesElement();
122 themeChoices
.style
.display
= "block";
123 themePicker
.style
.borderBottomRightRadius
= "0";
124 themePicker
.style
.borderBottomLeftRadius
= "0";
127 function hideThemeButtonState() {
128 var themePicker
= getThemePickerElement();
129 var themeChoices
= getThemesElement();
131 themeChoices
.style
.display
= "none";
132 themePicker
.style
.borderBottomRightRadius
= "3px";
133 themePicker
.style
.borderBottomLeftRadius
= "3px";
136 // Set up the theme picker list.
138 if (!document
.location
.href
.startsWith("file:///")) {
141 var themeChoices
= getThemesElement();
142 var themePicker
= getThemePickerElement();
143 var availableThemes
= getVar("themes").split(",");
145 removeClass(themeChoices
.parentElement
, "hidden");
147 function switchThemeButtonState() {
148 if (themeChoices
.style
.display
=== "block") {
149 hideThemeButtonState();
151 showThemeButtonState();
155 function handleThemeButtonsBlur(e
) {
156 var active
= document
.activeElement
;
157 var related
= e
.relatedTarget
;
159 if (active
.id
!== THEME_PICKER_ELEMENT_ID
&&
160 (!active
.parentNode
|| active
.parentNode
.id
!== THEMES_ELEMENT_ID
) &&
162 (related
.id
!== THEME_PICKER_ELEMENT_ID
&&
163 (!related
.parentNode
|| related
.parentNode
.id
!== THEMES_ELEMENT_ID
)))) {
164 hideThemeButtonState();
168 themePicker
.onclick
= switchThemeButtonState
;
169 themePicker
.onblur
= handleThemeButtonsBlur
;
170 availableThemes
.forEach(function(item
) {
171 var but
= document
.createElement("button");
172 but
.textContent
= item
;
173 but
.onclick = function() {
174 switchTheme(window
.currentTheme
, window
.mainTheme
, item
, true);
175 useSystemTheme(false);
177 but
.onblur
= handleThemeButtonsBlur
;
178 themeChoices
.appendChild(but
);
185 window
.searchState
= {
186 loadingText
: "Loading search results...",
187 input
: document
.getElementsByClassName("search-input")[0],
188 outputElement: function() {
189 return document
.getElementById("search");
191 title
: document
.title
,
192 titleBeforeSearch
: document
.title
,
194 // On the search screen, so you remain on the last tab you opened.
197 // 1 for "In Parameters"
198 // 2 for "In Return Types"
200 // tab and back preserves the element that was focused.
201 focusedByTab
: [null, null, null],
202 clearInputTimeout: function() {
203 if (searchState
.timeout
!== null) {
204 clearTimeout(searchState
.timeout
);
205 searchState
.timeout
= null;
208 // Sets the focus on the search bar at the top of the page
210 searchState
.input
.focus();
212 // Removes the focus from the search bar.
213 defocus: function() {
214 searchState
.input
.blur();
216 showResults: function(search
) {
217 if (search
=== null || typeof search
=== 'undefined') {
218 search
= searchState
.outputElement();
220 addClass(main
, "hidden");
221 removeClass(search
, "hidden");
222 searchState
.mouseMovedAfterSearch
= false;
223 document
.title
= searchState
.title
;
225 hideResults: function(search
) {
226 if (search
=== null || typeof search
=== 'undefined') {
227 search
= searchState
.outputElement();
229 addClass(search
, "hidden");
230 removeClass(main
, "hidden");
231 document
.title
= searchState
.titleBeforeSearch
;
232 // We also remove the query parameter from the URL.
233 if (searchState
.browserSupportsHistoryApi()) {
234 history
.replaceState(null, window
.currentCrate
+ " - Rust",
235 getNakedUrl() + window
.location
.hash
);
238 getQueryStringParams: function() {
240 window
.location
.search
.substring(1).split("&").
242 var pair
= s
.split("=");
243 params
[decodeURIComponent(pair
[0])] =
244 typeof pair
[1] === "undefined" ? null : decodeURIComponent(pair
[1]);
248 browserSupportsHistoryApi: function() {
249 return window
.history
&& typeof window
.history
.pushState
=== "function";
252 var search_input
= searchState
.input
;
253 if (!searchState
.input
) {
256 function loadScript(url
) {
257 var script
= document
.createElement('script');
259 document
.head
.append(script
);
262 var searchLoaded
= false;
263 function loadSearch() {
266 loadScript(window
.searchJS
);
267 loadScript(window
.searchIndexJS
);
271 search_input
.addEventListener("focus", function() {
272 search_input
.origPlaceholder
= search_input
.placeholder
;
273 search_input
.placeholder
= "Type your search here.";
277 if (search_input
.value
!= '') {
281 var params
= searchState
.getQueryStringParams();
282 if (params
.search
!== undefined) {
283 var search
= searchState
.outputElement();
284 search
.innerHTML
= "<h3 class=\"search-loading\">" +
285 searchState
.loadingText
+ "</h3>";
286 searchState
.showResults(search
);
292 function getPageId() {
293 if (window
.location
.hash
) {
294 var tmp
= window
.location
.hash
.replace(/^#/, "");
295 if (tmp
.length
> 0) {
302 var toggleAllDocsId
= "toggle-all-docs";
303 var main
= document
.getElementById(MAIN_ID
);
306 function handleHashes(ev
) {
308 var search
= searchState
.outputElement();
309 if (ev
!== null && search
&& !hasClass(search
, "hidden") && ev
.newURL
) {
310 // This block occurs when clicking on an element in the navbar while
312 searchState
.hideResults(search
);
313 var hash
= ev
.newURL
.slice(ev
.newURL
.indexOf("#") + 1);
314 if (searchState
.browserSupportsHistoryApi()) {
315 // `window.location.search`` contains all the query parameters, not just `search`.
316 history
.replaceState(null, "",
317 getNakedUrl() + window
.location
.search
+ "#" + hash
);
319 elem
= document
.getElementById(hash
);
321 elem
.scrollIntoView();
324 // This part is used in case an element is not visible.
325 if (savedHash
!== window
.location
.hash
) {
326 savedHash
= window
.location
.hash
;
327 if (savedHash
.length
=== 0) {
330 expandSection(savedHash
.slice(1)); // we remove the '#'
334 function onHashChange(ev
) {
335 // If we're in mobile mode, we should hide the sidebar in any case.
336 var sidebar
= document
.getElementsByClassName("sidebar")[0];
337 removeClass(sidebar
, "shown");
341 function openParentDetails(elem
) {
343 if (elem
.tagName
=== "DETAILS") {
346 elem
= elem
.parentNode
;
350 function expandSection(id
) {
351 openParentDetails(document
.getElementById(id
));
354 function getHelpElement(build
) {
358 return document
.getElementById("help");
362 * Show the help popup.
364 * @param {boolean} display - Whether to show or hide the popup
365 * @param {Event} ev - The event that triggered this call
366 * @param {Element} [help] - The help element if it already exists
368 function displayHelp(display
, ev
, help
) {
370 help
= help
? help
: getHelpElement(true);
371 if (hasClass(help
, "hidden")) {
373 removeClass(help
, "hidden");
374 addClass(document
.body
, "blur");
377 // No need to build the help popup if we want to hide it in case it hasn't been
379 help
= help
? help
: getHelpElement(false);
380 if (help
&& !hasClass(help
, "hidden")) {
382 addClass(help
, "hidden");
383 removeClass(document
.body
, "blur");
388 function handleEscape(ev
) {
389 var help
= getHelpElement(false);
390 var search
= searchState
.outputElement();
391 if (help
&& !hasClass(help
, "hidden")) {
392 displayHelp(false, ev
, help
);
393 } else if (search
&& !hasClass(search
, "hidden")) {
394 searchState
.clearInputTimeout();
396 searchState
.hideResults(search
);
398 searchState
.defocus();
399 hideThemeButtonState();
402 var disableShortcuts
= getSettingValue("disable-shortcuts") === "true";
403 function handleShortcut(ev
) {
404 // Don't interfere with browser shortcuts
405 if (ev
.ctrlKey
|| ev
.altKey
|| ev
.metaKey
|| disableShortcuts
) {
409 if (document
.activeElement
.tagName
=== "INPUT") {
410 switch (getVirtualKey(ev
)) {
416 switch (getVirtualKey(ev
)) {
423 displayHelp(false, ev
);
435 displayHelp(true, ev
);
440 displayHelp(false, ev
);
442 var themePicker
= getThemePickerElement();
448 if (getThemePickerElement().parentNode
.contains(ev
.target
)) {
449 handleThemeKeyDown(ev
);
455 function handleThemeKeyDown(ev
) {
456 var active
= document
.activeElement
;
457 var themes
= getThemesElement();
458 switch (getVirtualKey(ev
)) {
461 if (active
.previousElementSibling
&& ev
.target
.id
!== THEME_PICKER_ELEMENT_ID
) {
462 active
.previousElementSibling
.focus();
464 showThemeButtonState();
465 themes
.lastElementChild
.focus();
470 if (active
.nextElementSibling
&& ev
.target
.id
!== THEME_PICKER_ELEMENT_ID
) {
471 active
.nextElementSibling
.focus();
473 showThemeButtonState();
474 themes
.firstElementChild
.focus();
480 if (ev
.target
.id
=== THEME_PICKER_ELEMENT_ID
&& themes
.style
.display
=== "none") {
482 showThemeButtonState();
483 themes
.firstElementChild
.focus();
488 themes
.firstElementChild
.focus();
492 themes
.lastElementChild
.focus();
494 // The escape key is handled in handleEscape, not here,
495 // so that pressing escape will close the menu even if it isn't focused
499 document
.addEventListener("keypress", handleShortcut
);
500 document
.addEventListener("keydown", handleShortcut
);
503 var x
= document
.getElementsByClassName("version-selector");
505 x
[0].onchange = function() {
507 url
= document
.location
.href
,
509 len
= window
.rootPath
.match(/\.\.\//g).length
+ 1;
511 for (i
= 0; i
< len
; ++i
) {
512 match
= url
.match(/\/[^/]*$/);
514 stripped
= match
[0] + stripped
;
516 url
= url
.substring(0, url
.length
- match
[0].length
);
519 var selectedVersion
= document
.getElementsByClassName("version-selector")[0].value
;
520 url
+= "/" + selectedVersion
+ stripped
;
522 document
.location
.href
= url
;
527 // delayed sidebar rendering.
528 window
.initSidebarItems = function(items
) {
529 var sidebar
= document
.getElementsByClassName("sidebar-elems")[0];
531 var current
= window
.sidebarCurrent
;
533 function addSidebarCrates(crates
) {
534 if (!hasClass(document
.body
, "crate")) {
535 // We only want to list crates on the crate page.
538 // Draw a convenient sidebar of known crates if we have a listing
539 var div
= document
.createElement("div");
540 div
.className
= "block crate";
541 div
.innerHTML
= "<h3>Crates</h3>";
542 var ul
= document
.createElement("ul");
545 for (var i
= 0; i
< crates
.length
; ++i
) {
547 if (window
.rootPath
!== "./" && crates
[i
] === window
.currentCrate
) {
550 var link
= document
.createElement("a");
551 link
.href
= window
.rootPath
+ crates
[i
] + "/index.html";
552 link
.className
= klass
;
553 link
.textContent
= crates
[i
];
555 var li
= document
.createElement("li");
556 li
.appendChild(link
);
559 others
.appendChild(div
);
563 * Append to the sidebar a "block" of links - a heading along with a list (`<ul>`) of items.
565 * @param {string} shortty - A short type name, like "primitive", "mod", or "macro"
566 * @param {string} id - The HTML id of the corresponding section on the module page.
567 * @param {string} longty - A long, capitalized, plural name, like "Primitive Types",
568 * "Modules", or "Macros".
570 function block(shortty
, id
, longty
) {
571 var filtered
= items
[shortty
];
576 var div
= document
.createElement("div");
577 div
.className
= "block " + shortty
;
578 var h3
= document
.createElement("h3");
579 h3
.innerHTML
= `<a href="index.html#${id}">${longty}</a>`;
581 var ul
= document
.createElement("ul");
583 for (var i
= 0, len
= filtered
.length
; i
< len
; ++i
) {
584 var item
= filtered
[i
];
586 var desc
= item
[1]; // can be null
589 if (name
=== current
.name
&& shortty
=== current
.ty
) {
593 if (shortty
=== "mod") {
594 path
= name
+ "/index.html";
596 path
= shortty
+ "." + name
+ ".html";
598 var link
= document
.createElement("a");
599 link
.href
= current
.relpath
+ path
;
601 link
.className
= klass
;
602 link
.textContent
= name
;
603 var li
= document
.createElement("li");
604 li
.appendChild(link
);
608 others
.appendChild(div
);
612 others
= document
.createElement("div");
613 others
.className
= "others";
614 sidebar
.appendChild(others
);
616 var isModule
= hasClass(document
.body
, "mod");
618 block("primitive", "primitives", "Primitive Types");
619 block("mod", "modules", "Modules");
620 block("macro", "macros", "Macros");
621 block("struct", "structs", "Structs");
622 block("enum", "enums", "Enums");
623 block("union", "unions", "Unions");
624 block("constant", "constants", "Constants");
625 block("static", "static", "Statics");
626 block("trait", "traits", "Traits");
627 block("fn", "functions", "Functions");
628 block("type", "types", "Type Definitions");
629 block("foreigntype", "foreign-types", "Foreign Types");
630 block("keyword", "keywords", "Keywords");
631 block("traitalias", "trait-aliases", "Trait Aliases");
634 // `crates{version}.js` should always be loaded before this script, so we can use
636 addSidebarCrates(window
.ALL_CRATES
);
640 window
.register_implementors = function(imp
) {
641 var implementors
= document
.getElementById("implementors-list");
642 var synthetic_implementors
= document
.getElementById("synthetic-implementors-list");
644 if (synthetic_implementors
) {
645 // This `inlined_types` variable is used to avoid having the same implementation
646 // showing up twice. For example "String" in the "Sync" doc page.
648 // By the way, this is only used by and useful for traits implemented automatically
649 // (like "Send" and "Sync").
650 var inlined_types
= new Set();
651 onEachLazy(synthetic_implementors
.getElementsByClassName("impl"), function(el
) {
652 var aliases
= el
.getAttribute("data-aliases");
656 aliases
.split(",").forEach(function(alias
) {
657 inlined_types
.add(alias
);
662 var currentNbImpls
= implementors
.getElementsByClassName("impl").length
;
663 var traitName
= document
.querySelector("h1.fqn > .in-band > .trait").textContent
;
664 var baseIdName
= "impl-" + traitName
+ "-";
665 var libs
= Object
.getOwnPropertyNames(imp
);
666 for (var i
= 0, llength
= libs
.length
; i
< llength
; ++i
) {
667 if (libs
[i
] === window
.currentCrate
) { continue; }
668 var structs
= imp
[libs
[i
]];
671 for (var j
= 0, slength
= structs
.length
; j
< slength
; ++j
) {
672 var struct
= structs
[j
];
674 var list
= struct
.synthetic
? synthetic_implementors
: implementors
;
676 if (struct
.synthetic
) {
677 for (var k
= 0, stlength
= struct
.types
.length
; k
< stlength
; k
++) {
678 if (inlined_types
.has(struct
.types
[k
])) {
679 continue struct_loop
;
681 inlined_types
.add(struct
.types
[k
]);
685 var code
= document
.createElement("h3");
686 code
.innerHTML
= struct
.text
;
687 addClass(code
, "code-header");
688 addClass(code
, "in-band");
690 onEachLazy(code
.getElementsByTagName("a"), function(elem
) {
691 var href
= elem
.getAttribute("href");
693 if (href
&& href
.indexOf("http") !== 0) {
694 elem
.setAttribute("href", window
.rootPath
+ href
);
698 var currentId
= baseIdName
+ currentNbImpls
;
699 var anchor
= document
.createElement("a");
700 anchor
.href
= "#" + currentId
;
701 addClass(anchor
, "anchor");
703 var display
= document
.createElement("div");
704 display
.id
= currentId
;
705 addClass(display
, "impl");
706 display
.appendChild(anchor
);
707 display
.appendChild(code
);
708 list
.appendChild(display
);
713 if (window
.pending_implementors
) {
714 window
.register_implementors(window
.pending_implementors
);
717 function labelForToggleButton(sectionIsCollapsed
) {
718 if (sectionIsCollapsed
) {
719 // button will expand the section
722 // button will collapse the section
723 // note that this text is also set in the HTML template in ../render/mod.rs
724 return "\u2212"; // "\u2212" is "−" minus sign
727 function toggleAllDocs() {
728 var innerToggle
= document
.getElementById(toggleAllDocsId
);
732 var sectionIsCollapsed
= false;
733 if (hasClass(innerToggle
, "will-expand")) {
734 removeClass(innerToggle
, "will-expand");
735 onEachLazy(document
.getElementsByClassName("rustdoc-toggle"), function(e
) {
736 if (!hasClass(e
, "type-contents-toggle")) {
740 innerToggle
.title
= "collapse all docs";
742 addClass(innerToggle
, "will-expand");
743 onEachLazy(document
.getElementsByClassName("rustdoc-toggle"), function(e
) {
744 if (e
.parentNode
.id
!== MAIN_ID
||
745 (!hasClass(e
, "implementors-toggle") &&
746 !hasClass(e
, "type-contents-toggle")))
751 sectionIsCollapsed
= true;
752 innerToggle
.title
= "expand all docs";
754 innerToggle
.children
[0].innerText
= labelForToggleButton(sectionIsCollapsed
);
757 function insertAfter(newNode
, referenceNode
) {
758 referenceNode
.parentNode
.insertBefore(newNode
, referenceNode
.nextSibling
);
762 var toggles
= document
.getElementById(toggleAllDocsId
);
764 toggles
.onclick
= toggleAllDocs
;
767 var hideMethodDocs
= getSettingValue("auto-hide-method-docs") === "true";
768 var hideImplementations
= getSettingValue("auto-hide-trait-implementations") === "true";
769 var hideLargeItemContents
= getSettingValue("auto-hide-large-items") !== "false";
771 function setImplementorsTogglesOpen(id
, open
) {
772 var list
= document
.getElementById(id
);
774 onEachLazy(list
.getElementsByClassName("implementors-toggle"), function(e
) {
780 if (hideImplementations
) {
781 setImplementorsTogglesOpen("trait-implementations-list", false);
782 setImplementorsTogglesOpen("blanket-implementations-list", false);
785 onEachLazy(document
.getElementsByClassName("rustdoc-toggle"), function (e
) {
786 if (!hideLargeItemContents
&& hasClass(e
, "type-contents-toggle")) {
789 if (hideMethodDocs
&& hasClass(e
, "method-toggle")) {
795 var pageId
= getPageId();
796 if (pageId
!== null) {
797 expandSection(pageId
);
802 // To avoid checking on "rustdoc-line-numbers" value on every loop...
803 var lineNumbersFunc = function() {};
804 if (getSettingValue("line-numbers") === "true") {
805 lineNumbersFunc = function(x
) {
806 var count
= x
.textContent
.split("\n").length
;
808 for (var i
= 0; i
< count
; ++i
) {
811 var node
= document
.createElement("pre");
812 addClass(node
, "line-number");
813 node
.innerHTML
= elems
.join("\n");
814 x
.parentNode
.insertBefore(node
, x
);
817 onEachLazy(document
.getElementsByClassName("rust-example-rendered"), function(e
) {
818 if (hasClass(e
, "compile_fail")) {
819 e
.addEventListener("mouseover", function() {
820 this.parentElement
.previousElementSibling
.childNodes
[0].style
.color
= "#f00";
822 e
.addEventListener("mouseout", function() {
823 this.parentElement
.previousElementSibling
.childNodes
[0].style
.color
= "";
825 } else if (hasClass(e
, "ignore")) {
826 e
.addEventListener("mouseover", function() {
827 this.parentElement
.previousElementSibling
.childNodes
[0].style
.color
= "#ff9200";
829 e
.addEventListener("mouseout", function() {
830 this.parentElement
.previousElementSibling
.childNodes
[0].style
.color
= "";
837 function hideSidebar() {
838 var sidebar
= document
.getElementsByClassName("sidebar")[0];
839 removeClass(sidebar
, "shown");
842 function handleClick(id
, f
) {
843 var elem
= document
.getElementById(id
);
845 elem
.addEventListener("click", f
);
848 handleClick("help-button", function(ev
) {
849 displayHelp(true, ev
);
851 handleClick(MAIN_ID
, function() {
855 onEachLazy(document
.getElementsByTagName("a"), function(el
) {
856 // For clicks on internal links (<A> tags with a hash property), we expand the section we're
857 // jumping to *before* jumping there. We can't do this in onHashChange, because it changes
858 // the height of the document so we wind up scrolled to the wrong place.
860 el
.addEventListener("click", function() {
861 expandSection(el
.hash
.slice(1));
867 onEachLazy(document
.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"), function(el
) {
868 el
.addEventListener("click", function(e
) {
869 if (e
.target
.tagName
!= "SUMMARY" && e
.target
.tagName
!= "A") {
875 onEachLazy(document
.getElementsByClassName("notable-traits"), function(e
) {
876 e
.onclick = function() {
877 this.getElementsByClassName('notable-traits-tooltiptext')[0]
878 .classList
.toggle("force-tooltip");
882 var sidebar_menu_toggle
= document
.getElementsByClassName("sidebar-menu-toggle")[0];
883 if (sidebar_menu_toggle
) {
884 sidebar_menu_toggle
.addEventListener("click", function() {
885 var sidebar
= document
.getElementsByClassName("sidebar")[0];
886 if (!hasClass(sidebar
, "shown")) {
887 addClass(sidebar
, "shown");
889 removeClass(sidebar
, "shown");
894 var buildHelperPopup = function() {
895 var popup
= document
.createElement("aside");
896 addClass(popup
, "hidden");
899 popup
.addEventListener("click", function(ev
) {
900 if (ev
.target
=== popup
) {
901 // Clicked the blurred zone outside the help popup; dismiss help.
902 displayHelp(false, ev
);
906 var book_info
= document
.createElement("span");
907 book_info
.className
= "top";
908 book_info
.innerHTML
= "You can find more information in \
909 <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
911 var container
= document
.createElement("div");
913 ["?", "Show this help dialog"],
914 ["S", "Focus the search field"],
915 ["T", "Focus the theme picker menu"],
916 ["↑", "Move up in search results"],
917 ["↓", "Move down in search results"],
918 ["← / →", "Switch result tab (when results focused)"],
919 ["⏎", "Go to active search result"],
920 ["+", "Expand all sections"],
921 ["-", "Collapse all sections"],
925 .map(function(y
, index
) {
926 return (index
& 1) === 0 ? "<kbd>" + y
+ "</kbd>" : " " + y
+ " ";
928 .join("") + "</dt><dd>" + x
[1] + "</dd>";
930 var div_shortcuts
= document
.createElement("div");
931 addClass(div_shortcuts
, "shortcuts");
932 div_shortcuts
.innerHTML
= "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts
+ "</dl></div>";
935 "Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
936 restrict the search to a given item kind.",
937 "Accepted kinds are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
938 <code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, \
939 and <code>const</code>.",
940 "Search functions by type signature (e.g., <code>vec -> usize</code> or \
941 <code>* -> vec</code>)",
942 "Search multiple things at once by splitting your query with comma (e.g., \
943 <code>str,u8</code> or <code>String,struct:Vec,test</code>)",
944 "You can look for items with an exact name by putting double quotes around \
945 your request: <code>\"string\"</code>",
946 "Look for items inside another one by searching for a path: <code>vec::Vec</code>",
948 return "<p>" + x
+ "</p>";
950 var div_infos
= document
.createElement("div");
951 addClass(div_infos
, "infos");
952 div_infos
.innerHTML
= "<h2>Search Tricks</h2>" + infos
;
954 container
.appendChild(book_info
);
955 container
.appendChild(div_shortcuts
);
956 container
.appendChild(div_infos
);
958 var rustdoc_version
= document
.createElement("span");
959 rustdoc_version
.className
= "bottom";
960 var rustdoc_version_code
= document
.createElement("code");
961 rustdoc_version_code
.innerText
= "rustdoc " + getVar("rustdoc-version");
962 rustdoc_version
.appendChild(rustdoc_version_code
);
964 container
.appendChild(rustdoc_version
);
966 popup
.appendChild(container
);
967 insertAfter(popup
, document
.querySelector("main"));
968 // So that it's only built once and then it'll do nothing when called!
969 buildHelperPopup = function() {};
973 window
.addEventListener("hashchange", onHashChange
);
978 var reset_button_timeout
= null;
980 window
.copy_path = function(but
) {
981 var parent
= but
.parentElement
;
984 onEach(parent
.childNodes
, function(child
) {
985 if (child
.tagName
=== 'A') {
986 path
.push(child
.textContent
);
990 var el
= document
.createElement('textarea');
991 el
.value
= path
.join('::');
992 el
.setAttribute('readonly', '');
993 // To not make it appear on the screen.
994 el
.style
.position
= 'absolute';
995 el
.style
.left
= '-9999px';
997 document
.body
.appendChild(el
);
999 document
.execCommand('copy');
1000 document
.body
.removeChild(el
);
1002 // There is always one children, but multiple childNodes.
1003 but
.children
[0].style
.display
= 'none';
1006 if (but
.childNodes
.length
< 2) {
1007 tmp
= document
.createTextNode('✓');
1008 but
.appendChild(tmp
);
1010 onEachLazy(but
.childNodes
, function(e
) {
1011 if (e
.nodeType
=== Node
.TEXT_NODE
) {
1016 tmp
.textContent
= '✓';
1019 if (reset_button_timeout
!== null) {
1020 window
.clearTimeout(reset_button_timeout
);
1023 function reset_button() {
1024 tmp
.textContent
= '';
1025 reset_button_timeout
= null;
1026 but
.children
[0].style
.display
= "";
1029 reset_button_timeout
= window
.setTimeout(reset_button
, 1000);