]> git.proxmox.com Git - rustc.git/blob - src/librustdoc/html/static/js/main.js
New upstream version 1.56.0~beta.4+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 (function () {
41 var rustdocVars = document.getElementById("rustdoc-vars");
42 if (rustdocVars) {
43 window.rootPath = rustdocVars.attributes["data-root-path"].value;
44 window.currentCrate = rustdocVars.attributes["data-current-crate"].value;
45 window.searchJS = rustdocVars.attributes["data-search-js"].value;
46 window.searchIndexJS = rustdocVars.attributes["data-search-index-js"].value;
47 }
48 var sidebarVars = document.getElementById("sidebar-vars");
49 if (sidebarVars) {
50 window.sidebarCurrent = {
51 name: sidebarVars.attributes["data-name"].value,
52 ty: sidebarVars.attributes["data-ty"].value,
53 relpath: sidebarVars.attributes["data-relpath"].value,
54 };
55 }
56 }());
57
58 // Gets the human-readable string for the virtual-key code of the
59 // given KeyboardEvent, ev.
60 //
61 // This function is meant as a polyfill for KeyboardEvent#key,
62 // since it is not supported in IE 11 or Chrome for Android. We also test for
63 // KeyboardEvent#keyCode because the handleShortcut handler is
64 // also registered for the keydown event, because Blink doesn't fire
65 // keypress on hitting the Escape key.
66 //
67 // So I guess you could say things are getting pretty interoperable.
68 function getVirtualKey(ev) {
69 if ("key" in ev && typeof ev.key != "undefined") {
70 return ev.key;
71 }
72
73 var c = ev.charCode || ev.keyCode;
74 if (c == 27) {
75 return "Escape";
76 }
77 return String.fromCharCode(c);
78 }
79
80 var THEME_PICKER_ELEMENT_ID = "theme-picker";
81 var THEMES_ELEMENT_ID = "theme-choices";
82
83 function getThemesElement() {
84 return document.getElementById(THEMES_ELEMENT_ID);
85 }
86
87 function getThemePickerElement() {
88 return document.getElementById(THEME_PICKER_ELEMENT_ID);
89 }
90
91 // Returns the current URL without any query parameter or hash.
92 function getNakedUrl() {
93 return window.location.href.split("?")[0].split("#")[0];
94 }
95
96 function showThemeButtonState() {
97 var themePicker = getThemePickerElement();
98 var themeChoices = getThemesElement();
99
100 themeChoices.style.display = "block";
101 themePicker.style.borderBottomRightRadius = "0";
102 themePicker.style.borderBottomLeftRadius = "0";
103 }
104
105 function hideThemeButtonState() {
106 var themePicker = getThemePickerElement();
107 var themeChoices = getThemesElement();
108
109 themeChoices.style.display = "none";
110 themePicker.style.borderBottomRightRadius = "3px";
111 themePicker.style.borderBottomLeftRadius = "3px";
112 }
113
114 // Set up the theme picker list.
115 (function () {
116 var themeChoices = getThemesElement();
117 var themePicker = getThemePickerElement();
118 var availableThemes/* INSERT THEMES HERE */;
119
120 function switchThemeButtonState() {
121 if (themeChoices.style.display === "block") {
122 hideThemeButtonState();
123 } else {
124 showThemeButtonState();
125 }
126 }
127
128 function handleThemeButtonsBlur(e) {
129 var active = document.activeElement;
130 var related = e.relatedTarget;
131
132 if (active.id !== THEME_PICKER_ELEMENT_ID &&
133 (!active.parentNode || active.parentNode.id !== THEMES_ELEMENT_ID) &&
134 (!related ||
135 (related.id !== THEME_PICKER_ELEMENT_ID &&
136 (!related.parentNode || related.parentNode.id !== THEMES_ELEMENT_ID)))) {
137 hideThemeButtonState();
138 }
139 }
140
141 themePicker.onclick = switchThemeButtonState;
142 themePicker.onblur = handleThemeButtonsBlur;
143 availableThemes.forEach(function(item) {
144 var but = document.createElement("button");
145 but.textContent = item;
146 but.onclick = function() {
147 switchTheme(window.currentTheme, window.mainTheme, item, true);
148 useSystemTheme(false);
149 };
150 but.onblur = handleThemeButtonsBlur;
151 themeChoices.appendChild(but);
152 });
153 }());
154
155 (function() {
156 "use strict";
157
158 window.searchState = {
159 loadingText: "Loading search results...",
160 input: document.getElementsByClassName("search-input")[0],
161 outputElement: function() {
162 return document.getElementById("search");
163 },
164 title: document.title,
165 titleBeforeSearch: document.title,
166 timeout: null,
167 // On the search screen, so you remain on the last tab you opened.
168 //
169 // 0 for "In Names"
170 // 1 for "In Parameters"
171 // 2 for "In Return Types"
172 currentTab: 0,
173 // tab and back preserves the element that was focused.
174 focusedByTab: [null, null, null],
175 clearInputTimeout: function() {
176 if (searchState.timeout !== null) {
177 clearTimeout(searchState.timeout);
178 searchState.timeout = null;
179 }
180 },
181 // Sets the focus on the search bar at the top of the page
182 focus: function() {
183 searchState.input.focus();
184 },
185 // Removes the focus from the search bar.
186 defocus: function() {
187 searchState.input.blur();
188 },
189 showResults: function(search) {
190 if (search === null || typeof search === 'undefined') {
191 search = searchState.outputElement();
192 }
193 addClass(main, "hidden");
194 removeClass(search, "hidden");
195 searchState.mouseMovedAfterSearch = false;
196 document.title = searchState.title;
197 },
198 hideResults: function(search) {
199 if (search === null || typeof search === 'undefined') {
200 search = searchState.outputElement();
201 }
202 addClass(search, "hidden");
203 removeClass(main, "hidden");
204 document.title = searchState.titleBeforeSearch;
205 // We also remove the query parameter from the URL.
206 if (searchState.browserSupportsHistoryApi()) {
207 history.replaceState("", window.currentCrate + " - Rust",
208 getNakedUrl() + window.location.hash);
209 }
210 },
211 getQueryStringParams: function() {
212 var params = {};
213 window.location.search.substring(1).split("&").
214 map(function(s) {
215 var pair = s.split("=");
216 params[decodeURIComponent(pair[0])] =
217 typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
218 });
219 return params;
220 },
221 putBackSearch: function(search_input) {
222 var search = searchState.outputElement();
223 if (search_input.value !== "" && hasClass(search, "hidden")) {
224 searchState.showResults(search);
225 if (searchState.browserSupportsHistoryApi()) {
226 var extra = "?search=" + encodeURIComponent(search_input.value);
227 history.replaceState(search_input.value, "",
228 getNakedUrl() + extra + window.location.hash);
229 }
230 document.title = searchState.title;
231 }
232 },
233 browserSupportsHistoryApi: function() {
234 return window.history && typeof window.history.pushState === "function";
235 },
236 setup: function() {
237 var search_input = searchState.input;
238 if (!searchState.input) {
239 return;
240 }
241 function loadScript(url) {
242 var script = document.createElement('script');
243 script.src = url;
244 document.head.append(script);
245 }
246
247 var searchLoaded = false;
248 function loadSearch() {
249 if (!searchLoaded) {
250 searchLoaded = true;
251 loadScript(window.searchJS);
252 loadScript(window.searchIndexJS);
253 }
254 }
255
256 search_input.addEventListener("focus", function() {
257 searchState.putBackSearch(this);
258 search_input.origPlaceholder = searchState.input.placeholder;
259 search_input.placeholder = "Type your search here.";
260 loadSearch();
261 });
262 search_input.addEventListener("blur", function() {
263 search_input.placeholder = searchState.input.origPlaceholder;
264 });
265
266 search_input.removeAttribute('disabled');
267
268 // `crates{version}.js` should always be loaded before this script, so we can use it
269 // safely.
270 searchState.addCrateDropdown(window.ALL_CRATES);
271 var params = searchState.getQueryStringParams();
272 if (params.search !== undefined) {
273 var search = searchState.outputElement();
274 search.innerHTML = "<h3 style=\"text-align: center;\">" +
275 searchState.loadingText + "</h3>";
276 searchState.showResults(search);
277 loadSearch();
278 }
279 },
280 addCrateDropdown: function(crates) {
281 var elem = document.getElementById("crate-search");
282
283 if (!elem) {
284 return;
285 }
286 var savedCrate = getSettingValue("saved-filter-crate");
287 for (var i = 0, len = crates.length; i < len; ++i) {
288 var option = document.createElement("option");
289 option.value = crates[i];
290 option.innerText = crates[i];
291 elem.appendChild(option);
292 // Set the crate filter from saved storage, if the current page has the saved crate
293 // filter.
294 //
295 // If not, ignore the crate filter -- we want to support filtering for crates on
296 // sites like doc.rust-lang.org where the crates may differ from page to page while
297 // on the
298 // same domain.
299 if (crates[i] === savedCrate) {
300 elem.value = savedCrate;
301 }
302 }
303 },
304 };
305
306 function getPageId() {
307 if (window.location.hash) {
308 var tmp = window.location.hash.replace(/^#/, "");
309 if (tmp.length > 0) {
310 return tmp;
311 }
312 }
313 return null;
314 }
315
316 function showSidebar() {
317 var elems = document.getElementsByClassName("sidebar-elems")[0];
318 if (elems) {
319 addClass(elems, "show-it");
320 }
321 var sidebar = document.getElementsByClassName("sidebar")[0];
322 if (sidebar) {
323 addClass(sidebar, "mobile");
324 var filler = document.getElementById("sidebar-filler");
325 if (!filler) {
326 var div = document.createElement("div");
327 div.id = "sidebar-filler";
328 sidebar.appendChild(div);
329 }
330 }
331 }
332
333 function hideSidebar() {
334 var elems = document.getElementsByClassName("sidebar-elems")[0];
335 if (elems) {
336 removeClass(elems, "show-it");
337 }
338 var sidebar = document.getElementsByClassName("sidebar")[0];
339 removeClass(sidebar, "mobile");
340 var filler = document.getElementById("sidebar-filler");
341 if (filler) {
342 filler.remove();
343 }
344 document.getElementsByTagName("body")[0].style.marginTop = "";
345 }
346
347 var toggleAllDocsId = "toggle-all-docs";
348 var main = document.getElementById("main");
349 var savedHash = "";
350
351 function handleHashes(ev) {
352 var elem;
353 var search = searchState.outputElement();
354 if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
355 // This block occurs when clicking on an element in the navbar while
356 // in a search.
357 searchState.hideResults(search);
358 var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
359 if (searchState.browserSupportsHistoryApi()) {
360 // `window.location.search`` contains all the query parameters, not just `search`.
361 history.replaceState(hash, "",
362 getNakedUrl() + window.location.search + "#" + hash);
363 }
364 elem = document.getElementById(hash);
365 if (elem) {
366 elem.scrollIntoView();
367 }
368 }
369 // This part is used in case an element is not visible.
370 if (savedHash !== window.location.hash) {
371 savedHash = window.location.hash;
372 if (savedHash.length === 0) {
373 return;
374 }
375 expandSection(savedHash.slice(1)); // we remove the '#'
376 }
377 }
378
379 function onHashChange(ev) {
380 // If we're in mobile mode, we should hide the sidebar in any case.
381 hideSidebar();
382 handleHashes(ev);
383 }
384
385 function openParentDetails(elem) {
386 while (elem) {
387 if (elem.tagName === "DETAILS") {
388 elem.open = true;
389 }
390 elem = elem.parentNode;
391 }
392 }
393
394 function expandSection(id) {
395 openParentDetails(document.getElementById(id));
396 }
397
398 function getHelpElement(build) {
399 if (build) {
400 buildHelperPopup();
401 }
402 return document.getElementById("help");
403 }
404
405 function displayHelp(display, ev, help) {
406 if (display) {
407 help = help ? help : getHelpElement(true);
408 if (hasClass(help, "hidden")) {
409 ev.preventDefault();
410 removeClass(help, "hidden");
411 addClass(document.body, "blur");
412 }
413 } else {
414 // No need to build the help popup if we want to hide it in case it hasn't been
415 // built yet...
416 help = help ? help : getHelpElement(false);
417 if (help && !hasClass(help, "hidden")) {
418 ev.preventDefault();
419 addClass(help, "hidden");
420 removeClass(document.body, "blur");
421 }
422 }
423 }
424
425 function handleEscape(ev) {
426 var help = getHelpElement(false);
427 var search = searchState.outputElement();
428 if (help && !hasClass(help, "hidden")) {
429 displayHelp(false, ev, help);
430 } else if (search && !hasClass(search, "hidden")) {
431 searchState.clearInputTimeout();
432 ev.preventDefault();
433 searchState.hideResults(search);
434 }
435 searchState.defocus();
436 hideThemeButtonState();
437 }
438
439 var disableShortcuts = getSettingValue("disable-shortcuts") === "true";
440 function handleShortcut(ev) {
441 // Don't interfere with browser shortcuts
442 if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) {
443 return;
444 }
445
446 if (document.activeElement.tagName === "INPUT") {
447 switch (getVirtualKey(ev)) {
448 case "Escape":
449 handleEscape(ev);
450 break;
451 }
452 } else {
453 switch (getVirtualKey(ev)) {
454 case "Escape":
455 handleEscape(ev);
456 break;
457
458 case "s":
459 case "S":
460 displayHelp(false, ev);
461 ev.preventDefault();
462 searchState.focus();
463 break;
464
465 case "+":
466 case "-":
467 ev.preventDefault();
468 toggleAllDocs();
469 break;
470
471 case "?":
472 displayHelp(true, ev);
473 break;
474
475 case "t":
476 case "T":
477 displayHelp(false, ev);
478 ev.preventDefault();
479 var themePicker = getThemePickerElement();
480 themePicker.click();
481 themePicker.focus();
482 break;
483
484 default:
485 if (getThemePickerElement().parentNode.contains(ev.target)) {
486 handleThemeKeyDown(ev);
487 }
488 }
489 }
490 }
491
492 function handleThemeKeyDown(ev) {
493 var active = document.activeElement;
494 var themes = getThemesElement();
495 switch (getVirtualKey(ev)) {
496 case "ArrowUp":
497 ev.preventDefault();
498 if (active.previousElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
499 active.previousElementSibling.focus();
500 } else {
501 showThemeButtonState();
502 themes.lastElementChild.focus();
503 }
504 break;
505 case "ArrowDown":
506 ev.preventDefault();
507 if (active.nextElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
508 active.nextElementSibling.focus();
509 } else {
510 showThemeButtonState();
511 themes.firstElementChild.focus();
512 }
513 break;
514 case "Enter":
515 case "Return":
516 case "Space":
517 if (ev.target.id === THEME_PICKER_ELEMENT_ID && themes.style.display === "none") {
518 ev.preventDefault();
519 showThemeButtonState();
520 themes.firstElementChild.focus();
521 }
522 break;
523 case "Home":
524 ev.preventDefault();
525 themes.firstElementChild.focus();
526 break;
527 case "End":
528 ev.preventDefault();
529 themes.lastElementChild.focus();
530 break;
531 // The escape key is handled in handleEscape, not here,
532 // so that pressing escape will close the menu even if it isn't focused
533 }
534 }
535
536 document.addEventListener("keypress", handleShortcut);
537 document.addEventListener("keydown", handleShortcut);
538
539 (function() {
540 var x = document.getElementsByClassName("version-selector");
541 if (x.length > 0) {
542 x[0].onchange = function() {
543 var i, match,
544 url = document.location.href,
545 stripped = "",
546 len = window.rootPath.match(/\.\.\//g).length + 1;
547
548 for (i = 0; i < len; ++i) {
549 match = url.match(/\/[^/]*$/);
550 if (i < len - 1) {
551 stripped = match[0] + stripped;
552 }
553 url = url.substring(0, url.length - match[0].length);
554 }
555
556 var selectedVersion = document.getElementsByClassName("version-selector")[0].value;
557 url += "/" + selectedVersion + stripped;
558
559 document.location.href = url;
560 };
561 }
562 }());
563
564 // delayed sidebar rendering.
565 window.initSidebarItems = function(items) {
566 var sidebar = document.getElementsByClassName("sidebar-elems")[0];
567 var current = window.sidebarCurrent;
568
569 function addSidebarCrates(crates) {
570 if (!hasClass(document.body, "crate")) {
571 // We only want to list crates on the crate page.
572 return;
573 }
574 // Draw a convenient sidebar of known crates if we have a listing
575 var div = document.createElement("div");
576 div.className = "block crate";
577 div.innerHTML = "<h3>Crates</h3>";
578 var ul = document.createElement("ul");
579 div.appendChild(ul);
580
581 for (var i = 0; i < crates.length; ++i) {
582 var klass = "crate";
583 if (window.rootPath !== "./" && crates[i] === window.currentCrate) {
584 klass += " current";
585 }
586 var link = document.createElement("a");
587 link.href = window.rootPath + crates[i] + "/index.html";
588 link.className = klass;
589 link.textContent = crates[i];
590
591 var li = document.createElement("li");
592 li.appendChild(link);
593 ul.appendChild(li);
594 }
595 sidebar.appendChild(div);
596 }
597
598 function block(shortty, longty) {
599 var filtered = items[shortty];
600 if (!filtered) {
601 return;
602 }
603
604 var div = document.createElement("div");
605 div.className = "block " + shortty;
606 var h3 = document.createElement("h3");
607 h3.textContent = longty;
608 div.appendChild(h3);
609 var ul = document.createElement("ul");
610
611 for (var i = 0, len = filtered.length; i < len; ++i) {
612 var item = filtered[i];
613 var name = item[0];
614 var desc = item[1]; // can be null
615
616 var klass = shortty;
617 if (name === current.name && shortty === current.ty) {
618 klass += " current";
619 }
620 var path;
621 if (shortty === "mod") {
622 path = name + "/index.html";
623 } else {
624 path = shortty + "." + name + ".html";
625 }
626 var link = document.createElement("a");
627 link.href = current.relpath + path;
628 link.title = desc;
629 link.className = klass;
630 link.textContent = name;
631 var li = document.createElement("li");
632 li.appendChild(link);
633 ul.appendChild(li);
634 }
635 div.appendChild(ul);
636 sidebar.appendChild(div);
637 }
638
639 if (sidebar) {
640 var isModule = hasClass(document.body, "mod");
641 if (!isModule) {
642 block("primitive", "Primitive Types");
643 block("mod", "Modules");
644 block("macro", "Macros");
645 block("struct", "Structs");
646 block("enum", "Enums");
647 block("union", "Unions");
648 block("constant", "Constants");
649 block("static", "Statics");
650 block("trait", "Traits");
651 block("fn", "Functions");
652 block("type", "Type Definitions");
653 block("foreigntype", "Foreign Types");
654 block("keyword", "Keywords");
655 block("traitalias", "Trait Aliases");
656 }
657
658 // `crates{version}.js` should always be loaded before this script, so we can use
659 // it safely.
660 addSidebarCrates(window.ALL_CRATES);
661 }
662 };
663
664 window.register_implementors = function(imp) {
665 var implementors = document.getElementById("implementors-list");
666 var synthetic_implementors = document.getElementById("synthetic-implementors-list");
667
668 if (synthetic_implementors) {
669 // This `inlined_types` variable is used to avoid having the same implementation
670 // showing up twice. For example "String" in the "Sync" doc page.
671 //
672 // By the way, this is only used by and useful for traits implemented automatically
673 // (like "Send" and "Sync").
674 var inlined_types = new Set();
675 onEachLazy(synthetic_implementors.getElementsByClassName("impl"), function(el) {
676 var aliases = el.getAttribute("data-aliases");
677 if (!aliases) {
678 return;
679 }
680 aliases.split(",").forEach(function(alias) {
681 inlined_types.add(alias);
682 });
683 });
684 }
685
686 var currentNbImpls = implementors.getElementsByClassName("impl").length;
687 var traitName = document.querySelector("h1.fqn > .in-band > .trait").textContent;
688 var baseIdName = "impl-" + traitName + "-";
689 var libs = Object.getOwnPropertyNames(imp);
690 for (var i = 0, llength = libs.length; i < llength; ++i) {
691 if (libs[i] === window.currentCrate) { continue; }
692 var structs = imp[libs[i]];
693
694 struct_loop:
695 for (var j = 0, slength = structs.length; j < slength; ++j) {
696 var struct = structs[j];
697
698 var list = struct.synthetic ? synthetic_implementors : implementors;
699
700 if (struct.synthetic) {
701 for (var k = 0, stlength = struct.types.length; k < stlength; k++) {
702 if (inlined_types.has(struct.types[k])) {
703 continue struct_loop;
704 }
705 inlined_types.add(struct.types[k]);
706 }
707 }
708
709 var code = document.createElement("h3");
710 code.innerHTML = struct.text;
711 addClass(code, "code-header");
712 addClass(code, "in-band");
713
714 onEachLazy(code.getElementsByTagName("a"), function(elem) {
715 var href = elem.getAttribute("href");
716
717 if (href && href.indexOf("http") !== 0) {
718 elem.setAttribute("href", window.rootPath + href);
719 }
720 });
721
722 var currentId = baseIdName + currentNbImpls;
723 var anchor = document.createElement("a");
724 anchor.href = "#" + currentId;
725 addClass(anchor, "anchor");
726
727 var display = document.createElement("div");
728 display.id = currentId;
729 addClass(display, "impl");
730 display.appendChild(anchor);
731 display.appendChild(code);
732 list.appendChild(display);
733 currentNbImpls += 1;
734 }
735 }
736 };
737 if (window.pending_implementors) {
738 window.register_implementors(window.pending_implementors);
739 }
740
741 function labelForToggleButton(sectionIsCollapsed) {
742 if (sectionIsCollapsed) {
743 // button will expand the section
744 return "+";
745 }
746 // button will collapse the section
747 // note that this text is also set in the HTML template in ../render/mod.rs
748 return "\u2212"; // "\u2212" is "−" minus sign
749 }
750
751 function toggleAllDocs() {
752 var innerToggle = document.getElementById(toggleAllDocsId);
753 if (!innerToggle) {
754 return;
755 }
756 var sectionIsCollapsed = false;
757 if (hasClass(innerToggle, "will-expand")) {
758 removeClass(innerToggle, "will-expand");
759 onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
760 if (!hasClass(e, "type-contents-toggle")) {
761 e.open = true;
762 }
763 });
764 innerToggle.title = "collapse all docs";
765 } else {
766 addClass(innerToggle, "will-expand");
767 onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
768 if (e.parentNode.id !== "main" ||
769 (!hasClass(e, "implementors-toggle") &&
770 !hasClass(e, "type-contents-toggle")))
771 {
772 e.open = false;
773 }
774 });
775 sectionIsCollapsed = true;
776 innerToggle.title = "expand all docs";
777 }
778 innerToggle.children[0].innerText = labelForToggleButton(sectionIsCollapsed);
779 }
780
781 function insertAfter(newNode, referenceNode) {
782 referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
783 }
784
785 (function() {
786 var toggles = document.getElementById(toggleAllDocsId);
787 if (toggles) {
788 toggles.onclick = toggleAllDocs;
789 }
790
791 var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
792 var hideImplementations = getSettingValue("auto-hide-trait-implementations") === "true";
793 var hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
794
795 function setImplementorsTogglesOpen(id, open) {
796 var list = document.getElementById(id);
797 if (list !== null) {
798 onEachLazy(list.getElementsByClassName("implementors-toggle"), function(e) {
799 e.open = open;
800 });
801 }
802 }
803
804 if (hideImplementations) {
805 setImplementorsTogglesOpen("trait-implementations-list", false);
806 setImplementorsTogglesOpen("blanket-implementations-list", false);
807 }
808
809 onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function (e) {
810 if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) {
811 e.open = true;
812 }
813 if (hideMethodDocs && hasClass(e, "method-toggle")) {
814 e.open = false;
815 }
816
817 });
818
819 var pageId = getPageId();
820 if (pageId !== null) {
821 expandSection(pageId);
822 }
823 }());
824
825 (function() {
826 // To avoid checking on "rustdoc-line-numbers" value on every loop...
827 var lineNumbersFunc = function() {};
828 if (getSettingValue("line-numbers") === "true") {
829 lineNumbersFunc = function(x) {
830 var count = x.textContent.split("\n").length;
831 var elems = [];
832 for (var i = 0; i < count; ++i) {
833 elems.push(i + 1);
834 }
835 var node = document.createElement("pre");
836 addClass(node, "line-number");
837 node.innerHTML = elems.join("\n");
838 x.parentNode.insertBefore(node, x);
839 };
840 }
841 onEachLazy(document.getElementsByClassName("rust-example-rendered"), function(e) {
842 if (hasClass(e, "compile_fail")) {
843 e.addEventListener("mouseover", function() {
844 this.parentElement.previousElementSibling.childNodes[0].style.color = "#f00";
845 });
846 e.addEventListener("mouseout", function() {
847 this.parentElement.previousElementSibling.childNodes[0].style.color = "";
848 });
849 } else if (hasClass(e, "ignore")) {
850 e.addEventListener("mouseover", function() {
851 this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200";
852 });
853 e.addEventListener("mouseout", function() {
854 this.parentElement.previousElementSibling.childNodes[0].style.color = "";
855 });
856 }
857 lineNumbersFunc(e);
858 });
859 }());
860
861 function handleClick(id, f) {
862 var elem = document.getElementById(id);
863 if (elem) {
864 elem.addEventListener("click", f);
865 }
866 }
867 handleClick("help-button", function(ev) {
868 displayHelp(true, ev);
869 });
870
871 onEachLazy(document.getElementsByTagName("a"), function(el) {
872 // For clicks on internal links (<A> tags with a hash property), we expand the section we're
873 // jumping to *before* jumping there. We can't do this in onHashChange, because it changes
874 // the height of the document so we wind up scrolled to the wrong place.
875 if (el.hash) {
876 el.addEventListener("click", function() {
877 expandSection(el.hash.slice(1));
878 });
879 }
880 });
881
882 onEachLazy(document.getElementsByClassName("notable-traits"), function(e) {
883 e.onclick = function() {
884 this.getElementsByClassName('notable-traits-tooltiptext')[0]
885 .classList.toggle("force-tooltip");
886 };
887 });
888
889 var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
890 if (sidebar_menu) {
891 sidebar_menu.onclick = function() {
892 var sidebar = document.getElementsByClassName("sidebar")[0];
893 if (hasClass(sidebar, "mobile")) {
894 hideSidebar();
895 } else {
896 showSidebar();
897 }
898 };
899 }
900
901 var buildHelperPopup = function() {
902 var popup = document.createElement("aside");
903 addClass(popup, "hidden");
904 popup.id = "help";
905
906 popup.addEventListener("click", function(ev) {
907 if (ev.target === popup) {
908 // Clicked the blurred zone outside the help popup; dismiss help.
909 displayHelp(false, ev);
910 }
911 });
912
913 var book_info = document.createElement("span");
914 book_info.innerHTML = "You can find more information in \
915 <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
916
917 var container = document.createElement("div");
918 var shortcuts = [
919 ["?", "Show this help dialog"],
920 ["S", "Focus the search field"],
921 ["T", "Focus the theme picker menu"],
922 ["↑", "Move up in search results"],
923 ["↓", "Move down in search results"],
924 ["← / →", "Switch result tab (when results focused)"],
925 ["&#9166;", "Go to active search result"],
926 ["+", "Expand all sections"],
927 ["-", "Collapse all sections"],
928 ].map(function(x) {
929 return "<dt>" +
930 x[0].split(" ")
931 .map(function(y, index) {
932 return (index & 1) === 0 ? "<kbd>" + y + "</kbd>" : " " + y + " ";
933 })
934 .join("") + "</dt><dd>" + x[1] + "</dd>";
935 }).join("");
936 var div_shortcuts = document.createElement("div");
937 addClass(div_shortcuts, "shortcuts");
938 div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
939
940 var infos = [
941 "Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
942 restrict the search to a given item kind.",
943 "Accepted kinds are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
944 <code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, \
945 and <code>const</code>.",
946 "Search functions by type signature (e.g., <code>vec -&gt; usize</code> or \
947 <code>* -&gt; vec</code>)",
948 "Search multiple things at once by splitting your query with comma (e.g., \
949 <code>str,u8</code> or <code>String,struct:Vec,test</code>)",
950 "You can look for items with an exact name by putting double quotes around \
951 your request: <code>\"string\"</code>",
952 "Look for items inside another one by searching for a path: <code>vec::Vec</code>",
953 ].map(function(x) {
954 return "<p>" + x + "</p>";
955 }).join("");
956 var div_infos = document.createElement("div");
957 addClass(div_infos, "infos");
958 div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
959
960 container.appendChild(book_info);
961 container.appendChild(div_shortcuts);
962 container.appendChild(div_infos);
963
964 popup.appendChild(container);
965 insertAfter(popup, searchState.outputElement());
966 // So that it's only built once and then it'll do nothing when called!
967 buildHelperPopup = function() {};
968 };
969
970 onHashChange(null);
971 window.addEventListener("hashchange", onHashChange);
972 searchState.setup();
973 }());
974
975 (function () {
976 var reset_button_timeout = null;
977
978 window.copy_path = function(but) {
979 var parent = but.parentElement;
980 var path = [];
981
982 onEach(parent.childNodes, function(child) {
983 if (child.tagName === 'A') {
984 path.push(child.textContent);
985 }
986 });
987
988 var el = document.createElement('textarea');
989 el.value = path.join('::');
990 el.setAttribute('readonly', '');
991 // To not make it appear on the screen.
992 el.style.position = 'absolute';
993 el.style.left = '-9999px';
994
995 document.body.appendChild(el);
996 el.select();
997 document.execCommand('copy');
998 document.body.removeChild(el);
999
1000 // There is always one children, but multiple childNodes.
1001 but.children[0].style.display = 'none';
1002
1003 var tmp;
1004 if (but.childNodes.length < 2) {
1005 tmp = document.createTextNode('✓');
1006 but.appendChild(tmp);
1007 } else {
1008 onEachLazy(but.childNodes, function(e) {
1009 if (e.nodeType === Node.TEXT_NODE) {
1010 tmp = e;
1011 return true;
1012 }
1013 });
1014 tmp.textContent = '✓';
1015 }
1016
1017 if (reset_button_timeout !== null) {
1018 window.clearTimeout(reset_button_timeout);
1019 }
1020
1021 function reset_button() {
1022 tmp.textContent = '';
1023 reset_button_timeout = null;
1024 but.children[0].style.display = "";
1025 }
1026
1027 reset_button_timeout = window.setTimeout(reset_button, 1000);
1028 };
1029 }());