A semantic search engine for source code https://bitshift.benkurtovic.com/
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

235 righe
6.8 KiB

  1. /*
  2. * @file Manages all library initialization, jQuery callbacks, query entry
  3. * callbacks, server querying, and results diplay for `index.html`.
  4. */
  5. var advancedSearchDiv = $("div#advanced-search");
  6. var advancedSearchButton = $("button#advanced-search");
  7. advancedSearchButton.click(function(){
  8. var searchField = $("div#search-field");
  9. if(!advancedSearchDiv.hasClass("visible")){
  10. searchField.addClass("partly-visible");
  11. advancedSearchDiv.fadeIn(500).addClass("visible");
  12. advancedSearchButton.addClass("clicked");
  13. }
  14. else {
  15. advancedSearchDiv.fadeOut(300).removeClass("visible");
  16. advancedSearchButton.removeClass("clicked");
  17. if($("div#results .result").length == 0)
  18. searchField.removeClass("partly-visible");
  19. }
  20. });
  21. $("#date-last-modified").datepicker();
  22. $("#date-created").datepicker();
  23. var languages = new Bloodhound({
  24. datumTokenizer: Bloodhound.tokenizers.obj.whitespace("value"),
  25. queryTokenizer: Bloodhound.tokenizers.whitespace,
  26. local: $.map(TYPEAHEAD_LANGUAGES, function(state){
  27. return {value : state};
  28. })
  29. });
  30. languages.initialize();
  31. $("#languages.typeahead").typeahead({
  32. hint: true,
  33. highlight: true,
  34. minLength: 1
  35. },
  36. {
  37. name: "languages",
  38. displayKey: "value",
  39. source: languages.ttAdapter()
  40. });
  41. FINISH_TYPING_INTERVAL = 650;
  42. searchBar = $("form#search-bar input[type='text']")[0];
  43. resultsDiv = $("div#results")[0];
  44. var typingTimer, lastValue;
  45. searchBar.onkeyup = typingTimer;
  46. // Enable infinite scrolling down the results page.
  47. $(window).scroll(function() {
  48. if($(window).scrollTop() + $(window).height() == $(document).height()){
  49. loadMoreResults();
  50. }
  51. });
  52. // Enable capturing the `enter` key.
  53. $("form#search-bar").submit(function(event){
  54. event.preventDefault();
  55. return false;
  56. });
  57. /*
  58. * Clear the existing timer and set a new one the the user types text into the
  59. * search bar.
  60. */
  61. function typingTimer(event){
  62. clearTimeout(typingTimer);
  63. var enterKeyCode = 13;
  64. if(event.keyCode != enterKeyCode){
  65. if(lastValue != searchBar.value)
  66. typingTimer = setTimeout(finishedTyping, FINISH_TYPING_INTERVAL);
  67. }
  68. else {
  69. event.preventDefault();
  70. finishedTyping();
  71. return false;
  72. }
  73. };
  74. /*
  75. * Callback which queries the server whenver the user stops typing.
  76. *
  77. * Whenever the user doesn't type for a `FINISH_TYPING_INTERVAL` after having
  78. * entered new text in the search bar, send the current query request to the
  79. * server.
  80. */
  81. function finishedTyping(){
  82. lastValue = searchBar.value;
  83. var searchField = $("div#search-field");
  84. clearResults();
  85. if(searchBar.value){
  86. searchField.addClass("partly-visible");
  87. populateResults();
  88. }
  89. else {
  90. searchField.removeClass("partly-visible");
  91. $("div#advanced-search").fadeOut(50);
  92. advancedSearchButton.removeClass("clicked");
  93. }
  94. }
  95. /*
  96. * Removes any child elements of `div#results`.
  97. */
  98. function clearResults(){
  99. while(resultsDiv.firstChild)
  100. resultsDiv.removeChild(resultsDiv.firstChild);
  101. }
  102. /*
  103. * Query the server with the current search string, and populate `div#results`
  104. * with its response.
  105. */
  106. function populateResults(){
  107. var results = queryServer();
  108. for(var result = 0; result < results.length; result++){
  109. var newDiv = results[result];
  110. resultsDiv.appendChild(newDiv);
  111. setTimeout(
  112. (function(divReference){
  113. return function(){
  114. divReference.classList.add("cascade");
  115. };
  116. }(newDiv)), result * 20);
  117. }
  118. }
  119. /*
  120. * AJAX the current query string to the server, and return its response.
  121. *
  122. * @return {Array} The server's response in the form of `div.result` DOM
  123. * elements, to fill `div#results`.
  124. */
  125. function queryServer(){
  126. var resultDivs = []
  127. for(var result = 0; result < 20; result++){
  128. var newDiv = document.createElement("div");
  129. newDiv.classList.add("result");
  130. newDiv.innerHTML = Math.random();
  131. newDiv.style.textAlign = "center";
  132. newDiv.style.color = "#" + Math.floor(Math.random() *
  133. 16777215).toString(16);
  134. resultDivs.push(newDiv);
  135. }
  136. return resultDivs;
  137. }
  138. /*
  139. * Adds more results to `div#results`.
  140. */
  141. function loadMoreResults(){
  142. results = queryServer();
  143. for(var result = 0; result < results.length; result++){
  144. var newDiv = results[result];
  145. resultsDiv.appendChild(newDiv);
  146. setTimeout(
  147. (function(divReference){
  148. return function(){
  149. divReference.classList.add("cascade");
  150. };
  151. }(newDiv)),
  152. result * 20);
  153. }
  154. }
  155. var searchGroups = $("div#search-groups");
  156. // Create a new search group, and update the `#sidebar` checklist accordingly.
  157. $("button#add-group").click(function(){
  158. $("div#sidebar input[type=checkbox]").prop("checked", false);
  159. searchGroups.children("#selected").removeAttr("id");
  160. var searchGroup = $("<div/>", {class : "search-group", id : "selected"});
  161. searchGroups.append(searchGroup.append(createSearchGroupInput("language")));
  162. $("div#sidebar input[type=checkbox]#language").prop("checked", true);
  163. });
  164. $("button#remove-group").click(function(){
  165. var currentGroup = $("div.search-group#selected");
  166. if($("div.search-group").length == 1)
  167. return;
  168. else {
  169. var nextGroup = currentGroup.prev();
  170. if(nextGroup.size() == 0)
  171. nextGroup = currentGroup.next();
  172. }
  173. currentGroup.remove();
  174. nextGroup.click();
  175. });
  176. // Select a search group, and update the `#sidebar` checklist accordingly.
  177. $(document).on("click", "div.search-group", function(){
  178. searchGroups.children("#selected").removeAttr("id");
  179. $(this).attr("id", "selected");
  180. $("div#sidebar input[type=checkbox]").prop("checked", false);
  181. $(this).find("input[type=text]").each(function(){
  182. var checkBoxSelector = "div#sidebar input[type=checkbox]";
  183. $(checkBoxSelector + "#" + $(this).attr("id")).prop("checked", true);
  184. })
  185. });
  186. // Add an input field to the currently selected search group.
  187. $("div#sidebar input[type=checkbox]").click(function(){
  188. var fieldId = $(this).prop("id");
  189. if($(this).is(":checked"))
  190. $("div.search-group#selected").append(
  191. $.parseHTML(createSearchGroupInput(fieldId)));
  192. else
  193. $("div.search-group#selected #" + fieldId).remove()
  194. });
  195. /*
  196. * Return an HTML string representing a new input field div in a search group.
  197. *
  198. * @param fieldId The id of the input field div, and its child elements.
  199. */
  200. function createSearchGroupInput(fieldId){
  201. return [
  202. "<div id='" + fieldId + "'>",
  203. "<div>" + fieldId.replace(/-/g, " ") + "</div>",
  204. "<input id='" + fieldId + "'type='text'/>",
  205. "<input type='checkbox' name='regex'><span>Regex</span>",
  206. "</div>"
  207. ].join("");
  208. }