]> git.proxmox.com Git - rustc.git/blob - src/librustdoc/html/static/js/main.js
New upstream version 1.60.0+dfsg1
[rustc.git] / 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 */
5
6 if (!String.prototype.startsWith) {
7 String.prototype.startsWith = function(searchString, position) {
8 position = position || 0;
9 return this.indexOf(searchString, position) === position;
10 };
11 }
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;
16 };
17 }
18
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;
24 } else {
25 this.className = className;
26 }
27 }
28 };
29 }
30
31 if (!DOMTokenList.prototype.remove) {
32 DOMTokenList.prototype.remove = function(className) {
33 if (className && this.className) {
34 this.className = (" " + this.className + " ").replace(" " + className + " ", " ")
35 .trim();
36 }
37 };
38 }
39
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");
44 if (el) {
45 return el.attributes["data-" + name].value;
46 } else {
47 return null;
48 }
49 }
50
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;
55 }
56
57 (function () {
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");
63 if (sidebarVars) {
64 window.sidebarCurrent = {
65 name: sidebarVars.attributes["data-name"].value,
66 ty: sidebarVars.attributes["data-ty"].value,
67 relpath: sidebarVars.attributes["data-relpath"].value,
68 };
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;
75 }
76 }
77 }());
78
79 // Gets the human-readable string for the virtual-key code of the
80 // given KeyboardEvent, ev.
81 //
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.
87 //
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") {
91 return ev.key;
92 }
93
94 var c = ev.charCode || ev.keyCode;
95 if (c == 27) {
96 return "Escape";
97 }
98 return String.fromCharCode(c);
99 }
100
101 var THEME_PICKER_ELEMENT_ID = "theme-picker";
102 var THEMES_ELEMENT_ID = "theme-choices";
103 var MAIN_ID = "main-content";
104
105 function getThemesElement() {
106 return document.getElementById(THEMES_ELEMENT_ID);
107 }
108
109 function getThemePickerElement() {
110 return document.getElementById(THEME_PICKER_ELEMENT_ID);
111 }
112
113 // Returns the current URL without any query parameter or hash.
114 function getNakedUrl() {
115 return window.location.href.split("?")[0].split("#")[0];
116 }
117
118 function showThemeButtonState() {
119 var themePicker = getThemePickerElement();
120 var themeChoices = getThemesElement();
121
122 themeChoices.style.display = "block";
123 themePicker.style.borderBottomRightRadius = "0";
124 themePicker.style.borderBottomLeftRadius = "0";
125 }
126
127 function hideThemeButtonState() {
128 var themePicker = getThemePickerElement();
129 var themeChoices = getThemesElement();
130
131 themeChoices.style.display = "none";
132 themePicker.style.borderBottomRightRadius = "3px";
133 themePicker.style.borderBottomLeftRadius = "3px";
134 }
135
136 // Set up the theme picker list.
137 (function () {
138 if (!document.location.href.startsWith("file:///")) {
139 return;
140 }
141 var themeChoices = getThemesElement();
142 var themePicker = getThemePickerElement();
143 var availableThemes = getVar("themes").split(",");
144
145 removeClass(themeChoices.parentElement, "hidden");
146
147 function switchThemeButtonState() {
148 if (themeChoices.style.display === "block") {
149 hideThemeButtonState();
150 } else {
151 showThemeButtonState();
152 }
153 }
154
155 function handleThemeButtonsBlur(e) {
156 var active = document.activeElement;
157 var related = e.relatedTarget;
158
159 if (active.id !== THEME_PICKER_ELEMENT_ID &&
160 (!active.parentNode || active.parentNode.id !== THEMES_ELEMENT_ID) &&
161 (!related ||
162 (related.id !== THEME_PICKER_ELEMENT_ID &&
163 (!related.parentNode || related.parentNode.id !== THEMES_ELEMENT_ID)))) {
164 hideThemeButtonState();
165 }
166 }
167
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);
176 };
177 but.onblur = handleThemeButtonsBlur;
178 themeChoices.appendChild(but);
179 });
180 }());
181
182 (function() {
183 "use strict";
184
185 window.searchState = {
186 loadingText: "Loading search results...",
187 input: document.getElementsByClassName("search-input")[0],
188 outputElement: function() {
189 return document.getElementById("search");
190 },
191 title: document.title,
192 titleBeforeSearch: document.title,
193 timeout: null,
194 // On the search screen, so you remain on the last tab you opened.
195 //
196 // 0 for "In Names"
197 // 1 for "In Parameters"
198 // 2 for "In Return Types"
199 currentTab: 0,
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;
206 }
207 },
208 // Sets the focus on the search bar at the top of the page
209 focus: function() {
210 searchState.input.focus();
211 },
212 // Removes the focus from the search bar.
213 defocus: function() {
214 searchState.input.blur();
215 },
216 showResults: function(search) {
217 if (search === null || typeof search === 'undefined') {
218 search = searchState.outputElement();
219 }
220 addClass(main, "hidden");
221 removeClass(search, "hidden");
222 searchState.mouseMovedAfterSearch = false;
223 document.title = searchState.title;
224 },
225 hideResults: function(search) {
226 if (search === null || typeof search === 'undefined') {
227 search = searchState.outputElement();
228 }
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);
236 }
237 },
238 getQueryStringParams: function() {
239 var params = {};
240 window.location.search.substring(1).split("&").
241 map(function(s) {
242 var pair = s.split("=");
243 params[decodeURIComponent(pair[0])] =
244 typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
245 });
246 return params;
247 },
248 browserSupportsHistoryApi: function() {
249 return window.history && typeof window.history.pushState === "function";
250 },
251 setup: function() {
252 var search_input = searchState.input;
253 if (!searchState.input) {
254 return;
255 }
256 function loadScript(url) {
257 var script = document.createElement('script');
258 script.src = url;
259 document.head.append(script);
260 }
261
262 var searchLoaded = false;
263 function loadSearch() {
264 if (!searchLoaded) {
265 searchLoaded = true;
266 loadScript(window.searchJS);
267 loadScript(window.searchIndexJS);
268 }
269 }
270
271 search_input.addEventListener("focus", function() {
272 search_input.origPlaceholder = search_input.placeholder;
273 search_input.placeholder = "Type your search here.";
274 loadSearch();
275 });
276
277 if (search_input.value != '') {
278 loadSearch();
279 }
280
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);
287 loadSearch();
288 }
289 },
290 };
291
292 function getPageId() {
293 if (window.location.hash) {
294 var tmp = window.location.hash.replace(/^#/, "");
295 if (tmp.length > 0) {
296 return tmp;
297 }
298 }
299 return null;
300 }
301
302 var toggleAllDocsId = "toggle-all-docs";
303 var main = document.getElementById(MAIN_ID);
304 var savedHash = "";
305
306 function handleHashes(ev) {
307 var elem;
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
311 // in a search.
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);
318 }
319 elem = document.getElementById(hash);
320 if (elem) {
321 elem.scrollIntoView();
322 }
323 }
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) {
328 return;
329 }
330 expandSection(savedHash.slice(1)); // we remove the '#'
331 }
332 }
333
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");
338 handleHashes(ev);
339 }
340
341 function openParentDetails(elem) {
342 while (elem) {
343 if (elem.tagName === "DETAILS") {
344 elem.open = true;
345 }
346 elem = elem.parentNode;
347 }
348 }
349
350 function expandSection(id) {
351 openParentDetails(document.getElementById(id));
352 }
353
354 function getHelpElement(build) {
355 if (build) {
356 buildHelperPopup();
357 }
358 return document.getElementById("help");
359 }
360
361 /**
362 * Show the help popup.
363 *
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
367 */
368 function displayHelp(display, ev, help) {
369 if (display) {
370 help = help ? help : getHelpElement(true);
371 if (hasClass(help, "hidden")) {
372 ev.preventDefault();
373 removeClass(help, "hidden");
374 addClass(document.body, "blur");
375 }
376 } else {
377 // No need to build the help popup if we want to hide it in case it hasn't been
378 // built yet...
379 help = help ? help : getHelpElement(false);
380 if (help && !hasClass(help, "hidden")) {
381 ev.preventDefault();
382 addClass(help, "hidden");
383 removeClass(document.body, "blur");
384 }
385 }
386 }
387
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();
395 ev.preventDefault();
396 searchState.hideResults(search);
397 }
398 searchState.defocus();
399 hideThemeButtonState();
400 }
401
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) {
406 return;
407 }
408
409 if (document.activeElement.tagName === "INPUT") {
410 switch (getVirtualKey(ev)) {
411 case "Escape":
412 handleEscape(ev);
413 break;
414 }
415 } else {
416 switch (getVirtualKey(ev)) {
417 case "Escape":
418 handleEscape(ev);
419 break;
420
421 case "s":
422 case "S":
423 displayHelp(false, ev);
424 ev.preventDefault();
425 searchState.focus();
426 break;
427
428 case "+":
429 case "-":
430 ev.preventDefault();
431 toggleAllDocs();
432 break;
433
434 case "?":
435 displayHelp(true, ev);
436 break;
437
438 case "t":
439 case "T":
440 displayHelp(false, ev);
441 ev.preventDefault();
442 var themePicker = getThemePickerElement();
443 themePicker.click();
444 themePicker.focus();
445 break;
446
447 default:
448 if (getThemePickerElement().parentNode.contains(ev.target)) {
449 handleThemeKeyDown(ev);
450 }
451 }
452 }
453 }
454
455 function handleThemeKeyDown(ev) {
456 var active = document.activeElement;
457 var themes = getThemesElement();
458 switch (getVirtualKey(ev)) {
459 case "ArrowUp":
460 ev.preventDefault();
461 if (active.previousElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
462 active.previousElementSibling.focus();
463 } else {
464 showThemeButtonState();
465 themes.lastElementChild.focus();
466 }
467 break;
468 case "ArrowDown":
469 ev.preventDefault();
470 if (active.nextElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
471 active.nextElementSibling.focus();
472 } else {
473 showThemeButtonState();
474 themes.firstElementChild.focus();
475 }
476 break;
477 case "Enter":
478 case "Return":
479 case "Space":
480 if (ev.target.id === THEME_PICKER_ELEMENT_ID && themes.style.display === "none") {
481 ev.preventDefault();
482 showThemeButtonState();
483 themes.firstElementChild.focus();
484 }
485 break;
486 case "Home":
487 ev.preventDefault();
488 themes.firstElementChild.focus();
489 break;
490 case "End":
491 ev.preventDefault();
492 themes.lastElementChild.focus();
493 break;
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
496 }
497 }
498
499 document.addEventListener("keypress", handleShortcut);
500 document.addEventListener("keydown", handleShortcut);
501
502 (function() {
503 var x = document.getElementsByClassName("version-selector");
504 if (x.length > 0) {
505 x[0].onchange = function() {
506 var i, match,
507 url = document.location.href,
508 stripped = "",
509 len = window.rootPath.match(/\.\.\//g).length + 1;
510
511 for (i = 0; i < len; ++i) {
512 match = url.match(/\/[^/]*$/);
513 if (i < len - 1) {
514 stripped = match[0] + stripped;
515 }
516 url = url.substring(0, url.length - match[0].length);
517 }
518
519 var selectedVersion = document.getElementsByClassName("version-selector")[0].value;
520 url += "/" + selectedVersion + stripped;
521
522 document.location.href = url;
523 };
524 }
525 }());
526
527 // delayed sidebar rendering.
528 window.initSidebarItems = function(items) {
529 var sidebar = document.getElementsByClassName("sidebar-elems")[0];
530 var others;
531 var current = window.sidebarCurrent;
532
533 function addSidebarCrates(crates) {
534 if (!hasClass(document.body, "crate")) {
535 // We only want to list crates on the crate page.
536 return;
537 }
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");
543 div.appendChild(ul);
544
545 for (var i = 0; i < crates.length; ++i) {
546 var klass = "crate";
547 if (window.rootPath !== "./" && crates[i] === window.currentCrate) {
548 klass += " current";
549 }
550 var link = document.createElement("a");
551 link.href = window.rootPath + crates[i] + "/index.html";
552 link.className = klass;
553 link.textContent = crates[i];
554
555 var li = document.createElement("li");
556 li.appendChild(link);
557 ul.appendChild(li);
558 }
559 others.appendChild(div);
560 }
561
562 /**
563 * Append to the sidebar a "block" of links - a heading along with a list (`<ul>`) of items.
564 *
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".
569 */
570 function block(shortty, id, longty) {
571 var filtered = items[shortty];
572 if (!filtered) {
573 return;
574 }
575
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>`;
580 div.appendChild(h3);
581 var ul = document.createElement("ul");
582
583 for (var i = 0, len = filtered.length; i < len; ++i) {
584 var item = filtered[i];
585 var name = item[0];
586 var desc = item[1]; // can be null
587
588 var klass = shortty;
589 if (name === current.name && shortty === current.ty) {
590 klass += " current";
591 }
592 var path;
593 if (shortty === "mod") {
594 path = name + "/index.html";
595 } else {
596 path = shortty + "." + name + ".html";
597 }
598 var link = document.createElement("a");
599 link.href = current.relpath + path;
600 link.title = desc;
601 link.className = klass;
602 link.textContent = name;
603 var li = document.createElement("li");
604 li.appendChild(link);
605 ul.appendChild(li);
606 }
607 div.appendChild(ul);
608 others.appendChild(div);
609 }
610
611 if (sidebar) {
612 others = document.createElement("div");
613 others.className = "others";
614 sidebar.appendChild(others);
615
616 var isModule = hasClass(document.body, "mod");
617 if (!isModule) {
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");
632 }
633
634 // `crates{version}.js` should always be loaded before this script, so we can use
635 // it safely.
636 addSidebarCrates(window.ALL_CRATES);
637 }
638 };
639
640 window.register_implementors = function(imp) {
641 var implementors = document.getElementById("implementors-list");
642 var synthetic_implementors = document.getElementById("synthetic-implementors-list");
643
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.
647 //
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");
653 if (!aliases) {
654 return;
655 }
656 aliases.split(",").forEach(function(alias) {
657 inlined_types.add(alias);
658 });
659 });
660 }
661
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]];
669
670 struct_loop:
671 for (var j = 0, slength = structs.length; j < slength; ++j) {
672 var struct = structs[j];
673
674 var list = struct.synthetic ? synthetic_implementors : implementors;
675
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;
680 }
681 inlined_types.add(struct.types[k]);
682 }
683 }
684
685 var code = document.createElement("h3");
686 code.innerHTML = struct.text;
687 addClass(code, "code-header");
688 addClass(code, "in-band");
689
690 onEachLazy(code.getElementsByTagName("a"), function(elem) {
691 var href = elem.getAttribute("href");
692
693 if (href && href.indexOf("http") !== 0) {
694 elem.setAttribute("href", window.rootPath + href);
695 }
696 });
697
698 var currentId = baseIdName + currentNbImpls;
699 var anchor = document.createElement("a");
700 anchor.href = "#" + currentId;
701 addClass(anchor, "anchor");
702
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);
709 currentNbImpls += 1;
710 }
711 }
712 };
713 if (window.pending_implementors) {
714 window.register_implementors(window.pending_implementors);
715 }
716
717 function labelForToggleButton(sectionIsCollapsed) {
718 if (sectionIsCollapsed) {
719 // button will expand the section
720 return "+";
721 }
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
725 }
726
727 function toggleAllDocs() {
728 var innerToggle = document.getElementById(toggleAllDocsId);
729 if (!innerToggle) {
730 return;
731 }
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")) {
737 e.open = true;
738 }
739 });
740 innerToggle.title = "collapse all docs";
741 } else {
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")))
747 {
748 e.open = false;
749 }
750 });
751 sectionIsCollapsed = true;
752 innerToggle.title = "expand all docs";
753 }
754 innerToggle.children[0].innerText = labelForToggleButton(sectionIsCollapsed);
755 }
756
757 function insertAfter(newNode, referenceNode) {
758 referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
759 }
760
761 (function() {
762 var toggles = document.getElementById(toggleAllDocsId);
763 if (toggles) {
764 toggles.onclick = toggleAllDocs;
765 }
766
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";
770
771 function setImplementorsTogglesOpen(id, open) {
772 var list = document.getElementById(id);
773 if (list !== null) {
774 onEachLazy(list.getElementsByClassName("implementors-toggle"), function(e) {
775 e.open = open;
776 });
777 }
778 }
779
780 if (hideImplementations) {
781 setImplementorsTogglesOpen("trait-implementations-list", false);
782 setImplementorsTogglesOpen("blanket-implementations-list", false);
783 }
784
785 onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function (e) {
786 if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) {
787 e.open = true;
788 }
789 if (hideMethodDocs && hasClass(e, "method-toggle")) {
790 e.open = false;
791 }
792
793 });
794
795 var pageId = getPageId();
796 if (pageId !== null) {
797 expandSection(pageId);
798 }
799 }());
800
801 (function() {
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;
807 var elems = [];
808 for (var i = 0; i < count; ++i) {
809 elems.push(i + 1);
810 }
811 var node = document.createElement("pre");
812 addClass(node, "line-number");
813 node.innerHTML = elems.join("\n");
814 x.parentNode.insertBefore(node, x);
815 };
816 }
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";
821 });
822 e.addEventListener("mouseout", function() {
823 this.parentElement.previousElementSibling.childNodes[0].style.color = "";
824 });
825 } else if (hasClass(e, "ignore")) {
826 e.addEventListener("mouseover", function() {
827 this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200";
828 });
829 e.addEventListener("mouseout", function() {
830 this.parentElement.previousElementSibling.childNodes[0].style.color = "";
831 });
832 }
833 lineNumbersFunc(e);
834 });
835 }());
836
837 function hideSidebar() {
838 var sidebar = document.getElementsByClassName("sidebar")[0];
839 removeClass(sidebar, "shown");
840 }
841
842 function handleClick(id, f) {
843 var elem = document.getElementById(id);
844 if (elem) {
845 elem.addEventListener("click", f);
846 }
847 }
848 handleClick("help-button", function(ev) {
849 displayHelp(true, ev);
850 });
851 handleClick(MAIN_ID, function() {
852 hideSidebar();
853 });
854
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.
859 if (el.hash) {
860 el.addEventListener("click", function() {
861 expandSection(el.hash.slice(1));
862 hideSidebar();
863 });
864 }
865 });
866
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") {
870 e.preventDefault();
871 }
872 });
873 });
874
875 onEachLazy(document.getElementsByClassName("notable-traits"), function(e) {
876 e.onclick = function() {
877 this.getElementsByClassName('notable-traits-tooltiptext')[0]
878 .classList.toggle("force-tooltip");
879 };
880 });
881
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");
888 } else {
889 removeClass(sidebar, "shown");
890 }
891 });
892 }
893
894 var buildHelperPopup = function() {
895 var popup = document.createElement("aside");
896 addClass(popup, "hidden");
897 popup.id = "help";
898
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);
903 }
904 });
905
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>.";
910
911 var container = document.createElement("div");
912 var shortcuts = [
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 ["&#9166;", "Go to active search result"],
920 ["+", "Expand all sections"],
921 ["-", "Collapse all sections"],
922 ].map(function(x) {
923 return "<dt>" +
924 x[0].split(" ")
925 .map(function(y, index) {
926 return (index & 1) === 0 ? "<kbd>" + y + "</kbd>" : " " + y + " ";
927 })
928 .join("") + "</dt><dd>" + x[1] + "</dd>";
929 }).join("");
930 var div_shortcuts = document.createElement("div");
931 addClass(div_shortcuts, "shortcuts");
932 div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
933
934 var infos = [
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 -&gt; usize</code> or \
941 <code>* -&gt; 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>",
947 ].map(function(x) {
948 return "<p>" + x + "</p>";
949 }).join("");
950 var div_infos = document.createElement("div");
951 addClass(div_infos, "infos");
952 div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
953
954 container.appendChild(book_info);
955 container.appendChild(div_shortcuts);
956 container.appendChild(div_infos);
957
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);
963
964 container.appendChild(rustdoc_version);
965
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() {};
970 };
971
972 onHashChange(null);
973 window.addEventListener("hashchange", onHashChange);
974 searchState.setup();
975 }());
976
977 (function () {
978 var reset_button_timeout = null;
979
980 window.copy_path = function(but) {
981 var parent = but.parentElement;
982 var path = [];
983
984 onEach(parent.childNodes, function(child) {
985 if (child.tagName === 'A') {
986 path.push(child.textContent);
987 }
988 });
989
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';
996
997 document.body.appendChild(el);
998 el.select();
999 document.execCommand('copy');
1000 document.body.removeChild(el);
1001
1002 // There is always one children, but multiple childNodes.
1003 but.children[0].style.display = 'none';
1004
1005 var tmp;
1006 if (but.childNodes.length < 2) {
1007 tmp = document.createTextNode('✓');
1008 but.appendChild(tmp);
1009 } else {
1010 onEachLazy(but.childNodes, function(e) {
1011 if (e.nodeType === Node.TEXT_NODE) {
1012 tmp = e;
1013 return true;
1014 }
1015 });
1016 tmp.textContent = '✓';
1017 }
1018
1019 if (reset_button_timeout !== null) {
1020 window.clearTimeout(reset_button_timeout);
1021 }
1022
1023 function reset_button() {
1024 tmp.textContent = '';
1025 reset_button_timeout = null;
1026 but.children[0].style.display = "";
1027 }
1028
1029 reset_button_timeout = window.setTimeout(reset_button, 1000);
1030 };
1031 }());