You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
11 KiB

  1. /*
  2. * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * This code is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 only, as
  7. * published by the Free Software Foundation. Oracle designates this
  8. * particular file as subject to the "Classpath" exception as provided
  9. * by Oracle in the LICENSE file that accompanied this code.
  10. *
  11. * This code is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14. * version 2 for more details (a copy is included in the LICENSE file that
  15. * accompanied this code).
  16. *
  17. * You should have received a copy of the GNU General Public License version
  18. * 2 along with this work; if not, write to the Free Software Foundation,
  19. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22. * or visit www.oracle.com if you need additional information or have any
  23. * questions.
  24. */
  25. "use strict";
  26. $(function() {
  27. var copy = $("#page-search-copy");
  28. var expand = $("#page-search-expand");
  29. var searchLink = $("span#page-search-link");
  30. var redirect = $("input#search-redirect");
  31. function setSearchUrlTemplate() {
  32. var href = document.location.href.split(/[#?]/)[0];
  33. href += "?q=" + "%s";
  34. if (redirect.is(":checked")) {
  35. href += "&r=1";
  36. }
  37. searchLink.html(href);
  38. copy[0].onmouseenter();
  39. }
  40. function copyLink(e) {
  41. var textarea = document.createElement("textarea");
  42. textarea.style.height = 0;
  43. document.body.appendChild(textarea);
  44. textarea.value = this.previousSibling.innerText;
  45. textarea.select();
  46. document.execCommand("copy");
  47. document.body.removeChild(textarea);
  48. var span = this.lastElementChild;
  49. var copied = span.getAttribute("data-copied");
  50. if (span.innerHTML !== copied) {
  51. var initialLabel = span.innerHTML;
  52. span.innerHTML = copied;
  53. var parent = this.parentElement.parentElement;
  54. parent.onmouseleave = parent.ontouchend = copy[0].onmouseenter = function() {
  55. span.innerHTML = initialLabel;
  56. };
  57. }
  58. }
  59. copy.click(copyLink);
  60. copy[0].onmouseenter = function() {};
  61. redirect.click(setSearchUrlTemplate);
  62. setSearchUrlTemplate();
  63. copy.prop("disabled", false);
  64. redirect.prop("disabled", false);
  65. expand.click(function (e) {
  66. var searchInfo = $("div.page-search-info");
  67. if(this.parentElement.hasAttribute("open")) {
  68. searchInfo.attr("style", "border-width: 0;");
  69. } else {
  70. searchInfo.attr("style", "border-width: 1px;").height(searchInfo.prop("scrollHeight"));
  71. }
  72. });
  73. });
  74. $(window).on("load", function() {
  75. var input = $("#page-search-input");
  76. var reset = $("#page-search-reset");
  77. var notify = $("#page-search-notify");
  78. var resultSection = $("div#result-section");
  79. var resultContainer = $("div#result-container");
  80. var searchTerm = "";
  81. var activeTab = "";
  82. var fixedTab = false;
  83. var visibleTabs = [];
  84. var feelingLucky = false;
  85. function renderResults(result) {
  86. if (!result.length) {
  87. notify.html(messages.noResult);
  88. } else if (result.length === 1) {
  89. notify.html(messages.oneResult);
  90. } else {
  91. notify.html(messages.manyResults.replace("{0}", result.length));
  92. }
  93. resultContainer.empty();
  94. var r = {
  95. "types": [],
  96. "members": [],
  97. "packages": [],
  98. "modules": [],
  99. "searchTags": []
  100. };
  101. for (var i in result) {
  102. var item = result[i];
  103. var arr = r[item.category];
  104. arr.push(item);
  105. }
  106. if (!activeTab || r[activeTab].length === 0 || !fixedTab) {
  107. Object.keys(r).reduce(function(prev, curr) {
  108. if (r[curr].length > 0 && r[curr][0].score > prev) {
  109. activeTab = curr;
  110. return r[curr][0].score;
  111. }
  112. return prev;
  113. }, 0);
  114. }
  115. if (feelingLucky && activeTab) {
  116. notify.html(messages.redirecting)
  117. var firstItem = r[activeTab][0];
  118. window.location = getURL(firstItem.indexItem, firstItem.category);
  119. return;
  120. }
  121. if (result.length > 20) {
  122. if (searchTerm[searchTerm.length - 1] === ".") {
  123. if (activeTab === "types" && r["members"].length > r["types"].length) {
  124. activeTab = "members";
  125. } else if (activeTab === "packages" && r["types"].length > r["packages"].length) {
  126. activeTab = "types";
  127. }
  128. }
  129. }
  130. var categoryCount = Object.keys(r).reduce(function(prev, curr) {
  131. return prev + (r[curr].length > 0 ? 1 : 0);
  132. }, 0);
  133. visibleTabs = [];
  134. var tabContainer = $("<div class='table-tabs'></div>").appendTo(resultContainer);
  135. for (var key in r) {
  136. var id = "#result-tab-" + key.replace("searchTags", "search_tags");
  137. if (r[key].length) {
  138. var count = r[key].length >= 1000 ? "999+" : r[key].length;
  139. if (result.length > 20 && categoryCount > 1) {
  140. var button = $("<button id='result-tab-" + key
  141. + "' class='page-search-header'><span>" + categories[key] + "</span>"
  142. + "<span style='font-weight: normal'> (" + count + ")</span></button>").appendTo(tabContainer);
  143. button.click(key, function(e) {
  144. fixedTab = true;
  145. renderResult(e.data, $(this));
  146. });
  147. visibleTabs.push(key);
  148. } else {
  149. $("<span class='page-search-header active-table-tab'>" + categories[key]
  150. + "<span style='font-weight: normal'> (" + count + ")</span></span>").appendTo(tabContainer);
  151. renderTable(key, r[key]).appendTo(resultContainer);
  152. tabContainer = $("<div class='table-tabs'></div>").appendTo(resultContainer);
  153. }
  154. }
  155. }
  156. if (activeTab && result.length > 20 && categoryCount > 1) {
  157. $("button#result-tab-" + activeTab).addClass("active-table-tab");
  158. renderTable(activeTab, r[activeTab]).appendTo(resultContainer);
  159. }
  160. resultSection.show();
  161. function renderResult(category, button) {
  162. activeTab = category;
  163. setSearchUrl();
  164. resultContainer.find("div.summary-table").remove();
  165. renderTable(activeTab, r[activeTab]).appendTo(resultContainer);
  166. button.siblings().removeClass("active-table-tab");
  167. button.addClass("active-table-tab");
  168. }
  169. }
  170. function selectTab(category) {
  171. $("button#result-tab-" + category).click();
  172. }
  173. function renderTable(category, items) {
  174. var table = $("<div class='summary-table'>")
  175. .addClass(category === "modules"
  176. ? "one-column-search-results"
  177. : "two-column-search-results");
  178. var col1, col2;
  179. if (category === "modules") {
  180. col1 = "Module";
  181. } else if (category === "packages") {
  182. col1 = "Module";
  183. col2 = "Package";
  184. } else if (category === "types") {
  185. col1 = "Package";
  186. col2 = "Class"
  187. } else if (category === "members") {
  188. col1 = "Class";
  189. col2 = "Member";
  190. } else if (category === "searchTags") {
  191. col1 = "Location";
  192. col2 = "Name";
  193. }
  194. $("<div class='table-header col-plain'>" + col1 + "</div>").appendTo(table);
  195. if (category !== "modules") {
  196. $("<div class='table-header col-plain'>" + col2 + "</div>").appendTo(table);
  197. }
  198. $.each(items, function(index, item) {
  199. var rowColor = index % 2 ? "odd-row-color" : "even-row-color";
  200. renderItem(item, table, rowColor);
  201. });
  202. return table;
  203. }
  204. function renderItem(item, table, rowColor) {
  205. var label = getHighlightedText(item.input, item.boundaries, item.prefix.length, item.input.length);
  206. var link = $("<a/>")
  207. .attr("href", getURL(item.indexItem, item.category))
  208. .attr("tabindex", "0")
  209. .addClass("search-result-link")
  210. .html(label);
  211. var container = getHighlightedText(item.input, item.boundaries, 0, item.prefix.length - 1);
  212. if (item.category === "searchTags") {
  213. container = item.indexItem.h || "";
  214. }
  215. if (item.category !== "modules") {
  216. $("<div/>").html(container).addClass("col-plain").addClass(rowColor).appendTo(table);
  217. }
  218. $("<div/>").html(link).addClass("col-last").addClass(rowColor).appendTo(table);
  219. }
  220. var timeout;
  221. function schedulePageSearch() {
  222. if (timeout) {
  223. clearTimeout(timeout);
  224. }
  225. timeout = setTimeout(function () {
  226. doPageSearch()
  227. }, 100);
  228. }
  229. function doPageSearch() {
  230. setSearchUrl();
  231. var term = searchTerm = input.val().trim();
  232. if (term === "") {
  233. notify.html(messages.enterTerm);
  234. activeTab = "";
  235. fixedTab = false;
  236. resultContainer.empty();
  237. resultSection.hide();
  238. } else {
  239. notify.html(messages.searching);
  240. doSearch({ term: term, maxResults: 1200 }, renderResults);
  241. }
  242. }
  243. function setSearchUrl() {
  244. var query = input.val().trim();
  245. var url = document.location.pathname;
  246. if (query) {
  247. url += "?q=" + encodeURI(query);
  248. if (activeTab && fixedTab) {
  249. url += "&c=" + activeTab;
  250. }
  251. }
  252. history.replaceState({query: query}, "", url);
  253. }
  254. input.on("input", function(e) {
  255. feelingLucky = false;
  256. schedulePageSearch();
  257. });
  258. $(document).keydown(function(e) {
  259. if ((e.ctrlKey || e.metaKey) && (e.key === "ArrowLeft" || e.key === "ArrowRight")) {
  260. if (activeTab && visibleTabs.length > 1) {
  261. var idx = visibleTabs.indexOf(activeTab);
  262. idx += e.key === "ArrowLeft" ? visibleTabs.length - 1 : 1;
  263. selectTab(visibleTabs[idx % visibleTabs.length]);
  264. return false;
  265. }
  266. }
  267. });
  268. reset.click(function() {
  269. notify.html(messages.enterTerm);
  270. resultSection.hide();
  271. activeTab = "";
  272. fixedTab = false;
  273. resultContainer.empty();
  274. input.val('').focus();
  275. setSearchUrl();
  276. });
  277. input.prop("disabled", false);
  278. reset.prop("disabled", false);
  279. var urlParams = new URLSearchParams(window.location.search);
  280. if (urlParams.has("q")) {
  281. input.val(urlParams.get("q"))
  282. }
  283. if (urlParams.has("c")) {
  284. activeTab = urlParams.get("c");
  285. fixedTab = true;
  286. }
  287. if (urlParams.get("r")) {
  288. feelingLucky = true;
  289. }
  290. if (input.val()) {
  291. doPageSearch();
  292. } else {
  293. notify.html(messages.enterTerm);
  294. }
  295. input.select().focus();
  296. });