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