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