PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://github.com/youknowone/rust
JavaScript | 1322 lines | 1049 code | 127 blank | 146 comment | 250 complexity | 8fbf1ae9c7220e8c8e3cf31a6e8dd9dc MD5 | raw file
Possible License(s): 0BSD, MIT

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

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

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