search.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. root = document.getElementById("main_div");
  2. root.innerHTML = `
  3. <!-- You can append '?q=query' to the URL to default to a search -->
  4. <input id="searchBox" type="text" onkeyup="updateSearch(event)"
  5. placeholder="Search for requests and types…" />
  6. <div id="searchDiv">
  7. <div id="exactMatch" style="display:none;">
  8. <b>Exact match:</b>
  9. <ul id="exactList" class="together">
  10. </ul>
  11. </div>
  12. <details id="methods" open><summary class="title">Methods (<span id="methodsCount">0</span>)</summary>
  13. <ul id="methodsList" class="together">
  14. </ul>
  15. </details>
  16. <details id="types" open><summary class="title">Types (<span id="typesCount">0</span>)</summary>
  17. <ul id="typesList" class="together">
  18. </ul>
  19. </details>
  20. <details id="constructors"><summary class="title">Constructors (<span id="constructorsCount">0</span>)</summary>
  21. <ul id="constructorsList" class="together">
  22. </ul>
  23. </details>
  24. </div>
  25. <div id="contentDiv">
  26. ` + root.innerHTML + "</div>";
  27. // HTML modified, now load documents
  28. contentDiv = document.getElementById("contentDiv");
  29. searchDiv = document.getElementById("searchDiv");
  30. searchBox = document.getElementById("searchBox");
  31. // Search lists
  32. methodsDetails = document.getElementById("methods");
  33. methodsList = document.getElementById("methodsList");
  34. methodsCount = document.getElementById("methodsCount");
  35. typesDetails = document.getElementById("types");
  36. typesList = document.getElementById("typesList");
  37. typesCount = document.getElementById("typesCount");
  38. constructorsDetails = document.getElementById("constructors");
  39. constructorsList = document.getElementById("constructorsList");
  40. constructorsCount = document.getElementById("constructorsCount");
  41. // Exact match
  42. exactMatch = document.getElementById("exactMatch");
  43. exactList = document.getElementById("exactList");
  44. try {
  45. requests = [{requestNames}];
  46. types = [{typeNames}];
  47. constructors = [{constructorNames}];
  48. requestsu = [{requestUrls}];
  49. typesu = [{typeUrls}];
  50. constructorsu = [{constructorUrls}];
  51. } catch (e) {
  52. requests = [];
  53. types = [];
  54. constructors = [];
  55. requestsu = [];
  56. typesu = [];
  57. constructorsu = [];
  58. }
  59. if (typeof prependPath !== 'undefined') {
  60. for (var i = 0; i != requestsu.length; ++i) {
  61. requestsu[i] = prependPath + requestsu[i];
  62. }
  63. for (var i = 0; i != typesu.length; ++i) {
  64. typesu[i] = prependPath + typesu[i];
  65. }
  66. for (var i = 0; i != constructorsu.length; ++i) {
  67. constructorsu[i] = prependPath + constructorsu[i];
  68. }
  69. }
  70. // Assumes haystack has no whitespace and both are lowercase.
  71. //
  72. // Returns the penalty for finding the needle in the haystack
  73. // or -1 if the needle wasn't found at all.
  74. function find(haystack, needle) {
  75. if (haystack.indexOf(needle) != -1) {
  76. return 0;
  77. }
  78. var hi = 0;
  79. var ni = 0;
  80. var penalty = 0;
  81. var started = false;
  82. while (true) {
  83. while (needle[ni] < 'a' || needle[ni] > 'z') {
  84. ++ni;
  85. if (ni == needle.length) {
  86. return penalty;
  87. }
  88. }
  89. while (haystack[hi] != needle[ni]) {
  90. ++hi;
  91. if (started) {
  92. ++penalty;
  93. }
  94. if (hi == haystack.length) {
  95. return -1;
  96. }
  97. }
  98. ++hi;
  99. ++ni;
  100. started = true;
  101. if (ni == needle.length) {
  102. return penalty;
  103. }
  104. if (hi == haystack.length) {
  105. return -1;
  106. }
  107. }
  108. }
  109. // Given two input arrays "original" and "original urls" and a query,
  110. // return a pair of arrays with matching "query" elements from "original".
  111. //
  112. // TODO Perhaps return an array of pairs instead a pair of arrays (for cache).
  113. function getSearchArray(original, originalu, query) {
  114. var destination = [];
  115. var destinationu = [];
  116. for (var i = 0; i < original.length; ++i) {
  117. var penalty = find(original[i].toLowerCase(), query);
  118. if (penalty > -1 && penalty < original[i].length / 3) {
  119. destination.push(original[i]);
  120. destinationu.push(originalu[i]);
  121. }
  122. }
  123. return [destination, destinationu];
  124. }
  125. // Modify "countSpan" and "resultList" accordingly based on the elements
  126. // given as [[elements], [element urls]] (both with the same length)
  127. function buildList(countSpan, resultList, foundElements) {
  128. var result = "";
  129. for (var i = 0; i < foundElements[0].length; ++i) {
  130. result += '<li>';
  131. result += '<a href="' + foundElements[1][i] + '">';
  132. result += foundElements[0][i];
  133. result += '</a></li>';
  134. }
  135. if (countSpan) {
  136. countSpan.innerHTML = "" + foundElements[0].length;
  137. }
  138. resultList.innerHTML = result;
  139. }
  140. function updateSearch(event) {
  141. var query = searchBox.value.toLowerCase();
  142. if (!query) {
  143. contentDiv.style.display = "";
  144. searchDiv.style.display = "none";
  145. return;
  146. }
  147. contentDiv.style.display = "none";
  148. searchDiv.style.display = "";
  149. var foundRequests = getSearchArray(requests, requestsu, query);
  150. var foundTypes = getSearchArray(types, typesu, query);
  151. var foundConstructors = getSearchArray(constructors, constructorsu, query);
  152. var original = requests.concat(constructors);
  153. var originalu = requestsu.concat(constructorsu);
  154. var destination = [];
  155. var destinationu = [];
  156. for (var i = 0; i < original.length; ++i) {
  157. if (original[i].toLowerCase().replace("request", "") == query) {
  158. destination.push(original[i]);
  159. destinationu.push(originalu[i]);
  160. }
  161. }
  162. if (event && event.keyCode == 13) {
  163. if (destination.length != 0) {
  164. window.location = destinationu[0];
  165. } else if (methodsDetails.open && foundRequests[1].length) {
  166. window.location = foundRequests[1][0];
  167. } else if (typesDetails.open && foundTypes[1].length) {
  168. window.location = foundTypes[1][0];
  169. } else if (constructorsDetails.open && foundConstructors[1].length) {
  170. window.location = foundConstructors[1][0];
  171. }
  172. return;
  173. }
  174. buildList(methodsCount, methodsList, foundRequests);
  175. buildList(typesCount, typesList, foundTypes);
  176. buildList(constructorsCount, constructorsList, foundConstructors);
  177. // Now look for exact matches
  178. if (destination.length == 0) {
  179. exactMatch.style.display = "none";
  180. } else {
  181. exactMatch.style.display = "";
  182. buildList(null, exactList, [destination, destinationu]);
  183. return destinationu[0];
  184. }
  185. }
  186. function getQuery(name) {
  187. var query = window.location.search.substring(1);
  188. var vars = query.split("&");
  189. for (var i = 0; i != vars.length; ++i) {
  190. var pair = vars[i].split("=");
  191. if (pair[0] == name)
  192. return decodeURI(pair[1]);
  193. }
  194. }
  195. document.onkeydown = function (e) {
  196. if (e.key == '/' || e.key == 's' || e.key == 'S') {
  197. if (document.activeElement != searchBox) {
  198. searchBox.focus();
  199. return false;
  200. }
  201. } else if (e.key == '?') {
  202. alert('Pressing any of: /sS\nWill focus the search bar\n\n' +
  203. 'Pressing: enter\nWill navigate to the first match')
  204. }
  205. }
  206. var query = getQuery('q');
  207. if (query) {
  208. searchBox.value = query;
  209. }
  210. var exactUrl = updateSearch();
  211. var redirect = getQuery('redirect');
  212. if (exactUrl && redirect != 'no') {
  213. window.location = exactUrl;
  214. }