PageRenderTime 62ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/librustdoc/html/static/main.js

http://github.com/eholk/rust
JavaScript | 1294 lines | 1025 code | 125 blank | 144 comment | 247 complexity | f46cf4a5ea7ab5adfaa31249ce93a407 MD5 | raw file
Possible License(s): AGPL-1.0, BSD-2-Clause, 0BSD, Apache-2.0, MIT, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
  2. // file at the top-level directory of this distribution and at
  3. // http://rust-lang.org/COPYRIGHT.
  4. //
  5. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  6. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  7. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  8. // option. This file may not be copied, modified, or distributed
  9. // except according to those terms.
  10. /*jslint browser: true, es5: true */
  11. /*globals $: true, rootPath: true */
  12. (function() {
  13. "use strict";
  14. // This mapping table should match the discriminants of
  15. // `rustdoc::html::item_type::ItemType` type in Rust.
  16. var itemTypes = ["mod",
  17. "externcrate",
  18. "import",
  19. "struct",
  20. "enum",
  21. "fn",
  22. "type",
  23. "static",
  24. "trait",
  25. "impl",
  26. "tymethod",
  27. "method",
  28. "structfield",
  29. "variant",
  30. "macro",
  31. "primitive",
  32. "associatedtype",
  33. "constant",
  34. "associatedconstant",
  35. "union"];
  36. function hasClass(elem, className) {
  37. if (elem && className && elem.className) {
  38. var elemClass = elem.className;
  39. var start = elemClass.indexOf(className);
  40. if (start == -1) {
  41. return false;
  42. } else if (elemClass.length == className.length) {
  43. return true;
  44. } else {
  45. if (start > 0 && elemClass[start - 1] != ' ') {
  46. return false;
  47. }
  48. var end = start + className.length;
  49. if (end < elemClass.length && elemClass[end] != ' ') {
  50. return false;
  51. }
  52. return true;
  53. }
  54. }
  55. return false;
  56. }
  57. function addClass(elem, className) {
  58. if (elem && className && !hasClass(elem, className)) {
  59. if (elem.className && elem.className.length > 0) {
  60. elem.className += ' ' + className;
  61. } else {
  62. elem.className = className;
  63. }
  64. }
  65. }
  66. function removeClass(elem, className) {
  67. if (elem && className && elem.className) {
  68. elem.className = (" " + elem.className + " ").replace(" " + className + " ", " ")
  69. .trim();
  70. }
  71. }
  72. function onEach(arr, func) {
  73. if (arr && arr.length > 0 && func) {
  74. for (var i = 0; i < arr.length; i++) {
  75. func(arr[i]);
  76. }
  77. }
  78. }
  79. function isHidden(elem) {
  80. return (elem.offsetParent === null)
  81. }
  82. // used for special search precedence
  83. var TY_PRIMITIVE = itemTypes.indexOf("primitive");
  84. onEach(document.getElementsByClassName('js-only'), function(e) {
  85. removeClass(e, 'js-only');
  86. });
  87. function getQueryStringParams() {
  88. var params = {};
  89. window.location.search.substring(1).split("&").
  90. map(function(s) {
  91. var pair = s.split("=");
  92. params[decodeURIComponent(pair[0])] =
  93. typeof pair[1] === "undefined" ?
  94. null : decodeURIComponent(pair[1]);
  95. });
  96. return params;
  97. }
  98. function browserSupportsHistoryApi() {
  99. return document.location.protocol != "file:" &&
  100. window.history && typeof window.history.pushState === "function";
  101. }
  102. function highlightSourceLines(ev) {
  103. var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
  104. if (match) {
  105. from = parseInt(match[1], 10);
  106. to = Math.min(50000, parseInt(match[2] || match[1], 10));
  107. from = Math.min(from, to);
  108. var elem = document.getElementById(from);
  109. if (!elem) {
  110. return;
  111. }
  112. if (ev === null) {
  113. var x = document.getElementById(from);
  114. if (x) {
  115. x.scrollIntoView();
  116. }
  117. };
  118. onEach(document.getElementsByClassName('line-numbers'), function(e) {
  119. onEach(e.getElementsByTagName('span'), function(i_e) {
  120. removeClass(i_e, 'line-highlighted');
  121. });
  122. })
  123. for (i = from; i <= to; ++i) {
  124. addClass(document.getElementById(i), 'line-highlighted');
  125. }
  126. }
  127. }
  128. highlightSourceLines(null);
  129. window.onhashchange = highlightSourceLines;
  130. // Gets the human-readable string for the virtual-key code of the
  131. // given KeyboardEvent, ev.
  132. //
  133. // This function is meant as a polyfill for KeyboardEvent#key,
  134. // since it is not supported in Trident. We also test for
  135. // KeyboardEvent#keyCode because the handleShortcut handler is
  136. // also registered for the keydown event, because Blink doesn't fire
  137. // keypress on hitting the Escape key.
  138. //
  139. // So I guess you could say things are getting pretty interoperable.
  140. function getVirtualKey(ev) {
  141. if ("key" in ev && typeof ev.key != "undefined")
  142. return ev.key;
  143. var c = ev.charCode || ev.keyCode;
  144. if (c == 27)
  145. return "Escape";
  146. return String.fromCharCode(c);
  147. }
  148. function handleShortcut(ev) {
  149. if (document.activeElement.tagName === "INPUT")
  150. return;
  151. // Don't interfere with browser shortcuts
  152. if (ev.ctrlKey || ev.altKey || ev.metaKey)
  153. return;
  154. var help = document.getElementById("help");
  155. switch (getVirtualKey(ev)) {
  156. case "Escape":
  157. var search = document.getElementById("search");
  158. if (!hasClass(help, "hidden")) {
  159. ev.preventDefault();
  160. addClass(help, "hidden");
  161. removeClass(document.body, "blur");
  162. } else if (!hasClass(search, "hidden")) {
  163. ev.preventDefault();
  164. addClass(search, "hidden");
  165. removeClass(document.getElementById("main"), "hidden");
  166. }
  167. break;
  168. case "s":
  169. case "S":
  170. ev.preventDefault();
  171. focusSearchBar();
  172. break;
  173. case "+":
  174. ev.preventDefault();
  175. toggleAllDocs();
  176. break;
  177. case "?":
  178. if (ev.shiftKey && hasClass(help, "hidden")) {
  179. ev.preventDefault();
  180. removeClass(help, "hidden");
  181. addClass(document.body, "blur");
  182. }
  183. break;
  184. }
  185. }
  186. document.onkeypress = handleShortcut;
  187. document.onkeydown = handleShortcut;
  188. document.onclick = function(ev) {
  189. if (hasClass(ev.target, 'collapse-toggle')) {
  190. collapseDocs(ev.target);
  191. } else if (hasClass(ev.target.parentNode, 'collapse-toggle')) {
  192. collapseDocs(ev.target.parentNode);
  193. } else if (ev.target.tagName === 'SPAN' && hasClass(ev.target.parentNode, 'line-numbers')) {
  194. var prev_id = 0;
  195. function set_fragment(name) {
  196. if (browserSupportsHistoryApi()) {
  197. history.replaceState(null, null, '#' + name);
  198. window.hashchange();
  199. } else {
  200. location.replace('#' + name);
  201. }
  202. }
  203. var cur_id = parseInt(ev.target.id, 10);
  204. if (ev.shiftKey && prev_id) {
  205. if (prev_id > cur_id) {
  206. var tmp = prev_id;
  207. prev_id = cur_id;
  208. cur_id = tmp;
  209. }
  210. set_fragment(prev_id + '-' + cur_id);
  211. } else {
  212. prev_id = cur_id;
  213. set_fragment(cur_id);
  214. }
  215. } else if (!hasClass(document.getElementById("help"), "hidden")) {
  216. addClass(document.getElementById("help"), "hidden");
  217. removeClass(document.body, "blur");
  218. }
  219. };
  220. var x = document.getElementsByClassName('version-selector');
  221. if (x.length > 0) {
  222. x[0].onchange = function() {
  223. var i, match,
  224. url = document.location.href,
  225. stripped = '',
  226. len = rootPath.match(/\.\.\//g).length + 1;
  227. for (i = 0; i < len; ++i) {
  228. match = url.match(/\/[^\/]*$/);
  229. if (i < len - 1) {
  230. stripped = match[0] + stripped;
  231. }
  232. url = url.substring(0, url.length - match[0].length);
  233. }
  234. url += '/' + document.getElementsByClassName('version-selector')[0].value + stripped;
  235. document.location.href = url;
  236. };
  237. }
  238. /**
  239. * A function to compute the Levenshtein distance between two strings
  240. * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
  241. * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode
  242. * This code is an unmodified version of the code written by Marco de Wit
  243. * and was found at http://stackoverflow.com/a/18514751/745719
  244. */
  245. var levenshtein = (function() {
  246. var row2 = [];
  247. return function(s1, s2) {
  248. if (s1 === s2) {
  249. return 0;
  250. }
  251. var s1_len = s1.length, s2_len = s2.length;
  252. if (s1_len && s2_len) {
  253. var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
  254. while (i1 < s1_len) {
  255. row[i1] = ++i1;
  256. }
  257. while (i2 < s2_len) {
  258. c2 = s2.charCodeAt(i2);
  259. a = i2;
  260. ++i2;
  261. b = i2;
  262. for (i1 = 0; i1 < s1_len; ++i1) {
  263. c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
  264. a = row[i1];
  265. b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
  266. row[i1] = b;
  267. }
  268. }
  269. return b;
  270. }
  271. return s1_len + s2_len;
  272. };
  273. })();
  274. function initSearch(rawSearchIndex) {
  275. var currentResults, index, searchIndex;
  276. var MAX_LEV_DISTANCE = 3;
  277. var params = getQueryStringParams();
  278. // Populate search bar with query string search term when provided,
  279. // but only if the input bar is empty. This avoid the obnoxious issue
  280. // where you start trying to do a search, and the index loads, and
  281. // suddenly your search is gone!
  282. if (document.getElementsByClassName("search-input")[0].value === "") {
  283. document.getElementsByClassName("search-input")[0].value = params.search || '';
  284. }
  285. /**
  286. * Executes the query and builds an index of results
  287. * @param {[Object]} query [The user query]
  288. * @param {[type]} max [The maximum results returned]
  289. * @param {[type]} searchWords [The list of search words to query
  290. * against]
  291. * @return {[type]} [A search index of results]
  292. */
  293. function execQuery(query, max, searchWords) {
  294. var valLower = query.query.toLowerCase(),
  295. val = valLower,
  296. typeFilter = itemTypeFromName(query.type),
  297. results = [],
  298. split = valLower.split("::");
  299. // remove empty keywords
  300. for (var j = 0; j < split.length; ++j) {
  301. split[j].toLowerCase();
  302. if (split[j] === "") {
  303. split.splice(j, 1);
  304. }
  305. }
  306. function typePassesFilter(filter, type) {
  307. // No filter
  308. if (filter < 0) return true;
  309. // Exact match
  310. if (filter === type) return true;
  311. // Match related items
  312. var name = itemTypes[type];
  313. switch (itemTypes[filter]) {
  314. case "constant":
  315. return (name == "associatedconstant");
  316. case "fn":
  317. return (name == "method" || name == "tymethod");
  318. case "type":
  319. return (name == "primitive");
  320. }
  321. // No match
  322. return false;
  323. }
  324. // quoted values mean literal search
  325. var nSearchWords = searchWords.length;
  326. if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
  327. val.charAt(val.length - 1) === val.charAt(0))
  328. {
  329. val = val.substr(1, val.length - 2);
  330. for (var i = 0; i < nSearchWords; ++i) {
  331. if (searchWords[i] === val) {
  332. // filter type: ... queries
  333. if (typePassesFilter(typeFilter, searchIndex[i].ty)) {
  334. results.push({id: i, index: -1});
  335. }
  336. }
  337. if (results.length === max) {
  338. break;
  339. }
  340. }
  341. // searching by type
  342. } else if (val.search("->") > -1) {
  343. var trimmer = function (s) { return s.trim(); };
  344. var parts = val.split("->").map(trimmer);
  345. var input = parts[0];
  346. // sort inputs so that order does not matter
  347. var inputs = input.split(",").map(trimmer).sort().toString();
  348. var output = parts[1];
  349. for (var i = 0; i < nSearchWords; ++i) {
  350. var type = searchIndex[i].type;
  351. if (!type) {
  352. continue;
  353. }
  354. // sort index inputs so that order does not matter
  355. var typeInputs = type.inputs.map(function (input) {
  356. return input.name;
  357. }).sort();
  358. // allow searching for void (no output) functions as well
  359. var typeOutput = type.output ? type.output.name : "";
  360. if ((inputs === "*" || inputs === typeInputs.toString()) &&
  361. (output === "*" || output == typeOutput)) {
  362. results.push({id: i, index: -1, dontValidate: true});
  363. }
  364. }
  365. } else {
  366. // gather matching search results up to a certain maximum
  367. val = val.replace(/\_/g, "");
  368. for (var i = 0; i < split.length; ++i) {
  369. for (var j = 0; j < nSearchWords; ++j) {
  370. var lev_distance;
  371. if (searchWords[j].indexOf(split[i]) > -1 ||
  372. searchWords[j].indexOf(val) > -1 ||
  373. searchWords[j].replace(/_/g, "").indexOf(val) > -1)
  374. {
  375. // filter type: ... queries
  376. if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
  377. results.push({
  378. id: j,
  379. index: searchWords[j].replace(/_/g, "").indexOf(val),
  380. lev: 0,
  381. });
  382. }
  383. } else if (
  384. (lev_distance = levenshtein(searchWords[j], val)) <=
  385. MAX_LEV_DISTANCE) {
  386. if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
  387. results.push({
  388. id: j,
  389. index: 0,
  390. // we want lev results to go lower than others
  391. lev: lev_distance,
  392. });
  393. }
  394. }
  395. if (results.length === max) {
  396. break;
  397. }
  398. }
  399. }
  400. }
  401. var nresults = results.length;
  402. for (var i = 0; i < nresults; ++i) {
  403. results[i].word = searchWords[results[i].id];
  404. results[i].item = searchIndex[results[i].id] || {};
  405. }
  406. // if there are no results then return to default and fail
  407. if (results.length === 0) {
  408. return [];
  409. }
  410. results.sort(function sortResults(aaa, bbb) {
  411. var a, b;
  412. // Sort by non levenshtein results and then levenshtein results by the distance
  413. // (less changes required to match means higher rankings)
  414. a = (aaa.lev);
  415. b = (bbb.lev);
  416. if (a !== b) { return a - b; }
  417. // sort by crate (non-current crate goes later)
  418. a = (aaa.item.crate !== window.currentCrate);
  419. b = (bbb.item.crate !== window.currentCrate);
  420. if (a !== b) { return a - b; }
  421. // sort by exact match (mismatch goes later)
  422. a = (aaa.word !== valLower);
  423. b = (bbb.word !== valLower);
  424. if (a !== b) { return a - b; }
  425. // sort by item name length (longer goes later)
  426. a = aaa.word.length;
  427. b = bbb.word.length;
  428. if (a !== b) { return a - b; }
  429. // sort by item name (lexicographically larger goes later)
  430. a = aaa.word;
  431. b = bbb.word;
  432. if (a !== b) { return (a > b ? +1 : -1); }
  433. // sort by index of keyword in item name (no literal occurrence goes later)
  434. a = (aaa.index < 0);
  435. b = (bbb.index < 0);
  436. if (a !== b) { return a - b; }
  437. // (later literal occurrence, if any, goes later)
  438. a = aaa.index;
  439. b = bbb.index;
  440. if (a !== b) { return a - b; }
  441. // special precedence for primitive pages
  442. if ((aaa.item.ty === TY_PRIMITIVE) && (bbb.item.ty !== TY_PRIMITIVE)) {
  443. return -1;
  444. }
  445. if ((bbb.item.ty === TY_PRIMITIVE) && (aaa.item.ty !== TY_PRIMITIVE)) {
  446. return 1;
  447. }
  448. // sort by description (no description goes later)
  449. a = (aaa.item.desc === '');
  450. b = (bbb.item.desc === '');
  451. if (a !== b) { return a - b; }
  452. // sort by type (later occurrence in `itemTypes` goes later)
  453. a = aaa.item.ty;
  454. b = bbb.item.ty;
  455. if (a !== b) { return a - b; }
  456. // sort by path (lexicographically larger goes later)
  457. a = aaa.item.path;
  458. b = bbb.item.path;
  459. if (a !== b) { return (a > b ? +1 : -1); }
  460. // que sera, sera
  461. return 0;
  462. });
  463. // remove duplicates, according to the data provided
  464. for (var i = results.length - 1; i > 0; i -= 1) {
  465. if (results[i].word === results[i - 1].word &&
  466. results[i].item.ty === results[i - 1].item.ty &&
  467. results[i].item.path === results[i - 1].item.path &&
  468. (results[i].item.parent || {}).name === (results[i - 1].item.parent || {}).name)
  469. {
  470. results[i].id = -1;
  471. }
  472. }
  473. for (var i = 0; i < results.length; ++i) {
  474. var result = results[i],
  475. name = result.item.name.toLowerCase(),
  476. path = result.item.path.toLowerCase(),
  477. parent = result.item.parent;
  478. // this validation does not make sense when searching by types
  479. if (result.dontValidate) {
  480. continue;
  481. }
  482. var valid = validateResult(name, path, split, parent);
  483. if (!valid) {
  484. result.id = -1;
  485. }
  486. }
  487. return results;
  488. }
  489. /**
  490. * Validate performs the following boolean logic. For example:
  491. * "File::open" will give IF A PARENT EXISTS => ("file" && "open")
  492. * exists in (name || path || parent) OR => ("file" && "open") exists in
  493. * (name || path )
  494. *
  495. * This could be written functionally, but I wanted to minimise
  496. * functions on stack.
  497. *
  498. * @param {[string]} name [The name of the result]
  499. * @param {[string]} path [The path of the result]
  500. * @param {[string]} keys [The keys to be used (["file", "open"])]
  501. * @param {[object]} parent [The parent of the result]
  502. * @return {[boolean]} [Whether the result is valid or not]
  503. */
  504. function validateResult(name, path, keys, parent) {
  505. for (var i = 0; i < keys.length; ++i) {
  506. // each check is for validation so we negate the conditions and invalidate
  507. if (!(
  508. // check for an exact name match
  509. name.toLowerCase().indexOf(keys[i]) > -1 ||
  510. // then an exact path match
  511. path.toLowerCase().indexOf(keys[i]) > -1 ||
  512. // next if there is a parent, check for exact parent match
  513. (parent !== undefined &&
  514. parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
  515. // lastly check to see if the name was a levenshtein match
  516. levenshtein(name.toLowerCase(), keys[i]) <=
  517. MAX_LEV_DISTANCE)) {
  518. return false;
  519. }
  520. }
  521. return true;
  522. }
  523. function getQuery() {
  524. var matches, type, query, raw =
  525. document.getElementsByClassName('search-input')[0].value;
  526. query = raw;
  527. matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
  528. if (matches) {
  529. type = matches[1].replace(/^const$/, 'constant');
  530. query = query.substring(matches[0].length);
  531. }
  532. return {
  533. raw: raw,
  534. query: query,
  535. type: type,
  536. id: query + type
  537. };
  538. }
  539. function initSearchNav() {
  540. var hoverTimeout;
  541. var click_func = function(e) {
  542. var el = e.target;
  543. // to retrieve the real "owner" of the event.
  544. while (el.tagName !== 'TR') {
  545. el = el.parentNode;
  546. }
  547. var dst = e.target.getElementsByTagName('a');
  548. if (dst.length < 1) {
  549. return;
  550. }
  551. dst = dst[0];
  552. if (window.location.pathname === dst.pathname) {
  553. addClass(document.getElementById('search'), 'hidden');
  554. removeClass(document.getElementById('main'), 'hidden');
  555. document.location.href = dst.href;
  556. }
  557. };
  558. var mouseover_func = function(e) {
  559. var el = e.target;
  560. // to retrieve the real "owner" of the event.
  561. while (el.tagName !== 'TR') {
  562. el = el.parentNode;
  563. }
  564. clearTimeout(hoverTimeout);
  565. hoverTimeout = setTimeout(function() {
  566. onEach(document.getElementsByClassName('search-results'), function(e) {
  567. onEach(e.getElementsByClassName('result'), function(i_e) {
  568. removeClass(i_e, 'highlighted');
  569. });
  570. });
  571. addClass(el, 'highlighted');
  572. }, 20);
  573. };
  574. onEach(document.getElementsByClassName('search-results'), function(e) {
  575. onEach(e.getElementsByClassName('result'), function(i_e) {
  576. i_e.onclick = click_func;
  577. i_e.onmouseover = mouseover_func;
  578. });
  579. });
  580. var search_input = document.getElementsByClassName('search-input')[0];
  581. search_input.onkeydown = null;
  582. search_input.onkeydown = function(e) {
  583. var actives = [];
  584. onEach(document.getElementsByClassName('search-results'), function(e) {
  585. onEach(document.getElementsByClassName('highlighted'), function(e) {
  586. actives.push(e);
  587. });
  588. });
  589. if (e.which === 38) { // up
  590. if (!actives.length || !actives[0].previousElementSibling) {
  591. return;
  592. }
  593. addClass(actives[0].previousElementSibling, 'highlighted');
  594. removeClass(actives[0], 'highlighted');
  595. } else if (e.which === 40) { // down
  596. if (!actives.length) {
  597. var results = document.getElementsByClassName('search-results');
  598. if (results.length > 0) {
  599. var res = results[0].getElementsByClassName('result');
  600. if (res.length > 0) {
  601. addClass(res[0], 'highlighted');
  602. }
  603. }
  604. } else if (actives[0].nextElementSibling) {
  605. addClass(actives[0].nextElementSibling, 'highlighted');
  606. removeClass(actives[0], 'highlighted');
  607. }
  608. } else if (e.which === 13) { // return
  609. if (actives.length) {
  610. document.location.href = actives[0].getElementsByTagName('a')[0].href;
  611. }
  612. } else if (actives.length > 0) {
  613. removeClass(actives[0], 'highlighted');
  614. }
  615. };
  616. }
  617. function escape(content) {
  618. let h1 = document.createElement('h1');
  619. h1.textContent = content;
  620. return h1.innerHTML;
  621. }
  622. function showResults(results) {
  623. var output, shown, query = getQuery();
  624. currentResults = query.id;
  625. output = '<h1>Results for ' + escape(query.query) +
  626. (query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>';
  627. output += '<table class="search-results">';
  628. if (results.length > 0) {
  629. shown = [];
  630. results.forEach(function(item) {
  631. var name, type, href, displayPath;
  632. if (shown.indexOf(item) !== -1) {
  633. return;
  634. }
  635. shown.push(item);
  636. name = item.name;
  637. type = itemTypes[item.ty];
  638. if (type === 'mod') {
  639. displayPath = item.path + '::';
  640. href = rootPath + item.path.replace(/::/g, '/') + '/' +
  641. name + '/index.html';
  642. } else if (type === "primitive") {
  643. displayPath = "";
  644. href = rootPath + item.path.replace(/::/g, '/') +
  645. '/' + type + '.' + name + '.html';
  646. } else if (type === "externcrate") {
  647. displayPath = "";
  648. href = rootPath + name + '/index.html';
  649. } else if (item.parent !== undefined) {
  650. var myparent = item.parent;
  651. var anchor = '#' + type + '.' + name;
  652. var parentType = itemTypes[myparent.ty];
  653. if (parentType === "primitive") {
  654. displayPath = myparent.name + '::';
  655. } else {
  656. displayPath = item.path + '::' + myparent.name + '::';
  657. }
  658. href = rootPath + item.path.replace(/::/g, '/') +
  659. '/' + parentType +
  660. '.' + myparent.name +
  661. '.html' + anchor;
  662. } else {
  663. displayPath = item.path + '::';
  664. href = rootPath + item.path.replace(/::/g, '/') +
  665. '/' + type + '.' + name + '.html';
  666. }
  667. output += '<tr class="' + type + ' result"><td>' +
  668. '<a href="' + href + '">' +
  669. displayPath + '<span class="' + type + '">' +
  670. name + '</span></a></td><td>' +
  671. '<a href="' + href + '">' +
  672. '<span class="desc">' + escape(item.desc) +
  673. '&nbsp;</span></a></td></tr>';
  674. });
  675. } else {
  676. output += 'No results :( <a href="https://duckduckgo.com/?q=' +
  677. encodeURIComponent('rust ' + query.query) +
  678. '">Try on DuckDuckGo?</a>';
  679. }
  680. output += "</p>";
  681. addClass(document.getElementById('main'), 'hidden');
  682. var search = document.getElementById('search');
  683. removeClass(search, 'hidden');
  684. search.innerHTML = output;
  685. var tds = search.getElementsByTagName('td');
  686. var td_width = 0;
  687. if (tds.length > 0) {
  688. td_width = tds[0].offsetWidth;
  689. }
  690. var width = search.offsetWidth - 40 - td_width;
  691. onEach(search.getElementsByClassName('desc'), function(e) {
  692. e.style.width = width + 'px';
  693. });
  694. initSearchNav();
  695. }
  696. function search(e) {
  697. var query,
  698. filterdata = [],
  699. obj, i, len,
  700. results = [],
  701. maxResults = 200,
  702. resultIndex;
  703. var params = getQueryStringParams();
  704. query = getQuery();
  705. if (e) {
  706. e.preventDefault();
  707. }
  708. if (!query.query || query.id === currentResults) {
  709. return;
  710. }
  711. // Update document title to maintain a meaningful browser history
  712. document.title = "Results for " + query.query + " - Rust";
  713. // Because searching is incremental by character, only the most
  714. // recent search query is added to the browser history.
  715. if (browserSupportsHistoryApi()) {
  716. if (!history.state && !params.search) {
  717. history.pushState(query, "", "?search=" + encodeURIComponent(query.raw));
  718. } else {
  719. history.replaceState(query, "", "?search=" + encodeURIComponent(query.raw));
  720. }
  721. }
  722. resultIndex = execQuery(query, 20000, index);
  723. len = resultIndex.length;
  724. for (i = 0; i < len; ++i) {
  725. if (resultIndex[i].id > -1) {
  726. obj = searchIndex[resultIndex[i].id];
  727. filterdata.push([obj.name, obj.ty, obj.path, obj.desc]);
  728. results.push(obj);
  729. }
  730. if (results.length >= maxResults) {
  731. break;
  732. }
  733. }
  734. showResults(results);
  735. }
  736. function itemTypeFromName(typename) {
  737. for (var i = 0; i < itemTypes.length; ++i) {
  738. if (itemTypes[i] === typename) { return i; }
  739. }
  740. return -1;
  741. }
  742. function buildIndex(rawSearchIndex) {
  743. searchIndex = [];
  744. var searchWords = [];
  745. for (var crate in rawSearchIndex) {
  746. if (!rawSearchIndex.hasOwnProperty(crate)) { continue; }
  747. searchWords.push(crate);
  748. searchIndex.push({
  749. crate: crate,
  750. ty: 1, // == ExternCrate
  751. name: crate,
  752. path: "",
  753. desc: rawSearchIndex[crate].doc,
  754. type: null,
  755. });
  756. // an array of [(Number) item type,
  757. // (String) name,
  758. // (String) full path or empty string for previous path,
  759. // (String) description,
  760. // (Number | null) the parent path index to `paths`]
  761. // (Object | null) the type of the function (if any)
  762. var items = rawSearchIndex[crate].items;
  763. // an array of [(Number) item type,
  764. // (String) name]
  765. var paths = rawSearchIndex[crate].paths;
  766. // convert `paths` into an object form
  767. var len = paths.length;
  768. for (var i = 0; i < len; ++i) {
  769. paths[i] = {ty: paths[i][0], name: paths[i][1]};
  770. }
  771. // convert `items` into an object form, and construct word indices.
  772. //
  773. // before any analysis is performed lets gather the search terms to
  774. // search against apart from the rest of the data. This is a quick
  775. // operation that is cached for the life of the page state so that
  776. // all other search operations have access to this cached data for
  777. // faster analysis operations
  778. var len = items.length;
  779. var lastPath = "";
  780. for (var i = 0; i < len; ++i) {
  781. var rawRow = items[i];
  782. var row = {crate: crate, ty: rawRow[0], name: rawRow[1],
  783. path: rawRow[2] || lastPath, desc: rawRow[3],
  784. parent: paths[rawRow[4]], type: rawRow[5]};
  785. searchIndex.push(row);
  786. if (typeof row.name === "string") {
  787. var word = row.name.toLowerCase();
  788. searchWords.push(word);
  789. } else {
  790. searchWords.push("");
  791. }
  792. lastPath = row.path;
  793. }
  794. }
  795. return searchWords;
  796. }
  797. function startSearch() {
  798. var searchTimeout;
  799. var callback = function() {
  800. var search_input = document.getElementsByClassName('search-input');
  801. if (search_input.length < 1) { return; }
  802. search_input = search_input[0];
  803. clearTimeout(searchTimeout);
  804. if (search_input.value.length === 0) {
  805. if (browserSupportsHistoryApi()) {
  806. history.replaceState("", "std - Rust", "?search=");
  807. }
  808. var main = document.getElementById('main');
  809. if (hasClass(main, 'content')) {
  810. removeClass(main, 'hidden');
  811. }
  812. var search_c = document.getElementById('search');
  813. if (hasClass(search_c, 'content')) {
  814. addClass(search_c, 'hidden');
  815. }
  816. } else {
  817. searchTimeout = setTimeout(search, 500);
  818. }
  819. };
  820. var search_input = document.getElementsByClassName("search-input")[0];
  821. search_input.onkeyup = callback;
  822. search_input.oninput = callback;
  823. document.getElementsByClassName("search-form")[0].onsubmit = function(e){
  824. e.preventDefault();
  825. clearTimeout(searchTimeout);
  826. search();
  827. };
  828. search_input.onchange = function(e) {
  829. // Do NOT e.preventDefault() here. It will prevent pasting.
  830. clearTimeout(searchTimeout);
  831. // zero-timeout necessary here because at the time of event handler execution the
  832. // pasted content is not in the input field yet. Shouldn’t make any difference for
  833. // change, though.
  834. setTimeout(search, 0);
  835. };
  836. search_input.onpaste = search_input.onchange;
  837. // Push and pop states are used to add search results to the browser
  838. // history.
  839. if (browserSupportsHistoryApi()) {
  840. // Store the previous <title> so we can revert back to it later.
  841. var previousTitle = document.title;
  842. window.onpopstate = function(e) {
  843. var params = getQueryStringParams();
  844. // When browsing back from search results the main page
  845. // visibility must be reset.
  846. if (!params.search) {
  847. var main = document.getElementById('main');
  848. if (hasClass(main, 'content')) {
  849. removeClass(main, 'hidden');
  850. }
  851. var search_c = document.getElementById('search');
  852. if (hasClass(search_c, 'content')) {
  853. addClass(search_c, 'hidden');
  854. }
  855. }
  856. // Revert to the previous title manually since the History
  857. // API ignores the title parameter.
  858. document.title = previousTitle;
  859. // When browsing forward to search results the previous
  860. // search will be repeated, so the currentResults are
  861. // cleared to ensure the search is successful.
  862. currentResults = null;
  863. // Synchronize search bar with query string state and
  864. // perform the search. This will empty the bar if there's
  865. // nothing there, which lets you really go back to a
  866. // previous state with nothing in the bar.
  867. if (params.search) {
  868. document.getElementsByClassName('search-input')[0].value = params.search;
  869. } else {
  870. document.getElementsByClassName('search-input')[0].value = '';
  871. }
  872. // Some browsers fire 'onpopstate' for every page load
  873. // (Chrome), while others fire the event only when actually
  874. // popping a state (Firefox), which is why search() is
  875. // called both here and at the end of the startSearch()
  876. // function.
  877. search();
  878. };
  879. }
  880. search();
  881. }
  882. index = buildIndex(rawSearchIndex);
  883. startSearch();
  884. // Draw a convenient sidebar of known crates if we have a listing
  885. if (rootPath === '../') {
  886. var sidebar = document.getElementsByClassName('sidebar')[0];
  887. var div = document.createElement('div');
  888. div.className = 'block crate';
  889. div.innerHTML = '<h3>Crates</h3>';
  890. var ul = document.createElement('ul');
  891. div.appendChild(ul);
  892. var crates = [];
  893. for (var crate in rawSearchIndex) {
  894. if (!rawSearchIndex.hasOwnProperty(crate)) { continue; }
  895. crates.push(crate);
  896. }
  897. crates.sort();
  898. for (var i = 0; i < crates.length; ++i) {
  899. var klass = 'crate';
  900. if (crates[i] === window.currentCrate) {
  901. klass += ' current';
  902. }
  903. var link = document.createElement('a');
  904. link.href = '../' + crates[i] + '/index.html';
  905. link.title = rawSearchIndex[crates[i]].doc;
  906. link.className = klass;
  907. link.textContent = crates[i];
  908. var li = document.createElement('li');
  909. li.appendChild(link);
  910. ul.appendChild(li);
  911. }
  912. sidebar.appendChild(div);
  913. }
  914. }
  915. window.initSearch = initSearch;
  916. // delayed sidebar rendering.
  917. function initSidebarItems(items) {
  918. var sidebar = document.getElementsByClassName('sidebar')[0];
  919. var current = window.sidebarCurrent;
  920. function block(shortty, longty) {
  921. var filtered = items[shortty];
  922. if (!filtered) { return; }
  923. var div = document.createElement('div');
  924. div.className = 'block ' + shortty;
  925. var h3 = document.createElement('h3');
  926. h3.textContent = longty;
  927. div.appendChild(h3);
  928. var ul = document.createElement('ul');
  929. for (var i = 0; i < filtered.length; ++i) {
  930. var item = filtered[i];
  931. var name = item[0];
  932. var desc = item[1]; // can be null
  933. var klass = shortty;
  934. if (name === current.name && shortty === current.ty) {
  935. klass += ' current';
  936. }
  937. var path;
  938. if (shortty === 'mod') {
  939. path = name + '/index.html';
  940. } else {
  941. path = shortty + '.' + name + '.html';
  942. }
  943. var link = document.createElement('a');
  944. link.href = current.relpath + path;
  945. link.title = desc;
  946. link.className = klass;
  947. link.textContent = name;
  948. var li = document.createElement('li');
  949. li.appendChild(link);
  950. ul.appendChild(li);
  951. }
  952. div.appendChild(ul);
  953. sidebar.appendChild(div);
  954. }
  955. block("primitive", "Primitive Types");
  956. block("mod", "Modules");
  957. block("macro", "Macros");
  958. block("struct", "Structs");
  959. block("enum", "Enums");
  960. block("constant", "Constants");
  961. block("static", "Statics");
  962. block("trait", "Traits");
  963. block("fn", "Functions");
  964. block("type", "Type Definitions");
  965. }
  966. window.initSidebarItems = initSidebarItems;
  967. window.register_implementors = function(imp) {
  968. var list = document.getElementById('implementors-list');
  969. var libs = Object.getOwnPropertyNames(imp);
  970. for (var i = 0; i < libs.length; ++i) {
  971. if (libs[i] === currentCrate) { continue; }
  972. var structs = imp[libs[i]];
  973. for (var j = 0; j < structs.length; ++j) {
  974. var code = document.createElement('code');
  975. code.innerHTML = structs[j];
  976. var x = code.getElementsByTagName('a');
  977. for (var i = 0; i < x.length; i++) {
  978. var href = x[i].href;
  979. if (href && href.indexOf('http') !== 0) {
  980. x[i].href = rootPath + href;
  981. }
  982. }
  983. var li = document.createElement('li');
  984. li.appendChild(code);
  985. list.appendChild(li);
  986. }
  987. }
  988. };
  989. if (window.pending_implementors) {
  990. window.register_implementors(window.pending_implementors);
  991. }
  992. function labelForToggleButton(sectionIsCollapsed) {
  993. if (sectionIsCollapsed) {
  994. // button will expand the section
  995. return "+";
  996. }
  997. // button will collapse the section
  998. // note that this text is also set in the HTML template in render.rs
  999. return "\u2212"; // "\u2212" is '−' minus sign
  1000. }
  1001. function onEveryMatchingChild(elem, className, func) {
  1002. if (elem && className && func) {
  1003. for (var i = 0; i < elem.childNodes.length; i++) {
  1004. if (hasClass(elem.childNodes[i], className)) {
  1005. func(elem.childNodes[i]);
  1006. } else {
  1007. onEveryMatchingChild(elem.childNodes[i], className, func);
  1008. }
  1009. }
  1010. }
  1011. }
  1012. function toggleAllDocs() {
  1013. var toggle = document.getElementById("toggle-all-docs");
  1014. if (hasClass(toggle, "will-expand")) {
  1015. removeClass(toggle, "will-expand");
  1016. onEveryMatchingChild(toggle, "inner", function(e) {
  1017. e.innerHTML = labelForToggleButton(false);
  1018. });
  1019. toggle.title = "collapse all docs";
  1020. onEach(document.getElementsByClassName("docblock"), function(e) {
  1021. e.style.display = 'block';
  1022. });
  1023. onEach(document.getElementsByClassName("toggle-label"), function(e) {
  1024. e.style.display = 'none';
  1025. });
  1026. onEach(document.getElementsByClassName("toggle-wrapper"), function(e) {
  1027. removeClass(e, "collapsed");
  1028. });
  1029. onEach(document.getElementsByClassName("collapse-toggle"), function(e) {
  1030. onEveryMatchingChild(e, "inner", function(i_e) {
  1031. i_e.innerHTML = labelForToggleButton(false);
  1032. });
  1033. });
  1034. } else {
  1035. addClass(toggle, "will-expand");
  1036. onEveryMatchingChild(toggle, "inner", function(e) {
  1037. e.innerHTML = labelForToggleButton(true);
  1038. });
  1039. toggle.title = "expand all docs";
  1040. onEach(document.getElementsByClassName("docblock"), function(e) {
  1041. e.style.display = 'none';
  1042. });
  1043. onEach(document.getElementsByClassName("toggle-label"), function(e) {
  1044. e.style.display = 'inline-block';
  1045. });
  1046. onEach(document.getElementsByClassName("toggle-wrapper"), function(e) {
  1047. addClass(e, "collapsed");
  1048. });
  1049. onEach(document.getElementsByClassName("collapse-toggle"), function(e) {
  1050. onEveryMatchingChild(e, "inner", function(i_e) {
  1051. i_e.innerHTML = labelForToggleButton(true);
  1052. });
  1053. });
  1054. }
  1055. }
  1056. function collapseDocs(toggle) {
  1057. if (!toggle || !toggle.parentNode) {
  1058. return;
  1059. }
  1060. var relatedDoc = toggle.parentNode.nextElementSibling;
  1061. if (hasClass(relatedDoc, "stability")) {
  1062. relatedDoc = relatedDoc.nextElementSibling;
  1063. }
  1064. if (hasClass(relatedDoc, "docblock")) {
  1065. if (!isHidden(relatedDoc)) {
  1066. relatedDoc.style.display = 'none';
  1067. onEach(toggle.childNodes, function(e) {
  1068. if (hasClass(e, 'toggle-label')) {
  1069. e.style.display = 'inline-block';
  1070. }
  1071. if (hasClass(e, 'inner')) {
  1072. e.innerHTML = labelForToggleButton(true);
  1073. }
  1074. });
  1075. addClass(toggle.parentNode, 'collapsed');
  1076. } else {
  1077. relatedDoc.style.display = 'block';
  1078. removeClass(toggle.parentNode, 'collapsed');
  1079. onEach(toggle.childNodes, function(e) {
  1080. if (hasClass(e, 'toggle-label')) {
  1081. e.style.display = 'none';
  1082. }
  1083. if (hasClass(e, 'inner')) {
  1084. e.innerHTML = labelForToggleButton(false);
  1085. }
  1086. });
  1087. }
  1088. }
  1089. }
  1090. var x = document.getElementById('toggle-all-docs');
  1091. if (x) {
  1092. x.onclick = toggleAllDocs;
  1093. }
  1094. function insertAfter(newNode, referenceNode) {
  1095. referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
  1096. }
  1097. var toggle = document.createElement('a');
  1098. toggle.href = 'javascript:void(0)';
  1099. toggle.className = 'collapse-toggle';
  1100. toggle.innerHTML = "[<span class='inner'>"+labelForToggleButton(false)+"</span>]";
  1101. var func = function(e) {
  1102. var next = e.nextElementSibling;
  1103. if (!next) {
  1104. return;
  1105. }
  1106. if (hasClass(next, 'docblock') ||
  1107. (hasClass(next, 'stability') &&
  1108. hasClass(next.nextElementSibling, 'docblock'))) {
  1109. insertAfter(toggle.cloneNode(true), e.childNodes[e.childNodes.length - 1]);
  1110. }
  1111. }
  1112. onEach(document.getElementsByClassName('method'), func);
  1113. onEach(document.getElementsByClassName('impl-items'), function(e) {
  1114. onEach(e.getElementsByClassName('associatedconstant'), func);
  1115. });
  1116. var span = document.createElement('span');
  1117. span.className = 'toggle-label';
  1118. span.style.display = 'none';
  1119. span.innerHTML = '&nbsp;Expand&nbsp;description';
  1120. var mainToggle = toggle.cloneNode(true);
  1121. mainToggle.appendChild(span);
  1122. var wrapper = document.createElement('div');
  1123. wrapper.className = 'toggle-wrapper';
  1124. wrapper.appendChild(mainToggle);
  1125. onEach(document.getElementById('main').getElementsByClassName('docblock'), function(e) {
  1126. if (e.parentNode.id === "main") {
  1127. e.parentNode.insertBefore(wrapper, e);
  1128. }
  1129. });
  1130. onEach(document.getElementsByClassName('docblock'), function(e) {
  1131. if (hasClass(e, 'autohide')) {
  1132. var wrap = e.previousElementSibling;
  1133. if (wrap && hasClass(wrap, 'toggle-wrapper')) {
  1134. var toggle = wrap.childNodes[0];
  1135. if (e.childNodes[0].tagName === 'H3') {
  1136. onEach(toggle.getElementsByClass

Large files files are truncated, but you can click here to view the full file