]> git.proxmox.com Git - rustc.git/blame - src/librustdoc/html/static/main.js
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustdoc / html / static / main.js
CommitLineData
0731742a
XL
1// From rust:
2/* global ALIASES, currentCrate, rootPath */
3
4// Local js definitions:
5/* global addClass, getCurrentValue, hasClass */
60c5eb7d 6/* global onEach, removeClass, updateLocalStorage */
1a4d82fc 7
a1dfa0c6
XL
8if (!String.prototype.startsWith) {
9 String.prototype.startsWith = function(searchString, position) {
10 position = position || 0;
11 return this.indexOf(searchString, position) === position;
12 };
13}
14if (!String.prototype.endsWith) {
15 String.prototype.endsWith = function(suffix, length) {
16 var l = length || this.length;
17 return this.indexOf(suffix, l - suffix.length) !== -1;
18 };
19}
20
0731742a
XL
21if (!DOMTokenList.prototype.add) {
22 DOMTokenList.prototype.add = function(className) {
23 if (className && !hasClass(this, className)) {
24 if (this.className && this.className.length > 0) {
25 this.className += " " + className;
26 } else {
27 this.className = className;
28 }
29 }
30 };
31}
32
33if (!DOMTokenList.prototype.remove) {
34 DOMTokenList.prototype.remove = function(className) {
35 if (className && this.className) {
36 this.className = (" " + this.className + " ").replace(" " + className + " ", " ")
37 .trim();
38 }
39 };
40}
41
e1599b0c
XL
42function getSearchInput() {
43 return document.getElementsByClassName("search-input")[0];
44}
45
46function getSearchElement() {
47 return document.getElementById("search");
48}
49
1a4d82fc
JJ
50(function() {
51 "use strict";
1a4d82fc 52
c34b1796
AL
53 // This mapping table should match the discriminants of
54 // `rustdoc::html::item_type::ItemType` type in Rust.
55 var itemTypes = ["mod",
56 "externcrate",
57 "import",
58 "struct",
59 "enum",
60 "fn",
61 "type",
62 "static",
63 "trait",
64 "impl",
65 "tymethod",
66 "method",
67 "structfield",
68 "variant",
69 "macro",
70 "primitive",
71 "associatedtype",
d9579d0f 72 "constant",
9e0c209e 73 "associatedconstant",
abe05a73 74 "union",
94b46f34 75 "foreigntype",
0bf4aa26
XL
76 "keyword",
77 "existential",
78 "attr",
9fa01778
XL
79 "derive",
80 "traitalias"];
abe05a73 81
e74abb32 82 var disableShortcuts = getCurrentValue("rustdoc-disable-shortcuts") === "true";
e1599b0c 83 var search_input = getSearchInput();
83c7162d 84
abe05a73
XL
85 // On the search screen, so you remain on the last tab you opened.
86 //
ff7c6d11
XL
87 // 0 for "In Names"
88 // 1 for "In Parameters"
89 // 2 for "In Return Types"
abe05a73 90 var currentTab = 0;
c34b1796 91
b7449926
XL
92 var titleBeforeSearch = document.title;
93
83c7162d 94 function getPageId() {
0731742a 95 var id = document.location.href.split("#")[1];
83c7162d 96 if (id) {
0731742a 97 return id.split("?")[0].split("&")[0];
83c7162d
XL
98 }
99 return null;
100 }
101
ff7c6d11
XL
102 function showSidebar() {
103 var elems = document.getElementsByClassName("sidebar-elems")[0];
104 if (elems) {
105 addClass(elems, "show-it");
106 }
0731742a 107 var sidebar = document.getElementsByClassName("sidebar")[0];
ff7c6d11 108 if (sidebar) {
0731742a 109 addClass(sidebar, "mobile");
ff7c6d11
XL
110 var filler = document.getElementById("sidebar-filler");
111 if (!filler) {
112 var div = document.createElement("div");
113 div.id = "sidebar-filler";
114 sidebar.appendChild(div);
115 }
116 }
e1599b0c
XL
117 var themePickers = document.getElementsByClassName("theme-picker");
118 if (themePickers && themePickers.length > 0) {
119 themePickers[0].style.display = "none";
2c00a5a8 120 }
ff7c6d11
XL
121 }
122
123 function hideSidebar() {
124 var elems = document.getElementsByClassName("sidebar-elems")[0];
125 if (elems) {
126 removeClass(elems, "show-it");
127 }
0731742a
XL
128 var sidebar = document.getElementsByClassName("sidebar")[0];
129 removeClass(sidebar, "mobile");
ff7c6d11
XL
130 var filler = document.getElementById("sidebar-filler");
131 if (filler) {
132 filler.remove();
133 }
0731742a 134 document.getElementsByTagName("body")[0].style.marginTop = "";
e1599b0c
XL
135 var themePickers = document.getElementsByClassName("theme-picker");
136 if (themePickers && themePickers.length > 0) {
137 themePickers[0].style.display = null;
2c00a5a8 138 }
ff7c6d11
XL
139 }
140
62682a34
SL
141 // used for special search precedence
142 var TY_PRIMITIVE = itemTypes.indexOf("primitive");
94b46f34 143 var TY_KEYWORD = itemTypes.indexOf("keyword");
62682a34 144
1a4d82fc
JJ
145 function getQueryStringParams() {
146 var params = {};
147 window.location.search.substring(1).split("&").
148 map(function(s) {
149 var pair = s.split("=");
150 params[decodeURIComponent(pair[0])] =
ff7c6d11 151 typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
1a4d82fc
JJ
152 });
153 return params;
154 }
155
156 function browserSupportsHistoryApi() {
9fa01778 157 return window.history && typeof window.history.pushState === "function";
1a4d82fc
JJ
158 }
159
60c5eb7d
XL
160 function isHidden(elem) {
161 return elem.offsetHeight === 0;
162 }
163
0731742a 164 var main = document.getElementById("main");
60c5eb7d 165 var savedHash = "";
0731742a 166
60c5eb7d 167 function handleHashes(ev) {
e1599b0c 168 var search = getSearchElement();
60c5eb7d
XL
169 if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
170 // This block occurs when clicking on an element in the navbar while
171 // in a search.
172 addClass(search, "hidden");
173 removeClass(main, "hidden");
174 var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
175 if (browserSupportsHistoryApi()) {
176 history.replaceState(hash, "", "?search=#" + hash);
dc9dc135 177 }
60c5eb7d
XL
178 var elem = document.getElementById(hash);
179 if (elem) {
180 elem.scrollIntoView();
dc9dc135 181 }
60c5eb7d
XL
182 }
183 // This part is used in case an element is not visible.
184 if (savedHash !== window.location.hash) {
185 savedHash = window.location.hash;
186 if (savedHash.length === 0) {
1a4d82fc
JJ
187 return;
188 }
60c5eb7d
XL
189 var elem = document.getElementById(savedHash.slice(1)); // we remove the '#'
190 if (!elem || !isHidden(elem)) {
191 return;
abe05a73 192 }
60c5eb7d
XL
193 var parent = elem.parentNode;
194 if (parent && hasClass(parent, "impl-items")) {
195 // In case this is a trait implementation item, we first need to toggle
196 // the "Show hidden undocumented items".
197 onEachLazy(parent.getElementsByClassName("collapsed"), function(e) {
198 if (e.parentNode === parent) {
199 // Only click on the toggle we're looking for.
200 e.click();
201 return true;
202 }
7cac9316 203 });
60c5eb7d
XL
204 if (isHidden(elem)) {
205 // The whole parent is collapsed. We need to click on its toggle as well!
206 if (hasClass(parent.lastElementChild, "collapse-toggle")) {
207 parent.lastElementChild.click();
208 }
dc9dc135 209 }
1a4d82fc 210 }
60c5eb7d
XL
211 }
212 }
213
214 function highlightSourceLines(match, ev) {
215 if (typeof match === "undefined") {
216 // If we're in mobile mode, we should hide the sidebar in any case.
217 hideSidebar();
218 match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
219 }
220 if (!match) {
221 return;
222 }
223 var from = parseInt(match[1], 10);
224 var to = from;
225 if (typeof match[2] !== "undefined") {
226 to = parseInt(match[2], 10);
227 }
228 if (to < from) {
229 var tmp = to;
230 to = from;
231 from = tmp;
232 }
233 var elem = document.getElementById(from);
234 if (!elem) {
235 return;
236 }
237 if (!ev) {
238 var x = document.getElementById(from);
239 if (x) {
240 x.scrollIntoView();
abe05a73 241 }
60c5eb7d
XL
242 }
243 onEachLazy(document.getElementsByClassName("line-numbers"), function(e) {
244 onEachLazy(e.getElementsByTagName("span"), function(i_e) {
245 removeClass(i_e, "line-highlighted");
246 });
247 });
248 for (var i = from; i <= to; ++i) {
249 elem = document.getElementById(i);
250 if (!elem) {
251 break;
abe05a73 252 }
60c5eb7d
XL
253 addClass(elem, "line-highlighted");
254 }
255 }
256
257 function onHashChange(ev) {
258 // If we're in mobile mode, we should hide the sidebar in any case.
259 hideSidebar();
260 var match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
261 if (match) {
262 return highlightSourceLines(match, ev);
1a4d82fc 263 }
60c5eb7d 264 handleHashes(ev);
1a4d82fc 265 }
b7449926
XL
266
267 function expandSection(id) {
268 var elem = document.getElementById(id);
269 if (elem && isHidden(elem)) {
0731742a
XL
270 var h3 = elem.parentNode.previousElementSibling;
271 if (h3 && h3.tagName !== "H3") {
272 h3 = h3.previousElementSibling; // skip div.docblock
b7449926
XL
273 }
274
275 if (h3) {
276 var collapses = h3.getElementsByClassName("collapse-toggle");
277 if (collapses.length > 0) {
278 // The element is not visible, we need to make it appear!
279 collapseDocs(collapses[0], "show");
280 }
281 }
282 }
283 }
284
c1a9b12d
SL
285 // Gets the human-readable string for the virtual-key code of the
286 // given KeyboardEvent, ev.
287 //
288 // This function is meant as a polyfill for KeyboardEvent#key,
289 // since it is not supported in Trident. We also test for
290 // KeyboardEvent#keyCode because the handleShortcut handler is
291 // also registered for the keydown event, because Blink doesn't fire
292 // keypress on hitting the Escape key.
293 //
294 // So I guess you could say things are getting pretty interoperable.
295 function getVirtualKey(ev) {
0731742a 296 if ("key" in ev && typeof ev.key != "undefined") {
c1a9b12d 297 return ev.key;
0731742a 298 }
c1a9b12d
SL
299
300 var c = ev.charCode || ev.keyCode;
0731742a 301 if (c == 27) {
c1a9b12d 302 return "Escape";
0731742a 303 }
c1a9b12d
SL
304 return String.fromCharCode(c);
305 }
306
e1599b0c
XL
307 function getHelpElement() {
308 return document.getElementById("help");
309 }
310
9fa01778 311 function displayHelp(display, ev, help) {
e1599b0c 312 var help = help ? help : getHelpElement();
abe05a73
XL
313 if (display === true) {
314 if (hasClass(help, "hidden")) {
315 ev.preventDefault();
316 removeClass(help, "hidden");
317 addClass(document.body, "blur");
318 }
0731742a 319 } else if (hasClass(help, "hidden") === false) {
abe05a73
XL
320 ev.preventDefault();
321 addClass(help, "hidden");
322 removeClass(document.body, "blur");
323 }
324 }
325
e1599b0c
XL
326 function handleEscape(ev) {
327 var help = getHelpElement();
328 var search = getSearchElement();
0531ce1d 329 hideModal();
0731742a 330 if (hasClass(help, "hidden") === false) {
9fa01778 331 displayHelp(false, ev, help);
0731742a 332 } else if (hasClass(search, "hidden") === false) {
0531ce1d
XL
333 ev.preventDefault();
334 addClass(search, "hidden");
0731742a 335 removeClass(main, "hidden");
b7449926 336 document.title = titleBeforeSearch;
0531ce1d
XL
337 }
338 defocusSearchBar();
339 }
1a4d82fc 340
0531ce1d 341 function handleShortcut(ev) {
92a42be0 342 // Don't interfere with browser shortcuts
e74abb32 343 if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts === true) {
92a42be0 344 return;
0531ce1d 345 }
92a42be0 346
0531ce1d
XL
347 if (document.activeElement.tagName === "INPUT") {
348 switch (getVirtualKey(ev)) {
349 case "Escape":
e1599b0c 350 handleEscape(ev);
0531ce1d 351 break;
9346a6ac 352 }
0531ce1d
XL
353 } else {
354 switch (getVirtualKey(ev)) {
355 case "Escape":
e1599b0c 356 handleEscape(ev);
0531ce1d 357 break;
c1a9b12d 358
0531ce1d
XL
359 case "s":
360 case "S":
e1599b0c 361 displayHelp(false, ev);
0531ce1d
XL
362 hideModal();
363 ev.preventDefault();
364 focusSearchBar();
365 break;
c1a9b12d 366
0531ce1d
XL
367 case "+":
368 case "-":
369 ev.preventDefault();
370 toggleAllDocs();
371 break;
a7813a04 372
0531ce1d
XL
373 case "?":
374 if (ev.shiftKey) {
375 hideModal();
e1599b0c 376 displayHelp(true, ev);
0531ce1d
XL
377 }
378 break;
1a4d82fc 379 }
1a4d82fc 380 }
c1a9b12d
SL
381 }
382
b7449926
XL
383 function findParentElement(elem, tagName) {
384 do {
385 if (elem && elem.tagName === tagName) {
386 return elem;
387 }
0731742a
XL
388 elem = elem.parentNode;
389 } while (elem);
b7449926
XL
390 return null;
391 }
392
7cac9316
XL
393 document.onkeypress = handleShortcut;
394 document.onkeydown = handleShortcut;
7cac9316 395
60c5eb7d
XL
396 var handleSourceHighlight = (function() {
397 var prev_line_id = 0;
398
399 var set_fragment = function(name) {
400 var x = window.scrollX,
401 y = window.scrollY;
402 if (browserSupportsHistoryApi()) {
403 history.replaceState(null, null, "#" + name);
404 highlightSourceLines();
405 } else {
406 location.replace("#" + name);
407 }
408 // Prevent jumps when selecting one or many lines
409 window.scrollTo(x, y);
410 };
7cac9316 411
60c5eb7d
XL
412 return function(ev) {
413 var cur_line_id = parseInt(ev.target.id, 10);
414 ev.preventDefault();
7cac9316 415
60c5eb7d
XL
416 if (ev.shiftKey && prev_line_id) {
417 // Swap selection if needed
418 if (prev_line_id > cur_line_id) {
419 var tmp = prev_line_id;
420 prev_line_id = cur_line_id;
421 cur_line_id = tmp;
7cac9316 422 }
1a4d82fc 423
60c5eb7d 424 set_fragment(prev_line_id + "-" + cur_line_id);
7cac9316 425 } else {
60c5eb7d 426 prev_line_id = cur_line_id;
1a4d82fc 427
60c5eb7d 428 set_fragment(cur_line_id);
1a4d82fc 429 }
60c5eb7d
XL
430 }
431 })();
432
433 document.onclick = function(ev) {
434 if (hasClass(ev.target, "collapse-toggle")) {
435 collapseDocs(ev.target, "toggle");
436 } else if (hasClass(ev.target.parentNode, "collapse-toggle")) {
437 collapseDocs(ev.target.parentNode, "toggle");
438 } else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) {
439 handleSourceHighlight(ev);
e74abb32
XL
440 } else if (hasClass(getHelpElement(), "hidden") === false) {
441 var help = getHelpElement();
442 var is_inside_help_popup = ev.target !== help && help.contains(ev.target);
443 if (is_inside_help_popup === false) {
444 addClass(help, "hidden");
445 removeClass(document.body, "blur");
446 }
b7449926
XL
447 } else {
448 // Making a collapsed element visible on onhashchange seems
449 // too late
0731742a 450 var a = findParentElement(ev.target, "A");
b7449926 451 if (a && a.hash) {
0731742a 452 expandSection(a.hash.replace(/^#/, ""));
b7449926 453 }
1a4d82fc 454 }
7cac9316 455 };
1a4d82fc 456
0731742a 457 var x = document.getElementsByClassName("version-selector");
7cac9316
XL
458 if (x.length > 0) {
459 x[0].onchange = function() {
460 var i, match,
461 url = document.location.href,
0731742a 462 stripped = "",
7cac9316 463 len = rootPath.match(/\.\.\//g).length + 1;
1a4d82fc 464
7cac9316
XL
465 for (i = 0; i < len; ++i) {
466 match = url.match(/\/[^\/]*$/);
467 if (i < len - 1) {
468 stripped = match[0] + stripped;
469 }
470 url = url.substring(0, url.length - match[0].length);
471 }
472
0731742a 473 url += "/" + document.getElementsByClassName("version-selector")[0].value + stripped;
7cac9316
XL
474
475 document.location.href = url;
476 };
477 }
c1a9b12d 478
1a4d82fc
JJ
479 /**
480 * A function to compute the Levenshtein distance between two strings
481 * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
482 * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode
483 * This code is an unmodified version of the code written by Marco de Wit
484 * and was found at http://stackoverflow.com/a/18514751/745719
485 */
2c00a5a8
XL
486 var levenshtein_row2 = [];
487 function levenshtein(s1, s2) {
488 if (s1 === s2) {
489 return 0;
490 }
491 var s1_len = s1.length, s2_len = s2.length;
492 if (s1_len && s2_len) {
493 var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2;
494 while (i1 < s1_len) {
495 row[i1] = ++i1;
62682a34 496 }
2c00a5a8
XL
497 while (i2 < s2_len) {
498 c2 = s2.charCodeAt(i2);
499 a = i2;
500 ++i2;
501 b = i2;
502 for (i1 = 0; i1 < s1_len; ++i1) {
503 c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
504 a = row[i1];
505 b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
506 row[i1] = b;
1a4d82fc
JJ
507 }
508 }
2c00a5a8
XL
509 return b;
510 }
511 return s1_len + s2_len;
512 }
1a4d82fc
JJ
513
514 function initSearch(rawSearchIndex) {
515 var currentResults, index, searchIndex;
516 var MAX_LEV_DISTANCE = 3;
abe05a73 517 var MAX_RESULTS = 200;
8faf50e0
XL
518 var GENERICS_DATA = 1;
519 var NAME = 0;
520 var INPUTS_DATA = 0;
521 var OUTPUT_DATA = 1;
1a4d82fc
JJ
522 var params = getQueryStringParams();
523
524 // Populate search bar with query string search term when provided,
525 // but only if the input bar is empty. This avoid the obnoxious issue
526 // where you start trying to do a search, and the index loads, and
527 // suddenly your search is gone!
83c7162d 528 if (search_input.value === "") {
0731742a 529 search_input.value = params.search || "";
1a4d82fc
JJ
530 }
531
532 /**
533 * Executes the query and builds an index of results
0731742a
XL
534 * @param {[Object]} query [The user query]
535 * @param {[type]} searchWords [The list of search words to query
536 * against]
537 * @param {[type]} filterCrates [Crate to search in if defined]
538 * @return {[type]} [A search index of results]
1a4d82fc 539 */
0731742a 540 function execQuery(query, searchWords, filterCrates) {
2c00a5a8 541 function itemTypeFromName(typename) {
0731742a
XL
542 var length = itemTypes.length;
543 for (var i = 0; i < length; ++i) {
2c00a5a8
XL
544 if (itemTypes[i] === typename) {
545 return i;
546 }
547 }
548 return -1;
549 }
550
1a4d82fc
JJ
551 var valLower = query.query.toLowerCase(),
552 val = valLower,
553 typeFilter = itemTypeFromName(query.type),
abe05a73 554 results = {}, results_in_args = {}, results_returned = {},
1a4d82fc
JJ
555 split = valLower.split("::");
556
0731742a
XL
557 var length = split.length;
558 for (var z = 0; z < length; ++z) {
abe05a73
XL
559 if (split[z] === "") {
560 split.splice(z, 1);
561 z -= 1;
562 }
563 }
564
565 function transformResults(results, isType) {
566 var out = [];
0731742a
XL
567 var length = results.length;
568 for (var i = 0; i < length; ++i) {
abe05a73
XL
569 if (results[i].id > -1) {
570 var obj = searchIndex[results[i].id];
571 obj.lev = results[i].lev;
572 if (isType !== true || obj.type) {
94b46f34
XL
573 var res = buildHrefAndPath(obj);
574 obj.displayPath = pathSplitter(res[0]);
575 obj.fullPath = obj.displayPath + obj.name;
576 // To be sure than it some items aren't considered as duplicate.
0731742a 577 obj.fullPath += "|" + obj.ty;
94b46f34 578 obj.href = res[1];
abe05a73 579 out.push(obj);
94b46f34
XL
580 if (out.length >= MAX_RESULTS) {
581 break;
582 }
abe05a73
XL
583 }
584 }
abe05a73
XL
585 }
586 return out;
587 }
588
589 function sortResults(results, isType) {
590 var ar = [];
591 for (var entry in results) {
592 if (results.hasOwnProperty(entry)) {
593 ar.push(results[entry]);
594 }
595 }
596 results = ar;
0731742a 597 var i;
abe05a73 598 var nresults = results.length;
0731742a 599 for (i = 0; i < nresults; ++i) {
abe05a73
XL
600 results[i].word = searchWords[results[i].id];
601 results[i].item = searchIndex[results[i].id] || {};
602 }
603 // if there are no results then return to default and fail
604 if (results.length === 0) {
605 return [];
606 }
607
608 results.sort(function(aaa, bbb) {
609 var a, b;
610
e1599b0c
XL
611 // sort by exact match with regard to the last word (mismatch goes later)
612 a = (aaa.word !== val);
613 b = (bbb.word !== val);
614 if (a !== b) { return a - b; }
615
abe05a73
XL
616 // Sort by non levenshtein results and then levenshtein results by the distance
617 // (less changes required to match means higher rankings)
618 a = (aaa.lev);
619 b = (bbb.lev);
620 if (a !== b) { return a - b; }
621
622 // sort by crate (non-current crate goes later)
623 a = (aaa.item.crate !== window.currentCrate);
624 b = (bbb.item.crate !== window.currentCrate);
625 if (a !== b) { return a - b; }
626
abe05a73
XL
627 // sort by item name length (longer goes later)
628 a = aaa.word.length;
629 b = bbb.word.length;
630 if (a !== b) { return a - b; }
631
632 // sort by item name (lexicographically larger goes later)
633 a = aaa.word;
634 b = bbb.word;
635 if (a !== b) { return (a > b ? +1 : -1); }
636
637 // sort by index of keyword in item name (no literal occurrence goes later)
638 a = (aaa.index < 0);
639 b = (bbb.index < 0);
640 if (a !== b) { return a - b; }
641 // (later literal occurrence, if any, goes later)
642 a = aaa.index;
643 b = bbb.index;
644 if (a !== b) { return a - b; }
645
94b46f34
XL
646 // special precedence for primitive and keyword pages
647 if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
648 (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
abe05a73
XL
649 return -1;
650 }
94b46f34
XL
651 if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
652 (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
abe05a73
XL
653 return 1;
654 }
655
656 // sort by description (no description goes later)
0731742a
XL
657 a = (aaa.item.desc === "");
658 b = (bbb.item.desc === "");
abe05a73
XL
659 if (a !== b) { return a - b; }
660
661 // sort by type (later occurrence in `itemTypes` goes later)
662 a = aaa.item.ty;
663 b = bbb.item.ty;
664 if (a !== b) { return a - b; }
665
666 // sort by path (lexicographically larger goes later)
667 a = aaa.item.path;
668 b = bbb.item.path;
669 if (a !== b) { return (a > b ? +1 : -1); }
670
671 // que sera, sera
672 return 0;
673 });
674
0731742a
XL
675 var length = results.length;
676 for (i = 0; i < length; ++i) {
abe05a73
XL
677 var result = results[i];
678
679 // this validation does not make sense when searching by types
680 if (result.dontValidate) {
681 continue;
682 }
683 var name = result.item.name.toLowerCase(),
684 path = result.item.path.toLowerCase(),
685 parent = result.item.parent;
686
687 if (isType !== true &&
688 validateResult(name, path, split, parent) === false)
689 {
690 result.id = -1;
691 }
692 }
693 return transformResults(results);
694 }
695
696 function extractGenerics(val) {
697 val = val.toLowerCase();
0731742a
XL
698 if (val.indexOf("<") !== -1) {
699 var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
abe05a73 700 return {
0731742a 701 name: val.substring(0, val.indexOf("<")),
abe05a73
XL
702 generics: values.split(/\s*,\s*/),
703 };
704 }
705 return {
706 name: val,
707 generics: [],
708 };
709 }
710
711 function checkGenerics(obj, val) {
712 // The names match, but we need to be sure that all generics kinda
713 // match as well.
714 var lev_distance = MAX_LEV_DISTANCE + 1;
715 if (val.generics.length > 0) {
8faf50e0
XL
716 if (obj.length > GENERICS_DATA &&
717 obj[GENERICS_DATA].length >= val.generics.length) {
718 var elems = obj[GENERICS_DATA].slice(0);
abe05a73
XL
719 var total = 0;
720 var done = 0;
721 // We need to find the type that matches the most to remove it in order
722 // to move forward.
0731742a
XL
723 var vlength = val.generics.length;
724 for (var y = 0; y < vlength; ++y) {
abe05a73 725 var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1};
0731742a
XL
726 var elength = elems.length;
727 for (var x = 0; x < elength; ++x) {
abe05a73
XL
728 var tmp_lev = levenshtein(elems[x], val.generics[y]);
729 if (tmp_lev < lev.lev) {
730 lev.lev = tmp_lev;
731 lev.pos = x;
732 }
733 }
734 if (lev.pos !== -1) {
735 elems.splice(lev.pos, 1);
736 lev_distance = Math.min(lev.lev, lev_distance);
737 total += lev.lev;
738 done += 1;
739 } else {
740 return MAX_LEV_DISTANCE + 1;
741 }
742 }
9fa01778 743 return Math.ceil(total / done);
abe05a73
XL
744 }
745 }
746 return MAX_LEV_DISTANCE + 1;
747 }
748
749 // Check for type name and type generics (if any).
750 function checkType(obj, val, literalSearch) {
751 var lev_distance = MAX_LEV_DISTANCE + 1;
0731742a 752 var x;
8faf50e0 753 if (obj[NAME] === val.name) {
abe05a73 754 if (literalSearch === true) {
2c00a5a8 755 if (val.generics && val.generics.length !== 0) {
8faf50e0
XL
756 if (obj.length > GENERICS_DATA &&
757 obj[GENERICS_DATA].length >= val.generics.length) {
758 var elems = obj[GENERICS_DATA].slice(0);
abe05a73 759 var allFound = true;
abe05a73
XL
760
761 for (var y = 0; allFound === true && y < val.generics.length; ++y) {
762 allFound = false;
763 for (x = 0; allFound === false && x < elems.length; ++x) {
764 allFound = elems[x] === val.generics[y];
765 }
766 if (allFound === true) {
767 elems.splice(x - 1, 1);
768 }
769 }
770 if (allFound === true) {
771 return true;
772 }
773 } else {
774 return false;
775 }
776 }
777 return true;
778 }
779 // If the type has generics but don't match, then it won't return at this point.
780 // Otherwise, `checkGenerics` will return 0 and it'll return.
8faf50e0 781 if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
abe05a73
XL
782 var tmp_lev = checkGenerics(obj, val);
783 if (tmp_lev <= MAX_LEV_DISTANCE) {
784 return tmp_lev;
785 }
786 } else {
787 return 0;
788 }
789 }
790 // Names didn't match so let's check if one of the generic types could.
791 if (literalSearch === true) {
8faf50e0 792 if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
0731742a
XL
793 var length = obj[GENERICS_DATA].length;
794 for (x = 0; x < length; ++x) {
8faf50e0 795 if (obj[GENERICS_DATA][x] === val.name) {
abe05a73
XL
796 return true;
797 }
798 }
799 }
800 return false;
801 }
0731742a 802 lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
abe05a73 803 if (lev_distance <= MAX_LEV_DISTANCE) {
532ac7d7
XL
804 // The generics didn't match but the name kinda did so we give it
805 // a levenshtein distance value that isn't *this* good so it goes
806 // into the search results but not too high.
807 lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
8faf50e0 808 } else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
abe05a73 809 // We can check if the type we're looking for is inside the generics!
0731742a
XL
810 var olength = obj[GENERICS_DATA].length;
811 for (x = 0; x < olength; ++x) {
8faf50e0 812 lev_distance = Math.min(levenshtein(obj[GENERICS_DATA][x], val.name),
abe05a73
XL
813 lev_distance);
814 }
815 }
816 // Now whatever happens, the returned distance is "less good" so we should mark it
817 // as such, and so we add 1 to the distance to make it "less good".
818 return lev_distance + 1;
819 }
820
821 function findArg(obj, val, literalSearch) {
822 var lev_distance = MAX_LEV_DISTANCE + 1;
823
8faf50e0
XL
824 if (obj && obj.type && obj.type[INPUTS_DATA] &&
825 obj.type[INPUTS_DATA].length > 0) {
0731742a
XL
826 var length = obj.type[INPUTS_DATA].length;
827 for (var i = 0; i < length; i++) {
8faf50e0 828 var tmp = checkType(obj.type[INPUTS_DATA][i], val, literalSearch);
abe05a73
XL
829 if (literalSearch === true && tmp === true) {
830 return true;
831 }
832 lev_distance = Math.min(tmp, lev_distance);
833 if (lev_distance === 0) {
834 return 0;
835 }
836 }
837 }
838 return literalSearch === true ? false : lev_distance;
839 }
840
841 function checkReturned(obj, val, literalSearch) {
842 var lev_distance = MAX_LEV_DISTANCE + 1;
843
8faf50e0 844 if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
532ac7d7
XL
845 var ret = obj.type[OUTPUT_DATA];
846 if (!obj.type[OUTPUT_DATA].length) {
847 ret = [ret];
abe05a73 848 }
532ac7d7
XL
849 for (var x = 0; x < ret.length; ++x) {
850 var r = ret[x];
851 if (typeof r === "string") {
852 r = [r];
853 }
854 var tmp = checkType(r, val, literalSearch);
855 if (literalSearch === true) {
856 if (tmp === true) {
857 return true;
858 }
859 continue;
860 }
861 lev_distance = Math.min(tmp, lev_distance);
862 if (lev_distance === 0) {
863 return 0;
864 }
abe05a73
XL
865 }
866 }
867 return literalSearch === true ? false : lev_distance;
868 }
869
b7449926
XL
870 function checkPath(contains, lastElem, ty) {
871 if (contains.length === 0) {
ff7c6d11
XL
872 return 0;
873 }
abe05a73
XL
874 var ret_lev = MAX_LEV_DISTANCE + 1;
875 var path = ty.path.split("::");
876
877 if (ty.parent && ty.parent.name) {
878 path.push(ty.parent.name.toLowerCase());
879 }
880
0731742a
XL
881 var length = path.length;
882 var clength = contains.length;
883 if (clength > length) {
abe05a73
XL
884 return MAX_LEV_DISTANCE + 1;
885 }
0731742a
XL
886 for (var i = 0; i < length; ++i) {
887 if (i + clength > length) {
abe05a73
XL
888 break;
889 }
890 var lev_total = 0;
891 var aborted = false;
0731742a 892 for (var x = 0; x < clength; ++x) {
b7449926 893 var lev = levenshtein(path[i + x], contains[x]);
abe05a73
XL
894 if (lev > MAX_LEV_DISTANCE) {
895 aborted = true;
896 break;
897 }
898 lev_total += lev;
899 }
900 if (aborted === false) {
0731742a 901 ret_lev = Math.min(ret_lev, Math.round(lev_total / clength));
abe05a73 902 }
1a4d82fc 903 }
abe05a73 904 return ret_lev;
1a4d82fc
JJ
905 }
906
e9174d1e
SL
907 function typePassesFilter(filter, type) {
908 // No filter
909 if (filter < 0) return true;
910
911 // Exact match
912 if (filter === type) return true;
913
914 // Match related items
915 var name = itemTypes[type];
916 switch (itemTypes[filter]) {
917 case "constant":
918 return (name == "associatedconstant");
919 case "fn":
920 return (name == "method" || name == "tymethod");
921 case "type":
94b46f34 922 return (name == "primitive" || name == "keyword");
e9174d1e
SL
923 }
924
925 // No match
926 return false;
927 }
928
abe05a73
XL
929 function generateId(ty) {
930 if (ty.parent && ty.parent.name) {
931 return itemTypes[ty.ty] + ty.path + ty.parent.name + ty.name;
932 }
933 return itemTypes[ty.ty] + ty.path + ty.name;
934 }
935
1a4d82fc
JJ
936 // quoted values mean literal search
937 var nSearchWords = searchWords.length;
0731742a
XL
938 var i;
939 var ty;
940 var fullId;
941 var returned;
942 var in_args;
1a4d82fc
JJ
943 if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
944 val.charAt(val.length - 1) === val.charAt(0))
945 {
abe05a73 946 val = extractGenerics(val.substr(1, val.length - 2));
0731742a
XL
947 for (i = 0; i < nSearchWords; ++i) {
948 if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
949 continue;
950 }
951 in_args = findArg(searchIndex[i], val, true);
952 returned = checkReturned(searchIndex[i], val, true);
953 ty = searchIndex[i];
954 fullId = generateId(ty);
abe05a73
XL
955
956 if (searchWords[i] === val.name) {
1a4d82fc 957 // filter type: ... queries
abe05a73
XL
958 if (typePassesFilter(typeFilter, searchIndex[i].ty) &&
959 results[fullId] === undefined)
960 {
961 results[fullId] = {id: i, index: -1};
962 }
963 } else if ((in_args === true || returned === true) &&
964 typePassesFilter(typeFilter, searchIndex[i].ty)) {
965 if (in_args === true || returned === true) {
966 if (in_args === true) {
967 results_in_args[fullId] = {
968 id: i,
969 index: -1,
970 dontValidate: true,
971 };
972 }
973 if (returned === true) {
974 results_returned[fullId] = {
975 id: i,
976 index: -1,
977 dontValidate: true,
978 };
979 }
980 } else {
981 results[fullId] = {
982 id: i,
983 index: -1,
984 dontValidate: true,
985 };
1a4d82fc 986 }
1a4d82fc
JJ
987 }
988 }
abe05a73
XL
989 query.inputs = [val];
990 query.output = val;
991 query.search = val;
c34b1796
AL
992 // searching by type
993 } else if (val.search("->") > -1) {
83c7162d 994 var trimmer = function(s) { return s.trim(); };
c34b1796
AL
995 var parts = val.split("->").map(trimmer);
996 var input = parts[0];
997 // sort inputs so that order does not matter
abe05a73 998 var inputs = input.split(",").map(trimmer).sort();
0731742a 999 for (i = 0; i < inputs.length; ++i) {
abe05a73
XL
1000 inputs[i] = extractGenerics(inputs[i]);
1001 }
1002 var output = extractGenerics(parts[1]);
c34b1796 1003
0731742a
XL
1004 for (i = 0; i < nSearchWords; ++i) {
1005 if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
1006 continue;
1007 }
c34b1796 1008 var type = searchIndex[i].type;
0731742a 1009 ty = searchIndex[i];
c34b1796
AL
1010 if (!type) {
1011 continue;
1012 }
0731742a 1013 fullId = generateId(ty);
c34b1796
AL
1014
1015 // allow searching for void (no output) functions as well
8faf50e0 1016 var typeOutput = type.length > OUTPUT_DATA ? type[OUTPUT_DATA].name : "";
0731742a 1017 returned = checkReturned(ty, output, true);
abe05a73 1018 if (output.name === "*" || returned === true) {
0731742a 1019 in_args = false;
48663c56 1020 var is_module = false;
abe05a73
XL
1021
1022 if (input === "*") {
48663c56 1023 is_module = true;
abe05a73
XL
1024 } else {
1025 var allFound = true;
1026 for (var it = 0; allFound === true && it < inputs.length; it++) {
1027 allFound = checkType(type, inputs[it], true);
1a4d82fc 1028 }
abe05a73 1029 in_args = allFound;
1a4d82fc 1030 }
abe05a73
XL
1031 if (in_args === true) {
1032 results_in_args[fullId] = {
1033 id: i,
1034 index: -1,
1035 dontValidate: true,
1036 };
1037 }
1038 if (returned === true) {
1039 results_returned[fullId] = {
1040 id: i,
1041 index: -1,
1042 dontValidate: true,
1043 };
1044 }
48663c56 1045 if (is_module === true) {
abe05a73
XL
1046 results[fullId] = {
1047 id: i,
1048 index: -1,
1049 dontValidate: true,
1050 };
1a4d82fc
JJ
1051 }
1052 }
1053 }
abe05a73
XL
1054 query.inputs = inputs.map(function(input) {
1055 return input.name;
1056 });
1057 query.output = output.name;
1058 } else {
1059 query.inputs = [val];
1060 query.output = val;
1061 query.search = val;
1062 // gather matching search results up to a certain maximum
1063 val = val.replace(/\_/g, "");
1a4d82fc 1064
abe05a73 1065 var valGenerics = extractGenerics(val);
1a4d82fc 1066
abe05a73
XL
1067 var paths = valLower.split("::");
1068 var j;
1069 for (j = 0; j < paths.length; ++j) {
1070 if (paths[j] === "") {
1071 paths.splice(j, 1);
1072 j -= 1;
1073 }
b039eaaf 1074 }
abe05a73 1075 val = paths[paths.length - 1];
b7449926 1076 var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
1a4d82fc 1077
60c5eb7d
XL
1078 var lev;
1079 var lev_distance;
abe05a73 1080 for (j = 0; j < nSearchWords; ++j) {
0731742a
XL
1081 ty = searchIndex[j];
1082 if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) {
abe05a73
XL
1083 continue;
1084 }
1085 var lev_add = 0;
1086 if (paths.length > 1) {
0731742a 1087 lev = checkPath(contains, paths[paths.length - 1], ty);
abe05a73
XL
1088 if (lev > MAX_LEV_DISTANCE) {
1089 continue;
1090 } else if (lev > 0) {
e1599b0c 1091 lev_add = lev / 10;
abe05a73
XL
1092 }
1093 }
1a4d82fc 1094
0731742a
XL
1095 returned = MAX_LEV_DISTANCE + 1;
1096 in_args = MAX_LEV_DISTANCE + 1;
abe05a73
XL
1097 var index = -1;
1098 // we want lev results to go lower than others
0731742a
XL
1099 lev = MAX_LEV_DISTANCE + 1;
1100 fullId = generateId(ty);
abe05a73
XL
1101
1102 if (searchWords[j].indexOf(split[i]) > -1 ||
1103 searchWords[j].indexOf(val) > -1 ||
1104 searchWords[j].replace(/_/g, "").indexOf(val) > -1)
1105 {
1106 // filter type: ... queries
1107 if (typePassesFilter(typeFilter, ty.ty) && results[fullId] === undefined) {
1108 index = searchWords[j].replace(/_/g, "").indexOf(val);
1109 }
1110 }
1111 if ((lev = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
1112 if (typePassesFilter(typeFilter, ty.ty) === false) {
1113 lev = MAX_LEV_DISTANCE + 1;
1114 } else {
1115 lev += 1;
1116 }
1117 }
1118 if ((in_args = findArg(ty, valGenerics)) <= MAX_LEV_DISTANCE) {
1119 if (typePassesFilter(typeFilter, ty.ty) === false) {
1120 in_args = MAX_LEV_DISTANCE + 1;
1121 }
1122 }
1123 if ((returned = checkReturned(ty, valGenerics)) <= MAX_LEV_DISTANCE) {
1124 if (typePassesFilter(typeFilter, ty.ty) === false) {
1125 returned = MAX_LEV_DISTANCE + 1;
1126 }
1127 }
1a4d82fc 1128
abe05a73 1129 lev += lev_add;
b7449926 1130 if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
ff7c6d11
XL
1131 if (val.length < 6) {
1132 lev -= 1;
1133 } else {
1134 lev = 0;
1135 }
1136 }
abe05a73
XL
1137 if (in_args <= MAX_LEV_DISTANCE) {
1138 if (results_in_args[fullId] === undefined) {
1139 results_in_args[fullId] = {
1140 id: j,
1141 index: index,
1142 lev: in_args,
1143 };
1144 }
1145 results_in_args[fullId].lev =
1146 Math.min(results_in_args[fullId].lev, in_args);
1147 }
1148 if (returned <= MAX_LEV_DISTANCE) {
1149 if (results_returned[fullId] === undefined) {
1150 results_returned[fullId] = {
1151 id: j,
1152 index: index,
1153 lev: returned,
1154 };
1155 }
1156 results_returned[fullId].lev =
1157 Math.min(results_returned[fullId].lev, returned);
1158 }
1159 if (index !== -1 || lev <= MAX_LEV_DISTANCE) {
94b46f34 1160 if (index !== -1 && paths.length < 2) {
abe05a73
XL
1161 lev = 0;
1162 }
1163 if (results[fullId] === undefined) {
1164 results[fullId] = {
1165 id: j,
1166 index: index,
1167 lev: lev,
1168 };
1169 }
1170 results[fullId].lev = Math.min(results[fullId].lev, lev);
1171 }
1a4d82fc
JJ
1172 }
1173 }
c34b1796 1174
83c7162d 1175 var ret = {
0731742a
XL
1176 "in_args": sortResults(results_in_args, true),
1177 "returned": sortResults(results_returned, true),
1178 "others": sortResults(results),
abe05a73 1179 };
83c7162d
XL
1180 if (ALIASES && ALIASES[window.currentCrate] &&
1181 ALIASES[window.currentCrate][query.raw]) {
1182 var aliases = ALIASES[window.currentCrate][query.raw];
0731742a 1183 for (i = 0; i < aliases.length; ++i) {
94b46f34
XL
1184 aliases[i].is_alias = true;
1185 aliases[i].alias = query.raw;
1186 aliases[i].path = aliases[i].p;
1187 var res = buildHrefAndPath(aliases[i]);
1188 aliases[i].displayPath = pathSplitter(res[0]);
1189 aliases[i].fullPath = aliases[i].displayPath + aliases[i].name;
1190 aliases[i].href = res[1];
0731742a
XL
1191 ret.others.unshift(aliases[i]);
1192 if (ret.others.length > MAX_RESULTS) {
1193 ret.others.pop();
83c7162d
XL
1194 }
1195 }
1196 }
1197 return ret;
1a4d82fc
JJ
1198 }
1199
1200 /**
1201 * Validate performs the following boolean logic. For example:
1202 * "File::open" will give IF A PARENT EXISTS => ("file" && "open")
1203 * exists in (name || path || parent) OR => ("file" && "open") exists in
1204 * (name || path )
1205 *
1206 * This could be written functionally, but I wanted to minimise
1207 * functions on stack.
1208 *
1209 * @param {[string]} name [The name of the result]
1210 * @param {[string]} path [The path of the result]
1211 * @param {[string]} keys [The keys to be used (["file", "open"])]
1212 * @param {[object]} parent [The parent of the result]
1213 * @return {[boolean]} [Whether the result is valid or not]
1214 */
1215 function validateResult(name, path, keys, parent) {
62682a34 1216 for (var i = 0; i < keys.length; ++i) {
1a4d82fc
JJ
1217 // each check is for validation so we negate the conditions and invalidate
1218 if (!(
1219 // check for an exact name match
abe05a73 1220 name.indexOf(keys[i]) > -1 ||
1a4d82fc 1221 // then an exact path match
abe05a73 1222 path.indexOf(keys[i]) > -1 ||
1a4d82fc 1223 // next if there is a parent, check for exact parent match
60c5eb7d 1224 (parent !== undefined && parent.name !== undefined &&
1a4d82fc
JJ
1225 parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
1226 // lastly check to see if the name was a levenshtein match
abe05a73 1227 levenshtein(name, keys[i]) <= MAX_LEV_DISTANCE)) {
1a4d82fc
JJ
1228 return false;
1229 }
1230 }
1231 return true;
1232 }
1233
2c00a5a8
XL
1234 function getQuery(raw) {
1235 var matches, type, query;
1a4d82fc
JJ
1236 query = raw;
1237
e9174d1e 1238 matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
1a4d82fc 1239 if (matches) {
0731742a 1240 type = matches[1].replace(/^const$/, "constant");
1a4d82fc
JJ
1241 query = query.substring(matches[0].length);
1242 }
1243
1244 return {
1245 raw: raw,
1246 query: query,
1247 type: type,
62682a34 1248 id: query + type
1a4d82fc
JJ
1249 };
1250 }
1251
1252 function initSearchNav() {
7cac9316 1253 var hoverTimeout;
1a4d82fc 1254
7cac9316
XL
1255 var click_func = function(e) {
1256 var el = e.target;
1257 // to retrieve the real "owner" of the event.
0731742a 1258 while (el.tagName !== "TR") {
7cac9316
XL
1259 el = el.parentNode;
1260 }
0731742a 1261 var dst = e.target.getElementsByTagName("a");
7cac9316
XL
1262 if (dst.length < 1) {
1263 return;
1264 }
1265 dst = dst[0];
62682a34 1266 if (window.location.pathname === dst.pathname) {
e74abb32 1267 addClass(getSearchElement(), "hidden");
0731742a 1268 removeClass(main, "hidden");
1a4d82fc
JJ
1269 document.location.href = dst.href;
1270 }
7cac9316
XL
1271 };
1272 var mouseover_func = function(e) {
1273 var el = e.target;
1274 // to retrieve the real "owner" of the event.
0731742a 1275 while (el.tagName !== "TR") {
7cac9316
XL
1276 el = el.parentNode;
1277 }
1a4d82fc
JJ
1278 clearTimeout(hoverTimeout);
1279 hoverTimeout = setTimeout(function() {
0731742a
XL
1280 onEachLazy(document.getElementsByClassName("search-results"), function(e) {
1281 onEachLazy(e.getElementsByClassName("result"), function(i_e) {
1282 removeClass(i_e, "highlighted");
7cac9316
XL
1283 });
1284 });
0731742a 1285 addClass(el, "highlighted");
1a4d82fc 1286 }, 20);
7cac9316 1287 };
0731742a
XL
1288 onEachLazy(document.getElementsByClassName("search-results"), function(e) {
1289 onEachLazy(e.getElementsByClassName("result"), function(i_e) {
7cac9316
XL
1290 i_e.onclick = click_func;
1291 i_e.onmouseover = mouseover_func;
1292 });
1a4d82fc
JJ
1293 });
1294
7cac9316 1295 search_input.onkeydown = function(e) {
abe05a73
XL
1296 // "actives" references the currently highlighted item in each search tab.
1297 // Each array in "actives" represents a tab.
1298 var actives = [[], [], []];
1299 // "current" is used to know which tab we're looking into.
1300 var current = 0;
9fa01778 1301 onEachLazy(document.getElementById("results").childNodes, function(e) {
0731742a 1302 onEachLazy(e.getElementsByClassName("highlighted"), function(e) {
abe05a73 1303 actives[current].push(e);
7cac9316 1304 });
abe05a73 1305 current += 1;
7cac9316 1306 });
1a4d82fc
JJ
1307
1308 if (e.which === 38) { // up
abe05a73
XL
1309 if (!actives[currentTab].length ||
1310 !actives[currentTab][0].previousElementSibling) {
1a4d82fc
JJ
1311 return;
1312 }
1313
0731742a
XL
1314 addClass(actives[currentTab][0].previousElementSibling, "highlighted");
1315 removeClass(actives[currentTab][0], "highlighted");
1a4d82fc 1316 } else if (e.which === 40) { // down
abe05a73 1317 if (!actives[currentTab].length) {
9fa01778 1318 var results = document.getElementById("results").childNodes;
7cac9316 1319 if (results.length > 0) {
0731742a 1320 var res = results[currentTab].getElementsByClassName("result");
7cac9316 1321 if (res.length > 0) {
0731742a 1322 addClass(res[0], "highlighted");
7cac9316
XL
1323 }
1324 }
abe05a73 1325 } else if (actives[currentTab][0].nextElementSibling) {
0731742a
XL
1326 addClass(actives[currentTab][0].nextElementSibling, "highlighted");
1327 removeClass(actives[currentTab][0], "highlighted");
1a4d82fc
JJ
1328 }
1329 } else if (e.which === 13) { // return
abe05a73
XL
1330 if (actives[currentTab].length) {
1331 document.location.href =
0731742a 1332 actives[currentTab][0].getElementsByTagName("a")[0].href;
abe05a73
XL
1333 }
1334 } else if (e.which === 9) { // tab
1335 if (e.shiftKey) {
1336 printTab(currentTab > 0 ? currentTab - 1 : 2);
1337 } else {
1338 printTab(currentTab > 1 ? 0 : currentTab + 1);
1a4d82fc 1339 }
abe05a73
XL
1340 e.preventDefault();
1341 } else if (e.which === 16) { // shift
1342 // Does nothing, it's just to avoid losing "focus" on the highlighted element.
2c00a5a8 1343 } else if (e.which === 27) { // escape
e1599b0c 1344 handleEscape(e);
abe05a73 1345 } else if (actives[currentTab].length > 0) {
0731742a 1346 removeClass(actives[currentTab][0], "highlighted");
1a4d82fc 1347 }
7cac9316 1348 };
1a4d82fc
JJ
1349 }
1350
83c7162d
XL
1351 function buildHrefAndPath(item) {
1352 var displayPath;
1353 var href;
1354 var type = itemTypes[item.ty];
1355 var name = item.name;
1356
0731742a
XL
1357 if (type === "mod") {
1358 displayPath = item.path + "::";
1359 href = rootPath + item.path.replace(/::/g, "/") + "/" +
1360 name + "/index.html";
94b46f34 1361 } else if (type === "primitive" || type === "keyword") {
83c7162d 1362 displayPath = "";
0731742a
XL
1363 href = rootPath + item.path.replace(/::/g, "/") +
1364 "/" + type + "." + name + ".html";
83c7162d
XL
1365 } else if (type === "externcrate") {
1366 displayPath = "";
0731742a 1367 href = rootPath + name + "/index.html";
83c7162d
XL
1368 } else if (item.parent !== undefined) {
1369 var myparent = item.parent;
0731742a 1370 var anchor = "#" + type + "." + name;
83c7162d
XL
1371 var parentType = itemTypes[myparent.ty];
1372 if (parentType === "primitive") {
0731742a 1373 displayPath = myparent.name + "::";
83c7162d 1374 } else {
0731742a 1375 displayPath = item.path + "::" + myparent.name + "::";
83c7162d 1376 }
0731742a
XL
1377 href = rootPath + item.path.replace(/::/g, "/") +
1378 "/" + parentType +
1379 "." + myparent.name +
1380 ".html" + anchor;
83c7162d 1381 } else {
0731742a
XL
1382 displayPath = item.path + "::";
1383 href = rootPath + item.path.replace(/::/g, "/") +
1384 "/" + type + "." + name + ".html";
83c7162d
XL
1385 }
1386 return [displayPath, href];
1387 }
1388
94b46f34 1389 function escape(content) {
0731742a 1390 var h1 = document.createElement("h1");
94b46f34
XL
1391 h1.textContent = content;
1392 return h1.innerHTML;
1393 }
1394
1395 function pathSplitter(path) {
0731742a 1396 var tmp = "<span>" + path.replace(/::/g, "::</span><span>");
94b46f34
XL
1397 if (tmp.endsWith("<span>")) {
1398 return tmp.slice(0, tmp.length - 6);
1399 }
1400 return tmp;
1401 }
1402
abe05a73 1403 function addTab(array, query, display) {
0731742a 1404 var extraStyle = "";
abe05a73 1405 if (display === false) {
0731742a 1406 extraStyle = " style=\"display: none;\"";
abe05a73 1407 }
1a4d82fc 1408
0731742a 1409 var output = "";
94b46f34
XL
1410 var duplicates = {};
1411 var length = 0;
abe05a73 1412 if (array.length > 0) {
0731742a 1413 output = "<table class=\"search-results\"" + extraStyle + ">";
1a4d82fc 1414
abe05a73 1415 array.forEach(function(item) {
94b46f34 1416 var name, type;
1a4d82fc 1417
1a4d82fc
JJ
1418 name = item.name;
1419 type = itemTypes[item.ty];
1420
94b46f34
XL
1421 if (item.is_alias !== true) {
1422 if (duplicates[item.fullPath]) {
1423 return;
1424 }
1425 duplicates[item.fullPath] = true;
1426 }
1427 length += 1;
1a4d82fc 1428
0731742a
XL
1429 output += "<tr class=\"" + type + " result\"><td>" +
1430 "<a href=\"" + item.href + "\">" +
94b46f34 1431 (item.is_alias === true ?
0731742a
XL
1432 ("<span class=\"alias\"><b>" + item.alias + " </b></span><span " +
1433 "class=\"grey\"><i>&nbsp;- see&nbsp;</i></span>") : "") +
1434 item.displayPath + "<span class=\"" + type + "\">" +
1435 name + "</span></a></td><td>" +
1436 "<a href=\"" + item.href + "\">" +
1437 "<span class=\"desc\">" + escape(item.desc) +
1438 "&nbsp;</span></a></td></tr>";
1a4d82fc 1439 });
0731742a 1440 output += "</table>";
1a4d82fc 1441 } else {
0731742a
XL
1442 output = "<div class=\"search-failed\"" + extraStyle + ">No results :(<br/>" +
1443 "Try on <a href=\"https://duckduckgo.com/?q=" +
1444 encodeURIComponent("rust " + query.query) +
1445 "\">DuckDuckGo</a>?<br/><br/>" +
1446 "Or try looking in one of these:<ul><li>The <a " +
1447 "href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " +
1448 " for technical details about the language.</li><li><a " +
1449 "href=\"https://doc.rust-lang.org/rust-by-example/index.html\">Rust By " +
1450 "Example</a> for expository code examples.</a></li><li>The <a " +
1451 "href=\"https://doc.rust-lang.org/book/index.html\">Rust Book</a> for " +
1452 "introductions to language features and the language itself.</li><li><a " +
1453 "href=\"https://docs.rs\">Docs.rs</a> for documentation of crates released on" +
1454 " <a href=\"https://crates.io/\">crates.io</a>.</li></ul></div>";
1a4d82fc 1455 }
94b46f34 1456 return [output, length];
abe05a73
XL
1457 }
1458
1459 function makeTabHeader(tabNb, text, nbElems) {
1460 if (currentTab === tabNb) {
0731742a
XL
1461 return "<div class=\"selected\">" + text +
1462 " <div class=\"count\">(" + nbElems + ")</div></div>";
abe05a73 1463 }
0731742a 1464 return "<div>" + text + " <div class=\"count\">(" + nbElems + ")</div></div>";
abe05a73
XL
1465 }
1466
1467 function showResults(results) {
0731742a
XL
1468 if (results.others.length === 1 &&
1469 getCurrentValue("rustdoc-go-to-only-result") === "true") {
1470 var elem = document.createElement("a");
1471 elem.href = results.others[0].href;
1472 elem.style.display = "none";
83c7162d
XL
1473 // For firefox, we need the element to be in the DOM so it can be clicked.
1474 document.body.appendChild(elem);
1475 elem.click();
1476 }
94b46f34 1477 var query = getQuery(search_input.value);
abe05a73
XL
1478
1479 currentResults = query.id;
94b46f34 1480
0731742a
XL
1481 var ret_others = addTab(results.others, query);
1482 var ret_in_args = addTab(results.in_args, query, false);
1483 var ret_returned = addTab(results.returned, query, false);
94b46f34 1484
0731742a
XL
1485 var output = "<h1>Results for " + escape(query.query) +
1486 (query.type ? " (type: " + escape(query.type) + ")" : "") + "</h1>" +
1487 "<div id=\"titles\">" +
94b46f34
XL
1488 makeTabHeader(0, "In Names", ret_others[1]) +
1489 makeTabHeader(1, "In Parameters", ret_in_args[1]) +
1490 makeTabHeader(2, "In Return Types", ret_returned[1]) +
0731742a
XL
1491 "</div><div id=\"results\">" +
1492 ret_others[0] + ret_in_args[0] + ret_returned[0] + "</div>";
1a4d82fc 1493
0731742a 1494 addClass(main, "hidden");
e1599b0c 1495 var search = getSearchElement();
0731742a 1496 removeClass(search, "hidden");
7cac9316 1497 search.innerHTML = output;
0731742a 1498 var tds = search.getElementsByTagName("td");
7cac9316
XL
1499 var td_width = 0;
1500 if (tds.length > 0) {
1501 td_width = tds[0].offsetWidth;
1502 }
1503 var width = search.offsetWidth - 40 - td_width;
0731742a
XL
1504 onEachLazy(search.getElementsByClassName("desc"), function(e) {
1505 e.style.width = width + "px";
7cac9316 1506 });
1a4d82fc 1507 initSearchNav();
0731742a 1508 var elems = document.getElementById("titles").childNodes;
abe05a73
XL
1509 elems[0].onclick = function() { printTab(0); };
1510 elems[1].onclick = function() { printTab(1); };
1511 elems[2].onclick = function() { printTab(2); };
1512 printTab(currentTab);
1a4d82fc
JJ
1513 }
1514
0731742a
XL
1515 function execSearch(query, searchWords, filterCrates) {
1516 function getSmallest(arrays, positions, notDuplicates) {
1517 var start = null;
83c7162d 1518
0731742a
XL
1519 for (var it = 0; it < positions.length; ++it) {
1520 if (arrays[it].length > positions[it] &&
1521 (start === null || start > arrays[it][positions[it]].lev) &&
1522 !notDuplicates[arrays[it][positions[it]].fullPath]) {
1523 start = arrays[it][positions[it]].lev;
83c7162d 1524 }
83c7162d 1525 }
0731742a
XL
1526 return start;
1527 }
83c7162d 1528
0731742a
XL
1529 function mergeArrays(arrays) {
1530 var ret = [];
1531 var positions = [];
1532 var notDuplicates = {};
83c7162d 1533
0731742a
XL
1534 for (var x = 0; x < arrays.length; ++x) {
1535 positions.push(0);
1536 }
1537 while (ret.length < MAX_RESULTS) {
1538 var smallest = getSmallest(arrays, positions, notDuplicates);
94b46f34 1539
0731742a
XL
1540 if (smallest === null) {
1541 break;
1542 }
1543 for (x = 0; x < arrays.length && ret.length < MAX_RESULTS; ++x) {
1544 if (arrays[x].length > positions[x] &&
1545 arrays[x][positions[x]].lev === smallest &&
1546 !notDuplicates[arrays[x][positions[x]].fullPath]) {
1547 ret.push(arrays[x][positions[x]]);
1548 notDuplicates[arrays[x][positions[x]].fullPath] = true;
1549 positions[x] += 1;
83c7162d
XL
1550 }
1551 }
83c7162d 1552 }
0731742a
XL
1553 return ret;
1554 }
1555
1556 var queries = query.raw.split(",");
1557 var results = {
1558 "in_args": [],
1559 "returned": [],
1560 "others": [],
1561 };
1562
1563 for (var i = 0; i < queries.length; ++i) {
1564 query = queries[i].trim();
1565 if (query.length !== 0) {
1566 var tmp = execQuery(getQuery(query), searchWords, filterCrates);
83c7162d 1567
0731742a
XL
1568 results.in_args.push(tmp.in_args);
1569 results.returned.push(tmp.returned);
1570 results.others.push(tmp.others);
1571 }
1572 }
1573 if (queries.length > 1) {
83c7162d 1574 return {
0731742a
XL
1575 "in_args": mergeArrays(results.in_args),
1576 "returned": mergeArrays(results.returned),
1577 "others": mergeArrays(results.others),
83c7162d
XL
1578 };
1579 } else {
1580 return {
0731742a
XL
1581 "in_args": results.in_args[0],
1582 "returned": results.returned[0],
1583 "others": results.others[0],
83c7162d
XL
1584 };
1585 }
1586 }
1587
0731742a
XL
1588 function getFilterCrates() {
1589 var elem = document.getElementById("crate-search");
1590
1591 if (elem && elem.value !== "All crates" && rawSearchIndex.hasOwnProperty(elem.value)) {
1592 return elem.value;
1593 }
1594 return undefined;
1595 }
1596
1597 function search(e, forced) {
1a4d82fc 1598 var params = getQueryStringParams();
83c7162d 1599 var query = getQuery(search_input.value.trim());
1a4d82fc 1600
1a4d82fc
JJ
1601 if (e) {
1602 e.preventDefault();
1603 }
1604
0731742a
XL
1605 if (query.query.length === 0) {
1606 return;
1607 }
1608 if (forced !== true && query.id === currentResults) {
83c7162d
XL
1609 if (query.query.length > 0) {
1610 putBackSearch(search_input);
1611 }
1a4d82fc
JJ
1612 return;
1613 }
1614
62682a34 1615 // Update document title to maintain a meaningful browser history
7cac9316 1616 document.title = "Results for " + query.query + " - Rust";
62682a34 1617
1a4d82fc
JJ
1618 // Because searching is incremental by character, only the most
1619 // recent search query is added to the browser history.
1620 if (browserSupportsHistoryApi()) {
1621 if (!history.state && !params.search) {
7cac9316 1622 history.pushState(query, "", "?search=" + encodeURIComponent(query.raw));
1a4d82fc 1623 } else {
7cac9316 1624 history.replaceState(query, "", "?search=" + encodeURIComponent(query.raw));
1a4d82fc
JJ
1625 }
1626 }
1627
0731742a 1628 var filterCrates = getFilterCrates();
60c5eb7d 1629 showResults(execSearch(query, index, filterCrates));
1a4d82fc
JJ
1630 }
1631
1a4d82fc
JJ
1632 function buildIndex(rawSearchIndex) {
1633 searchIndex = [];
1634 var searchWords = [];
0731742a
XL
1635 var i;
1636
1a4d82fc 1637 for (var crate in rawSearchIndex) {
62682a34 1638 if (!rawSearchIndex.hasOwnProperty(crate)) { continue; }
1a4d82fc 1639
7453a54e
SL
1640 searchWords.push(crate);
1641 searchIndex.push({
1642 crate: crate,
1643 ty: 1, // == ExternCrate
1644 name: crate,
1645 path: "",
1646 desc: rawSearchIndex[crate].doc,
1647 type: null,
1648 });
1649
1a4d82fc
JJ
1650 // an array of [(Number) item type,
1651 // (String) name,
1652 // (String) full path or empty string for previous path,
1653 // (String) description,
c34b1796
AL
1654 // (Number | null) the parent path index to `paths`]
1655 // (Object | null) the type of the function (if any)
9fa01778 1656 var items = rawSearchIndex[crate].i;
1a4d82fc
JJ
1657 // an array of [(Number) item type,
1658 // (String) name]
9fa01778 1659 var paths = rawSearchIndex[crate].p;
1a4d82fc
JJ
1660
1661 // convert `paths` into an object form
1662 var len = paths.length;
0731742a 1663 for (i = 0; i < len; ++i) {
1a4d82fc
JJ
1664 paths[i] = {ty: paths[i][0], name: paths[i][1]};
1665 }
1666
1667 // convert `items` into an object form, and construct word indices.
1668 //
1669 // before any analysis is performed lets gather the search terms to
1670 // search against apart from the rest of the data. This is a quick
1671 // operation that is cached for the life of the page state so that
1672 // all other search operations have access to this cached data for
1673 // faster analysis operations
0731742a 1674 len = items.length;
1a4d82fc 1675 var lastPath = "";
0731742a 1676 for (i = 0; i < len; ++i) {
1a4d82fc
JJ
1677 var rawRow = items[i];
1678 var row = {crate: crate, ty: rawRow[0], name: rawRow[1],
1679 path: rawRow[2] || lastPath, desc: rawRow[3],
c34b1796 1680 parent: paths[rawRow[4]], type: rawRow[5]};
1a4d82fc
JJ
1681 searchIndex.push(row);
1682 if (typeof row.name === "string") {
1683 var word = row.name.toLowerCase();
1684 searchWords.push(word);
1685 } else {
1686 searchWords.push("");
1687 }
1688 lastPath = row.path;
1689 }
1690 }
1691 return searchWords;
1692 }
1693
1694 function startSearch() {
b039eaaf 1695 var searchTimeout;
7cac9316 1696 var callback = function() {
b039eaaf 1697 clearTimeout(searchTimeout);
7cac9316 1698 if (search_input.value.length === 0) {
54a0048b 1699 if (browserSupportsHistoryApi()) {
9fa01778 1700 history.replaceState("", window.currentCrate + " - Rust", "?search=");
54a0048b 1701 }
0731742a
XL
1702 if (hasClass(main, "content")) {
1703 removeClass(main, "hidden");
7cac9316 1704 }
e1599b0c 1705 var search_c = getSearchElement();
0731742a
XL
1706 if (hasClass(search_c, "content")) {
1707 addClass(search_c, "hidden");
7cac9316 1708 }
b039eaaf
SL
1709 } else {
1710 searchTimeout = setTimeout(search, 500);
1711 }
7cac9316 1712 };
7cac9316
XL
1713 search_input.onkeyup = callback;
1714 search_input.oninput = callback;
abe05a73 1715 document.getElementsByClassName("search-form")[0].onsubmit = function(e) {
b039eaaf
SL
1716 e.preventDefault();
1717 clearTimeout(searchTimeout);
1718 search();
7cac9316
XL
1719 };
1720 search_input.onchange = function(e) {
b039eaaf
SL
1721 // Do NOT e.preventDefault() here. It will prevent pasting.
1722 clearTimeout(searchTimeout);
1723 // zero-timeout necessary here because at the time of event handler execution the
1724 // pasted content is not in the input field yet. Shouldn’t make any difference for
1725 // change, though.
1726 setTimeout(search, 0);
7cac9316
XL
1727 };
1728 search_input.onpaste = search_input.onchange;
1a4d82fc 1729
e1599b0c 1730 var selectCrate = document.getElementById("crate-search");
0731742a
XL
1731 if (selectCrate) {
1732 selectCrate.onchange = function() {
e1599b0c 1733 updateLocalStorage("rustdoc-saved-filter-crate", selectCrate.value);
0731742a
XL
1734 search(undefined, true);
1735 };
1736 }
1737
1a4d82fc
JJ
1738 // Push and pop states are used to add search results to the browser
1739 // history.
1740 if (browserSupportsHistoryApi()) {
c1a9b12d 1741 // Store the previous <title> so we can revert back to it later.
7cac9316 1742 var previousTitle = document.title;
c1a9b12d 1743
7cac9316 1744 window.onpopstate = function(e) {
1a4d82fc
JJ
1745 var params = getQueryStringParams();
1746 // When browsing back from search results the main page
1747 // visibility must be reset.
1748 if (!params.search) {
0731742a
XL
1749 if (hasClass(main, "content")) {
1750 removeClass(main, "hidden");
7cac9316 1751 }
e1599b0c 1752 var search_c = getSearchElement();
0731742a
XL
1753 if (hasClass(search_c, "content")) {
1754 addClass(search_c, "hidden");
7cac9316 1755 }
1a4d82fc 1756 }
c1a9b12d
SL
1757 // Revert to the previous title manually since the History
1758 // API ignores the title parameter.
7cac9316 1759 document.title = previousTitle;
1a4d82fc
JJ
1760 // When browsing forward to search results the previous
1761 // search will be repeated, so the currentResults are
1762 // cleared to ensure the search is successful.
1763 currentResults = null;
1764 // Synchronize search bar with query string state and
1765 // perform the search. This will empty the bar if there's
1766 // nothing there, which lets you really go back to a
1767 // previous state with nothing in the bar.
7cac9316 1768 if (params.search) {
83c7162d 1769 search_input.value = params.search;
7cac9316 1770 } else {
0731742a 1771 search_input.value = "";
7cac9316 1772 }
0731742a 1773 // Some browsers fire "onpopstate" for every page load
1a4d82fc
JJ
1774 // (Chrome), while others fire the event only when actually
1775 // popping a state (Firefox), which is why search() is
1776 // called both here and at the end of the startSearch()
1777 // function.
1778 search();
7cac9316 1779 };
1a4d82fc
JJ
1780 }
1781 search();
1782 }
1783
1784 index = buildIndex(rawSearchIndex);
1785 startSearch();
1786
1787 // Draw a convenient sidebar of known crates if we have a listing
0731742a
XL
1788 if (rootPath === "../" || rootPath === "./") {
1789 var sidebar = document.getElementsByClassName("sidebar-elems")[0];
0531ce1d 1790 if (sidebar) {
0731742a
XL
1791 var div = document.createElement("div");
1792 div.className = "block crate";
1793 div.innerHTML = "<h3>Crates</h3>";
1794 var ul = document.createElement("ul");
0531ce1d
XL
1795 div.appendChild(ul);
1796
1797 var crates = [];
1798 for (var crate in rawSearchIndex) {
1799 if (!rawSearchIndex.hasOwnProperty(crate)) {
1800 continue;
1801 }
1802 crates.push(crate);
abe05a73 1803 }
0531ce1d
XL
1804 crates.sort();
1805 for (var i = 0; i < crates.length; ++i) {
0731742a 1806 var klass = "crate";
83c7162d 1807 if (rootPath !== "./" && crates[i] === window.currentCrate) {
0731742a 1808 klass += " current";
0531ce1d 1809 }
0731742a
XL
1810 var link = document.createElement("a");
1811 link.href = rootPath + crates[i] + "/index.html";
0531ce1d
XL
1812 link.title = rawSearchIndex[crates[i]].doc;
1813 link.className = klass;
1814 link.textContent = crates[i];
1815
0731742a 1816 var li = document.createElement("li");
0531ce1d
XL
1817 li.appendChild(link);
1818 ul.appendChild(li);
1a4d82fc 1819 }
0531ce1d 1820 sidebar.appendChild(div);
1a4d82fc 1821 }
1a4d82fc
JJ
1822 }
1823 }
1824
1825 window.initSearch = initSearch;
1826
c34b1796
AL
1827 // delayed sidebar rendering.
1828 function initSidebarItems(items) {
0731742a 1829 var sidebar = document.getElementsByClassName("sidebar-elems")[0];
c34b1796
AL
1830 var current = window.sidebarCurrent;
1831
1832 function block(shortty, longty) {
1833 var filtered = items[shortty];
0731742a
XL
1834 if (!filtered) {
1835 return;
1836 }
c34b1796 1837
0731742a
XL
1838 var div = document.createElement("div");
1839 div.className = "block " + shortty;
1840 var h3 = document.createElement("h3");
7cac9316
XL
1841 h3.textContent = longty;
1842 div.appendChild(h3);
0731742a 1843 var ul = document.createElement("ul");
c34b1796 1844
0731742a
XL
1845 var length = filtered.length;
1846 for (var i = 0; i < length; ++i) {
c34b1796
AL
1847 var item = filtered[i];
1848 var name = item[0];
1849 var desc = item[1]; // can be null
1850
1851 var klass = shortty;
62682a34 1852 if (name === current.name && shortty === current.ty) {
0731742a 1853 klass += " current";
c34b1796
AL
1854 }
1855 var path;
0731742a
XL
1856 if (shortty === "mod") {
1857 path = name + "/index.html";
c34b1796 1858 } else {
0731742a 1859 path = shortty + "." + name + ".html";
c34b1796 1860 }
0731742a 1861 var link = document.createElement("a");
7cac9316
XL
1862 link.href = current.relpath + path;
1863 link.title = desc;
1864 link.className = klass;
1865 link.textContent = name;
0731742a 1866 var li = document.createElement("li");
7cac9316
XL
1867 li.appendChild(link);
1868 ul.appendChild(li);
c34b1796 1869 }
7cac9316 1870 div.appendChild(ul);
2c00a5a8
XL
1871 if (sidebar) {
1872 sidebar.appendChild(div);
1873 }
c34b1796
AL
1874 }
1875
3157f602 1876 block("primitive", "Primitive Types");
c34b1796 1877 block("mod", "Modules");
3157f602 1878 block("macro", "Macros");
c34b1796
AL
1879 block("struct", "Structs");
1880 block("enum", "Enums");
3b2f2976 1881 block("union", "Unions");
3157f602
XL
1882 block("constant", "Constants");
1883 block("static", "Statics");
c34b1796
AL
1884 block("trait", "Traits");
1885 block("fn", "Functions");
3157f602 1886 block("type", "Type Definitions");
abe05a73 1887 block("foreigntype", "Foreign Types");
94b46f34 1888 block("keyword", "Keywords");
9fa01778 1889 block("traitalias", "Trait Aliases");
c34b1796
AL
1890 }
1891
1892 window.initSidebarItems = initSidebarItems;
1893
1a4d82fc 1894 window.register_implementors = function(imp) {
0731742a
XL
1895 var implementors = document.getElementById("implementors-list");
1896 var synthetic_implementors = document.getElementById("synthetic-implementors-list");
0531ce1d 1897
1a4d82fc 1898 var libs = Object.getOwnPropertyNames(imp);
0731742a
XL
1899 var llength = libs.length;
1900 for (var i = 0; i < llength; ++i) {
62682a34 1901 if (libs[i] === currentCrate) { continue; }
1a4d82fc 1902 var structs = imp[libs[i]];
0531ce1d 1903
0731742a 1904 var slength = structs.length;
0531ce1d 1905 struct_loop:
0731742a 1906 for (var j = 0; j < slength; ++j) {
0531ce1d
XL
1907 var struct = structs[j];
1908
1909 var list = struct.synthetic ? synthetic_implementors : implementors;
1910
1911 if (struct.synthetic) {
0731742a
XL
1912 var stlength = struct.types.length;
1913 for (var k = 0; k < stlength; k++) {
0531ce1d
XL
1914 if (window.inlined_types.has(struct.types[k])) {
1915 continue struct_loop;
1916 }
1917 window.inlined_types.add(struct.types[k]);
1918 }
1919 }
1920
0731742a 1921 var code = document.createElement("code");
0531ce1d 1922 code.innerHTML = struct.text;
7cac9316 1923
0731742a
XL
1924 var x = code.getElementsByTagName("a");
1925 var xlength = x.length;
1926 for (var it = 0; it < xlength; it++) {
1927 var href = x[it].getAttribute("href");
1928 if (href && href.indexOf("http") !== 0) {
1929 x[it].setAttribute("href", rootPath + href);
1a4d82fc 1930 }
7cac9316 1931 }
0731742a 1932 var display = document.createElement("h3");
b7449926 1933 addClass(display, "impl");
0731742a
XL
1934 display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" +
1935 "<tbody><tr><td><code>" + code.outerHTML + "</code></td><td></td></tr>" +
1936 "</tbody></table></span>";
b7449926 1937 list.appendChild(display);
1a4d82fc
JJ
1938 }
1939 }
1940 };
1941 if (window.pending_implementors) {
1942 window.register_implementors(window.pending_implementors);
1943 }
1944
d9579d0f
AL
1945 function labelForToggleButton(sectionIsCollapsed) {
1946 if (sectionIsCollapsed) {
1947 // button will expand the section
1948 return "+";
d9579d0f 1949 }
62682a34
SL
1950 // button will collapse the section
1951 // note that this text is also set in the HTML template in render.rs
0731742a 1952 return "\u2212"; // "\u2212" is "−" minus sign
d9579d0f 1953 }
1a4d82fc 1954
7cac9316
XL
1955 function onEveryMatchingChild(elem, className, func) {
1956 if (elem && className && func) {
0731742a
XL
1957 var length = elem.childNodes.length;
1958 var nodes = elem.childNodes;
1959 for (var i = 0; i < length; ++i) {
1960 if (hasClass(nodes[i], className)) {
1961 func(nodes[i]);
7cac9316 1962 } else {
0731742a 1963 onEveryMatchingChild(nodes[i], className, func);
7cac9316
XL
1964 }
1965 }
1966 }
1967 }
1968
94b46f34 1969 function toggleAllDocs(pageId, fromAutoCollapse) {
0731742a
XL
1970 var innerToggle = document.getElementById("toggle-all-docs");
1971 if (!innerToggle) {
83c7162d
XL
1972 return;
1973 }
0731742a 1974 if (hasClass(innerToggle, "will-expand")) {
0531ce1d 1975 updateLocalStorage("rustdoc-collapse", "false");
0731742a
XL
1976 removeClass(innerToggle, "will-expand");
1977 onEveryMatchingChild(innerToggle, "inner", function(e) {
7cac9316
XL
1978 e.innerHTML = labelForToggleButton(false);
1979 });
0731742a 1980 innerToggle.title = "collapse all docs";
94b46f34 1981 if (fromAutoCollapse !== true) {
0731742a 1982 onEachLazy(document.getElementsByClassName("collapse-toggle"), function(e) {
94b46f34
XL
1983 collapseDocs(e, "show");
1984 });
1985 }
d9579d0f 1986 } else {
0531ce1d 1987 updateLocalStorage("rustdoc-collapse", "true");
0731742a
XL
1988 addClass(innerToggle, "will-expand");
1989 onEveryMatchingChild(innerToggle, "inner", function(e) {
9fa01778
XL
1990 var parent = e.parentNode;
1991 var superParent = null;
1992
1993 if (parent) {
1994 superParent = parent.parentNode;
1995 }
1996 if (!parent || !superParent || superParent.id !== "main" ||
1997 hasClass(parent, "impl") === false) {
1998 e.innerHTML = labelForToggleButton(true);
1999 }
7cac9316 2000 });
0731742a 2001 innerToggle.title = "expand all docs";
94b46f34 2002 if (fromAutoCollapse !== true) {
0731742a 2003 onEachLazy(document.getElementsByClassName("collapse-toggle"), function(e) {
9fa01778
XL
2004 var parent = e.parentNode;
2005 var superParent = null;
2006
2007 if (parent) {
2008 superParent = parent.parentNode;
2009 }
2010 if (!parent || !superParent || superParent.id !== "main" ||
2011 hasClass(parent, "impl") === false) {
2012 collapseDocs(e, "hide", pageId);
2013 }
94b46f34
XL
2014 });
2015 }
d9579d0f 2016 }
a7813a04
XL
2017 }
2018
83c7162d 2019 function collapseDocs(toggle, mode, pageId) {
7cac9316
XL
2020 if (!toggle || !toggle.parentNode) {
2021 return;
d9579d0f 2022 }
0531ce1d
XL
2023
2024 function adjustToggle(arg) {
2025 return function(e) {
0731742a 2026 if (hasClass(e, "toggle-label")) {
0531ce1d 2027 if (arg) {
0731742a 2028 e.style.display = "inline-block";
0531ce1d 2029 } else {
0731742a 2030 e.style.display = "none";
7cac9316 2031 }
0531ce1d 2032 }
0731742a 2033 if (hasClass(e, "inner")) {
0531ce1d
XL
2034 e.innerHTML = labelForToggleButton(arg);
2035 }
2036 };
0731742a
XL
2037 }
2038
9fa01778 2039 function implHider(addOrRemove, fullHide) {
0731742a 2040 return function(n) {
9fa01778 2041 var is_method = hasClass(n, "method") || fullHide;
0731742a
XL
2042 if (is_method || hasClass(n, "type")) {
2043 if (is_method === true) {
2044 if (addOrRemove) {
2045 addClass(n, "hidden-by-impl-hider");
2046 } else {
2047 removeClass(n, "hidden-by-impl-hider");
2048 }
2049 }
2050 var ns = n.nextElementSibling;
2051 while (true) {
2052 if (ns && (
2053 hasClass(ns, "docblock") ||
2054 hasClass(ns, "stability"))) {
2055 if (addOrRemove) {
2056 addClass(ns, "hidden-by-impl-hider");
2057 } else {
2058 removeClass(ns, "hidden-by-impl-hider");
2059 }
2060 ns = ns.nextElementSibling;
2061 continue;
2062 }
2063 break;
2064 }
2065 }
2066 };
2067 }
0531ce1d 2068
0731742a
XL
2069 var relatedDoc;
2070 var action = mode;
2071 if (hasClass(toggle.parentNode, "impl") === false) {
2072 relatedDoc = toggle.parentNode.nextElementSibling;
0531ce1d
XL
2073 if (hasClass(relatedDoc, "stability")) {
2074 relatedDoc = relatedDoc.nextElementSibling;
2075 }
a1dfa0c6 2076 if (hasClass(relatedDoc, "docblock") || hasClass(relatedDoc, "sub-variant")) {
0731742a 2077 if (mode === "toggle") {
0531ce1d
XL
2078 if (hasClass(relatedDoc, "hidden-by-usual-hider")) {
2079 action = "show";
2080 } else {
2081 action = "hide";
7cac9316 2082 }
0531ce1d
XL
2083 }
2084 if (action === "hide") {
2085 addClass(relatedDoc, "hidden-by-usual-hider");
0731742a
XL
2086 onEachLazy(toggle.childNodes, adjustToggle(true));
2087 addClass(toggle.parentNode, "collapsed");
0531ce1d
XL
2088 } else if (action === "show") {
2089 removeClass(relatedDoc, "hidden-by-usual-hider");
0731742a
XL
2090 removeClass(toggle.parentNode, "collapsed");
2091 onEachLazy(toggle.childNodes, adjustToggle(false));
0531ce1d
XL
2092 }
2093 }
2094 } else {
9fa01778 2095 // we are collapsing the impl block(s).
0531ce1d 2096
83c7162d 2097 var parentElem = toggle.parentNode;
0731742a 2098 relatedDoc = parentElem;
0531ce1d
XL
2099 var docblock = relatedDoc.nextElementSibling;
2100
0731742a 2101 while (hasClass(relatedDoc, "impl-items") === false) {
0531ce1d
XL
2102 relatedDoc = relatedDoc.nextElementSibling;
2103 }
2104
0731742a
XL
2105 if ((!relatedDoc && hasClass(docblock, "docblock") === false) ||
2106 (pageId && document.getElementById(pageId))) {
0531ce1d
XL
2107 return;
2108 }
2109
9fa01778 2110 // Hide all functions, but not associated types/consts.
0531ce1d 2111
0731742a 2112 if (mode === "toggle") {
0531ce1d 2113 if (hasClass(relatedDoc, "fns-now-collapsed") ||
0731742a 2114 hasClass(docblock, "hidden-by-impl-hider")) {
0531ce1d
XL
2115 action = "show";
2116 } else {
2117 action = "hide";
2118 }
2119 }
2120
9fa01778 2121 var dontApplyBlockRule = toggle.parentNode.parentNode.id !== "main";
0531ce1d
XL
2122 if (action === "show") {
2123 removeClass(relatedDoc, "fns-now-collapsed");
2124 removeClass(docblock, "hidden-by-usual-hider");
9fa01778
XL
2125 onEachLazy(toggle.childNodes, adjustToggle(false, dontApplyBlockRule));
2126 onEachLazy(relatedDoc.childNodes, implHider(false, dontApplyBlockRule));
0531ce1d
XL
2127 } else if (action === "hide") {
2128 addClass(relatedDoc, "fns-now-collapsed");
2129 addClass(docblock, "hidden-by-usual-hider");
9fa01778
XL
2130 onEachLazy(toggle.childNodes, adjustToggle(true, dontApplyBlockRule));
2131 onEachLazy(relatedDoc.childNodes, implHider(true, dontApplyBlockRule));
0731742a
XL
2132 }
2133 }
2134 }
2135
2136 function collapser(e, collapse) {
2137 // inherent impl ids are like "impl" or impl-<number>'.
2138 // they will never be hidden by default.
2139 var n = e.parentElement;
2140 if (n.id.match(/^impl(?:-\d+)?$/) === null) {
2141 // Automatically minimize all non-inherent impls
2142 if (collapse || hasClass(n, "impl")) {
2143 collapseDocs(e, "hide", pageId);
0531ce1d
XL
2144 }
2145 }
2146 }
2147
94b46f34
XL
2148 function autoCollapse(pageId, collapse) {
2149 if (collapse) {
2150 toggleAllDocs(pageId, true);
60c5eb7d 2151 } else if (getCurrentValue("rustdoc-auto-hide-trait-implementations") !== "false") {
0731742a 2152 var impl_list = document.getElementById("implementations-list");
0bf4aa26
XL
2153
2154 if (impl_list !== null) {
0731742a
XL
2155 onEachLazy(impl_list.getElementsByClassName("collapse-toggle"), function(e) {
2156 collapser(e, collapse);
b7449926
XL
2157 });
2158 }
532ac7d7
XL
2159
2160 var blanket_list = document.getElementById("blanket-implementations-list");
2161
2162 if (blanket_list !== null) {
2163 onEachLazy(blanket_list.getElementsByClassName("collapse-toggle"), function(e) {
2164 collapser(e, collapse);
2165 });
2166 }
8faf50e0 2167 }
476ff2be
SL
2168 }
2169
0731742a
XL
2170 var toggles = document.getElementById("toggle-all-docs");
2171 if (toggles) {
2172 toggles.onclick = toggleAllDocs;
7cac9316 2173 }
476ff2be 2174
7cac9316
XL
2175 function insertAfter(newNode, referenceNode) {
2176 referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
2177 }
1a4d82fc 2178
0731742a
XL
2179 function createSimpleToggle(sectionIsCollapsed) {
2180 var toggle = document.createElement("a");
2181 toggle.href = "javascript:void(0)";
2182 toggle.className = "collapse-toggle";
2183 toggle.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(sectionIsCollapsed) +
2184 "</span>]";
2185 return toggle;
0531ce1d
XL
2186 }
2187
0731742a 2188 var toggle = createSimpleToggle(false);
60c5eb7d 2189 var hideMethodDocs = getCurrentValue("rustdoc-auto-hide-method-docs") === "true";
532ac7d7 2190 var pageId = getPageId();
1a4d82fc 2191
7cac9316
XL
2192 var func = function(e) {
2193 var next = e.nextElementSibling;
0731742a
XL
2194 if (!next) {
2195 return;
2196 }
532ac7d7
XL
2197 if (hasClass(next, "docblock") === true ||
2198 (hasClass(next, "stability") === true &&
2199 hasClass(next.nextElementSibling, "docblock") === true)) {
2200 var newToggle = toggle.cloneNode(true);
2201 insertAfter(newToggle, e.childNodes[e.childNodes.length - 1]);
2202 if (hideMethodDocs === true && hasClass(e, "method") === true) {
2203 collapseDocs(newToggle, "hide", pageId);
2204 }
0731742a
XL
2205 }
2206 };
2207
2208 var funcImpl = function(e) {
2209 var next = e.nextElementSibling;
2210 if (next && hasClass(next, "docblock")) {
0531ce1d
XL
2211 next = next.nextElementSibling;
2212 }
7cac9316
XL
2213 if (!next) {
2214 return;
2215 }
0731742a 2216 if (next.getElementsByClassName("method").length > 0 && hasClass(e, "impl")) {
7cac9316
XL
2217 insertAfter(toggle.cloneNode(true), e.childNodes[e.childNodes.length - 1]);
2218 }
94b46f34 2219 };
0731742a
XL
2220
2221 onEachLazy(document.getElementsByClassName("method"), func);
2222 onEachLazy(document.getElementsByClassName("associatedconstant"), func);
2223 onEachLazy(document.getElementsByClassName("impl"), funcImpl);
2224 var impl_call = function() {};
532ac7d7 2225 if (hideMethodDocs === true) {
0731742a
XL
2226 impl_call = function(e, newToggle, pageId) {
2227 if (e.id.match(/^impl(?:-\d+)?$/) === null) {
2228 // Automatically minimize all non-inherent impls
532ac7d7 2229 if (hasClass(e, "impl") === true) {
0731742a
XL
2230 collapseDocs(newToggle, "hide", pageId);
2231 }
2232 }
2233 };
2234 }
0731742a
XL
2235 var newToggle = document.createElement("a");
2236 newToggle.href = "javascript:void(0)";
2237 newToggle.className = "collapse-toggle hidden-default collapsed";
2238 newToggle.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(true) +
2239 "</span>] Show hidden undocumented items";
2240 function toggleClicked() {
2241 if (hasClass(this, "collapsed")) {
2242 removeClass(this, "collapsed");
2243 onEachLazy(this.parentNode.getElementsByClassName("hidden"), function(x) {
2244 if (hasClass(x, "content") === false) {
2245 removeClass(x, "hidden");
2246 addClass(x, "x");
2247 }
2248 }, true);
2249 this.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(false) +
2250 "</span>] Hide undocumented items";
2251 } else {
2252 addClass(this, "collapsed");
2253 onEachLazy(this.parentNode.getElementsByClassName("x"), function(x) {
2254 if (hasClass(x, "content") === false) {
2255 addClass(x, "hidden");
2256 removeClass(x, "x");
2257 }
2258 }, true);
2259 this.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(true) +
2260 "</span>] Show hidden undocumented items";
2261 }
2262 }
2263 onEachLazy(document.getElementsByClassName("impl-items"), function(e) {
2264 onEachLazy(e.getElementsByClassName("associatedconstant"), func);
2265 var hiddenElems = e.getElementsByClassName("hidden");
a1dfa0c6
XL
2266 var needToggle = false;
2267
0731742a
XL
2268 var hlength = hiddenElems.length;
2269 for (var i = 0; i < hlength; ++i) {
a1dfa0c6
XL
2270 if (hasClass(hiddenElems[i], "content") === false &&
2271 hasClass(hiddenElems[i], "docblock") === false) {
2272 needToggle = true;
2273 break;
2274 }
2275 }
2276 if (needToggle === true) {
0731742a
XL
2277 var inner_toggle = newToggle.cloneNode(true);
2278 inner_toggle.onclick = toggleClicked;
2279 e.insertBefore(inner_toggle, e.firstChild);
532ac7d7 2280 impl_call(e.previousSibling, inner_toggle, pageId);
a1dfa0c6
XL
2281 }
2282 });
1a4d82fc 2283
b7449926 2284 function createToggle(otherMessage, fontSize, extraClass, show) {
0731742a
XL
2285 var span = document.createElement("span");
2286 span.className = "toggle-label";
b7449926 2287 if (show) {
0731742a 2288 span.style.display = "none";
b7449926 2289 }
0531ce1d 2290 if (!otherMessage) {
0731742a 2291 span.innerHTML = "&nbsp;Expand&nbsp;description";
0531ce1d
XL
2292 } else {
2293 span.innerHTML = otherMessage;
8faf50e0
XL
2294 }
2295
2296 if (fontSize) {
2297 span.style.fontSize = fontSize;
0531ce1d 2298 }
476ff2be 2299
041b39d2
XL
2300 var mainToggle = toggle.cloneNode(true);
2301 mainToggle.appendChild(span);
1a4d82fc 2302
0731742a
XL
2303 var wrapper = document.createElement("div");
2304 wrapper.className = "toggle-wrapper";
b7449926 2305 if (!show) {
0731742a
XL
2306 addClass(wrapper, "collapsed");
2307 var inner = mainToggle.getElementsByClassName("inner");
b7449926 2308 if (inner && inner.length > 0) {
0731742a 2309 inner[0].innerHTML = "+";
b7449926
XL
2310 }
2311 }
94b46f34 2312 if (extraClass) {
b7449926 2313 addClass(wrapper, extraClass);
94b46f34 2314 }
041b39d2
XL
2315 wrapper.appendChild(mainToggle);
2316 return wrapper;
2317 }
1a4d82fc 2318
60c5eb7d
XL
2319 var currentType = document.getElementsByClassName("type-decl")[0];
2320 var className = null;
2321 if (currentType) {
2322 currentType = currentType.getElementsByClassName("rust")[0];
2323 if (currentType) {
2324 currentType.classList.forEach(function(item) {
2325 if (item !== "main") {
2326 className = item;
2327 return true;
2328 }
2329 });
2330 }
2331 }
2332 var showItemDeclarations = getCurrentValue("rustdoc-auto-hide-" + className);
2333 if (showItemDeclarations === null) {
2334 if (className === "enum" || className === "macro") {
2335 showItemDeclarations = "false";
2336 } else if (className === "struct" || className === "union" || className === "trait") {
2337 showItemDeclarations = "true";
2338 } else {
2339 // In case we found an unknown type, we just use the "parent" value.
2340 showItemDeclarations = getCurrentValue("rustdoc-auto-hide-declarations");
2341 }
2342 }
2343 showItemDeclarations = showItemDeclarations === "false";
a1dfa0c6 2344 function buildToggleWrapper(e) {
0731742a 2345 if (hasClass(e, "autohide")) {
7cac9316 2346 var wrap = e.previousElementSibling;
0731742a
XL
2347 if (wrap && hasClass(wrap, "toggle-wrapper")) {
2348 var inner_toggle = wrap.childNodes[0];
2349 var extra = e.childNodes[0].tagName === "H3";
a1dfa0c6 2350
0731742a
XL
2351 e.style.display = "none";
2352 addClass(wrap, "collapsed");
2353 onEachLazy(inner_toggle.getElementsByClassName("inner"), function(e) {
7cac9316
XL
2354 e.innerHTML = labelForToggleButton(true);
2355 });
0731742a
XL
2356 onEachLazy(inner_toggle.getElementsByClassName("toggle-label"), function(e) {
2357 e.style.display = "inline-block";
83c7162d
XL
2358 if (extra === true) {
2359 i_e.innerHTML = " Show " + e.childNodes[0].innerHTML;
2360 }
7cac9316 2361 });
1a4d82fc 2362 }
7cac9316 2363 }
83c7162d 2364 if (e.parentNode.id === "main") {
0731742a 2365 var otherMessage = "";
8faf50e0 2366 var fontSize;
94b46f34 2367 var extraClass;
8faf50e0 2368
83c7162d 2369 if (hasClass(e, "type-decl")) {
8faf50e0 2370 fontSize = "20px";
0731742a 2371 otherMessage = "&nbsp;Show&nbsp;declaration";
a1dfa0c6 2372 if (showItemDeclarations === false) {
0731742a 2373 extraClass = "collapsed";
b7449926 2374 }
a1dfa0c6 2375 } else if (hasClass(e, "sub-variant")) {
0731742a 2376 otherMessage = "&nbsp;Show&nbsp;fields";
8faf50e0 2377 } else if (hasClass(e, "non-exhaustive")) {
0731742a 2378 otherMessage = "&nbsp;This&nbsp;";
8faf50e0 2379 if (hasClass(e, "non-exhaustive-struct")) {
0731742a 2380 otherMessage += "struct";
8faf50e0 2381 } else if (hasClass(e, "non-exhaustive-enum")) {
0731742a 2382 otherMessage += "enum";
532ac7d7
XL
2383 } else if (hasClass(e, "non-exhaustive-variant")) {
2384 otherMessage += "enum variant";
8faf50e0 2385 } else if (hasClass(e, "non-exhaustive-type")) {
0731742a 2386 otherMessage += "type";
8faf50e0 2387 }
0731742a 2388 otherMessage += "&nbsp;is&nbsp;marked&nbsp;as&nbsp;non-exhaustive";
94b46f34
XL
2389 } else if (hasClass(e.childNodes[0], "impl-items")) {
2390 extraClass = "marg-left";
83c7162d 2391 }
8faf50e0 2392
a1dfa0c6
XL
2393 e.parentNode.insertBefore(
2394 createToggle(otherMessage,
2395 fontSize,
2396 extraClass,
2397 hasClass(e, "type-decl") === false || showItemDeclarations === true),
2398 e);
2399 if (hasClass(e, "type-decl") === true && showItemDeclarations === true) {
83c7162d
XL
2400 collapseDocs(e.previousSibling.childNodes[0], "toggle");
2401 }
532ac7d7
XL
2402 if (hasClass(e, "non-exhaustive") === true) {
2403 collapseDocs(e.previousSibling.childNodes[0], "toggle");
2404 }
83c7162d 2405 }
a1dfa0c6
XL
2406 }
2407
0731742a
XL
2408 onEachLazy(document.getElementsByClassName("docblock"), buildToggleWrapper);
2409 onEachLazy(document.getElementsByClassName("sub-variant"), buildToggleWrapper);
7cac9316 2410
0731742a
XL
2411 function createToggleWrapper(tog) {
2412 var span = document.createElement("span");
2413 span.className = "toggle-label";
2414 span.style.display = "none";
2415 span.innerHTML = "&nbsp;Expand&nbsp;attributes";
2416 tog.appendChild(span);
2417
2418 var wrapper = document.createElement("div");
2419 wrapper.className = "toggle-wrapper toggle-attributes";
2420 wrapper.appendChild(tog);
2421 return wrapper;
2422 }
2423
a1dfa0c6
XL
2424 // To avoid checking on "rustdoc-item-attributes" value on every loop...
2425 var itemAttributesFunc = function() {};
60c5eb7d 2426 if (getCurrentValue("rustdoc-auto-hide-attributes") !== "false") {
a1dfa0c6
XL
2427 itemAttributesFunc = function(x) {
2428 collapseDocs(x.previousSibling.childNodes[0], "toggle");
2429 };
2430 }
0731742a
XL
2431 var attributesToggle = createToggleWrapper(createSimpleToggle(false));
2432 onEachLazy(main.getElementsByClassName("attributes"), function(i_e) {
48663c56
XL
2433 var attr_tog = attributesToggle.cloneNode(true);
2434 if (hasClass(i_e, "top-attr") === true) {
2435 addClass(attr_tog, "top-attr");
2436 }
2437 i_e.parentNode.insertBefore(attr_tog, i_e);
a1dfa0c6 2438 itemAttributesFunc(i_e);
7cac9316 2439 });
ea8adc8c 2440
a1dfa0c6
XL
2441 // To avoid checking on "rustdoc-line-numbers" value on every loop...
2442 var lineNumbersFunc = function() {};
2443 if (getCurrentValue("rustdoc-line-numbers") === "true") {
2444 lineNumbersFunc = function(x) {
0731742a 2445 var count = x.textContent.split("\n").length;
a1dfa0c6
XL
2446 var elems = [];
2447 for (var i = 0; i < count; ++i) {
2448 elems.push(i + 1);
2449 }
0731742a
XL
2450 var node = document.createElement("pre");
2451 addClass(node, "line-number");
2452 node.innerHTML = elems.join("\n");
a1dfa0c6
XL
2453 x.parentNode.insertBefore(node, x);
2454 };
2455 }
0731742a
XL
2456 onEachLazy(document.getElementsByClassName("rust-example-rendered"), function(e) {
2457 if (hasClass(e, "compile_fail")) {
ea8adc8c 2458 e.addEventListener("mouseover", function(event) {
0731742a 2459 this.parentElement.previousElementSibling.childNodes[0].style.color = "#f00";
ea8adc8c
XL
2460 });
2461 e.addEventListener("mouseout", function(event) {
0731742a 2462 this.parentElement.previousElementSibling.childNodes[0].style.color = "";
ea8adc8c 2463 });
0731742a 2464 } else if (hasClass(e, "ignore")) {
ea8adc8c 2465 e.addEventListener("mouseover", function(event) {
0731742a 2466 this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200";
ea8adc8c
XL
2467 });
2468 e.addEventListener("mouseout", function(event) {
0731742a 2469 this.parentElement.previousElementSibling.childNodes[0].style.color = "";
ea8adc8c
XL
2470 });
2471 }
a1dfa0c6 2472 lineNumbersFunc(e);
ea8adc8c 2473 });
abe05a73 2474
ff7c6d11 2475 function showModal(content) {
0731742a 2476 var modal = document.createElement("div");
ff7c6d11 2477 modal.id = "important";
0731742a
XL
2478 addClass(modal, "modal");
2479 modal.innerHTML = "<div class=\"modal-content\"><div class=\"close\" id=\"modal-close\">✕" +
2480 "</div><div class=\"whiter\"></div><span class=\"docblock\">" + content +
2481 "</span></div>";
2482 document.getElementsByTagName("body")[0].appendChild(modal);
2483 document.getElementById("modal-close").onclick = hideModal;
ff7c6d11
XL
2484 modal.onclick = hideModal;
2485 }
2486
2487 function hideModal() {
2488 var modal = document.getElementById("important");
2489 if (modal) {
2490 modal.parentNode.removeChild(modal);
2491 }
2492 }
2493
0731742a 2494 onEachLazy(document.getElementsByClassName("important-traits"), function(e) {
ff7c6d11
XL
2495 e.onclick = function() {
2496 showModal(e.lastElementChild.innerHTML);
2497 };
2498 });
2499
532ac7d7
XL
2500 // In the search display, allows to switch between tabs.
2501 function printTab(nb) {
2502 if (nb === 0 || nb === 1 || nb === 2) {
2503 currentTab = nb;
2504 }
2505 var nb_copy = nb;
2506 onEachLazy(document.getElementById("titles").childNodes, function(elem) {
2507 if (nb_copy === 0) {
2508 addClass(elem, "selected");
2509 } else {
2510 removeClass(elem, "selected");
2511 }
2512 nb_copy -= 1;
2513 });
2514 onEachLazy(document.getElementById("results").childNodes, function(elem) {
2515 if (nb === 0) {
2516 elem.style.display = "";
2517 } else {
2518 elem.style.display = "none";
2519 }
2520 nb -= 1;
2521 });
2522 }
2523
83c7162d
XL
2524 function putBackSearch(search_input) {
2525 if (search_input.value !== "") {
0731742a 2526 addClass(main, "hidden");
e74abb32 2527 removeClass(getSearchElement(), "hidden");
83c7162d
XL
2528 if (browserSupportsHistoryApi()) {
2529 history.replaceState(search_input.value,
2530 "",
2531 "?search=" + encodeURIComponent(search_input.value));
2532 }
2533 }
2534 }
abe05a73
XL
2535
2536 if (search_input) {
2537 search_input.onfocus = function() {
83c7162d 2538 putBackSearch(this);
abe05a73
XL
2539 };
2540 }
ff7c6d11
XL
2541
2542 var params = getQueryStringParams();
2543 if (params && params.search) {
0731742a 2544 addClass(main, "hidden");
e1599b0c 2545 var search = getSearchElement();
ff7c6d11 2546 removeClass(search, "hidden");
0731742a 2547 search.innerHTML = "<h3 style=\"text-align: center;\">Loading search results...</h3>";
ff7c6d11
XL
2548 }
2549
2550 var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
2551 if (sidebar_menu) {
2552 sidebar_menu.onclick = function() {
0731742a 2553 var sidebar = document.getElementsByClassName("sidebar")[0];
ff7c6d11
XL
2554 if (hasClass(sidebar, "mobile") === true) {
2555 hideSidebar();
2556 } else {
2557 showSidebar();
2558 }
2559 };
2560 }
2561
2562 window.onresize = function() {
2563 hideSidebar();
2564 };
0531ce1d 2565
94b46f34 2566 autoCollapse(getPageId(), getCurrentValue("rustdoc-collapse") === "true");
b7449926
XL
2567
2568 if (window.location.hash && window.location.hash.length > 0) {
0731742a 2569 expandSection(window.location.hash.replace(/^#/, ""));
b7449926 2570 }
0731742a
XL
2571
2572 if (main) {
2573 onEachLazy(main.getElementsByClassName("loading-content"), function(e) {
2574 e.remove();
2575 });
2576 onEachLazy(main.childNodes, function(e) {
2577 // Unhide the actual content once loading is complete. Headers get
2578 // flex treatment for their horizontal layout, divs get block treatment
2579 // for vertical layout (column-oriented flex layout for divs caused
2580 // errors in mobile browsers).
2581 if (e.tagName === "H2" || e.tagName === "H3") {
9fa01778 2582 var nextTagName = e.nextElementSibling.tagName;
0731742a
XL
2583 if (nextTagName == "H2" || nextTagName == "H3") {
2584 e.nextElementSibling.style.display = "flex";
2585 } else {
2586 e.nextElementSibling.style.display = "block";
2587 }
2588 }
2589 });
2590 }
2591
2592 function addSearchOptions(crates) {
e1599b0c 2593 var elem = document.getElementById("crate-search");
0731742a
XL
2594
2595 if (!elem) {
2596 return;
2597 }
2598 var crates_text = [];
2599 if (Object.keys(crates).length > 1) {
2600 for (var crate in crates) {
2601 if (crates.hasOwnProperty(crate)) {
2602 crates_text.push(crate);
2603 }
2604 }
2605 }
2606 crates_text.sort(function(a, b) {
2607 var lower_a = a.toLowerCase();
2608 var lower_b = b.toLowerCase();
2609
2610 if (lower_a < lower_b) {
2611 return -1;
2612 } else if (lower_a > lower_b) {
2613 return 1;
2614 }
2615 return 0;
2616 });
60c5eb7d 2617 var savedCrate = getCurrentValue("rustdoc-saved-filter-crate");
0731742a
XL
2618 for (var i = 0; i < crates_text.length; ++i) {
2619 var option = document.createElement("option");
2620 option.value = crates_text[i];
2621 option.innerText = crates_text[i];
2622 elem.appendChild(option);
60c5eb7d
XL
2623 // Set the crate filter from saved storage, if the current page has the saved crate
2624 // filter.
2625 //
2626 // If not, ignore the crate filter -- we want to support filtering for crates on sites
2627 // like doc.rust-lang.org where the crates may differ from page to page while on the
2628 // same domain.
2629 if (crates_text[i] === savedCrate) {
2630 elem.value = savedCrate;
2631 }
0731742a 2632 }
60c5eb7d
XL
2633
2634 if (search_input) {
2635 search_input.removeAttribute('disabled');
2636 };
0731742a
XL
2637 }
2638
2639 window.addSearchOptions = addSearchOptions;
e74abb32
XL
2640
2641 function buildHelperPopup() {
2642 var popup = document.createElement("aside");
2643 addClass(popup, "hidden");
2644 popup.id = "help";
2645
2646 var container = document.createElement("div");
2647 var shortcuts = [
2648 ["?", "Show this help dialog"],
2649 ["S", "Focus the search field"],
2650 ["↑", "Move up in search results"],
2651 ["↓", "Move down in search results"],
2652 ["↹", "Switch tab"],
2653 ["&#9166;", "Go to active search result"],
2654 ["+", "Expand all sections"],
2655 ["-", "Collapse all sections"],
2656 ].map(x => "<dt><kbd>" + x[0] + "</kbd></dt><dd>" + x[1] + "</dd>").join("");
2657 var div_shortcuts = document.createElement("div");
2658 addClass(div_shortcuts, "shortcuts");
2659 div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
2660
2661 var infos = [
2662 "Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
2663 restrict the search to a given type.",
2664 "Accepted types are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
2665 <code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, \
2666 and <code>const</code>.",
2667 "Search functions by type signature (e.g., <code>vec -> usize</code> or \
2668 <code>* -> vec</code>)",
2669 "Search multiple things at once by splitting your query with comma (e.g., \
2670 <code>str,u8</code> or <code>String,struct:Vec,test</code>)",
2671 "You can look for items with an exact name by putting double quotes around \
2672 your request: <code>\"string\"</code>",
2673 "Look for items inside another one by searching for a path: <code>vec::Vec</code>",
2674 ].map(x => "<p>" + x + "</p>").join("");
2675 var div_infos = document.createElement("div");
2676 addClass(div_infos, "infos");
2677 div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
2678
2679 container.appendChild(div_shortcuts);
2680 container.appendChild(div_infos);
2681
2682 popup.appendChild(container);
2683 insertAfter(popup, getSearchElement());
2684 }
2685
60c5eb7d
XL
2686 onHashChange(null);
2687 window.onhashchange = onHashChange;
2688
e74abb32 2689 buildHelperPopup();
1a4d82fc 2690}());
c1a9b12d
SL
2691
2692// Sets the focus on the search bar at the top of the page
2693function focusSearchBar() {
e1599b0c 2694 getSearchInput().focus();
c1a9b12d 2695}
2c00a5a8
XL
2696
2697// Removes the focus from the search bar
2698function defocusSearchBar() {
e1599b0c 2699 getSearchInput().blur();
2c00a5a8 2700}