A semantic search engine for source code https://bitshift.benkurtovic.com/
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.
 
 
 
 
 
 

153 lines
5.2 KiB

  1. /*
  2. * @file Manages all advanced search form logic.
  3. */
  4. var searchGroups = $("div#search-groups");
  5. /*
  6. * Load all advanced search form libraries.
  7. */
  8. (function loadInputFieldWidgets(){
  9. $(".search-group input#date-last-modified").datepicker();
  10. $(".search-group input#date-created").datepicker();
  11. $("#autocomplete").autocomplete({
  12. source: function(request, response){
  13. var matcher = new RegExp(
  14. $.ui.autocomplete.escapeRegex(request.term), "i");
  15. response($.grep(AUTOCOMPLETE_LANGUAGES, function(item){
  16. return matcher.test(item);
  17. }));
  18. }
  19. });
  20. }());
  21. /*
  22. * Set all advanced search form button callbacks.
  23. */
  24. (function setSearchFormCallbacks(){
  25. // Create a new search group, and update the `#sidebar` checklist.
  26. $("button#add-group").click(function(){
  27. $("div#sidebar input[type=checkbox]").prop("checked", false);
  28. searchGroups.children("#selected").removeAttr("id");
  29. var searchGroup = $("<div/>", {
  30. class : "search-group",
  31. id : "selected"
  32. });
  33. searchGroups.append(
  34. searchGroup.append(createSearchGroupInput("language")));
  35. $("div#sidebar input[type=checkbox]#language").prop("checked", true);
  36. searchGroups[0].scrollTop = searchGroups[0].scrollHeight;
  37. });
  38. // Remove the currently selected group if it's not the only one, and mark
  39. // one of its siblings as selected.
  40. $("button#remove-group").click(function(){
  41. var currentGroup = $("div.search-group#selected");
  42. if($("div.search-group").length == 1)
  43. return;
  44. else {
  45. var nextGroup = currentGroup.prev();
  46. if(nextGroup.size() == 0)
  47. nextGroup = currentGroup.next();
  48. }
  49. currentGroup.remove();
  50. nextGroup.click();
  51. });
  52. // Select a search group, and update the `#sidebar` checklist accordingly.
  53. $(document).on("click", "div.search-group", function(){
  54. searchGroups.children("#selected").removeAttr("id");
  55. $(this).attr("id", "selected");
  56. $("div#sidebar input[type=checkbox]").prop("checked", false);
  57. $(this).find("input[type=text]").each(function(){
  58. var checkBoxSelector = "div#sidebar input[type=checkbox]";
  59. $(checkBoxSelector + "#" + $(this).attr("class").split(" ")[0]).
  60. prop("checked", true);
  61. })
  62. });
  63. // Toggle the presence of an input field.
  64. $("div#sidebar input[type=checkbox]").click(function(){
  65. var fieldId = $(this).prop("id");
  66. if($(this).is(":checked")){
  67. $("div.search-group#selected").append(
  68. $.parseHTML(createSearchGroupInput(fieldId)));
  69. if(fieldId.slice(0, 4) == "date")
  70. $(".search-group#selected ." + fieldId).datepicker();
  71. }
  72. else {
  73. if($(".search-group#selected").children("div").length > 1)
  74. $(".search-group#selected #" + fieldId).remove()
  75. else
  76. $(this).prop("checked", true);
  77. }
  78. searchGroups[0].scrollTop = searchGroups[0].scrollHeight;
  79. });
  80. var previousAdvancedQuery = "";
  81. var searchBar = $("form#search-bar input[name=query]");
  82. window.setInterval(function(){
  83. var currentQuery = assembleQuery();
  84. if(currentQuery != previousAdvancedQuery){
  85. previousAdvancedQuery = currentQuery;
  86. searchBar.val(assembleQuery());
  87. }
  88. }, 1e3 / 15);
  89. }());
  90. /*
  91. * Return an HTML string representing a new input field div in a search group.
  92. *
  93. * @param fieldId The id of the input field div, and its child elements.
  94. */
  95. function createSearchGroupInput(fieldId){
  96. return [
  97. "<div id='" + fieldId + "'>",
  98. "<div class='name'>" + fieldId.replace(/-/g, " ") + "</div>",
  99. "<input class='" + fieldId + "' name='" + fieldId + "'type='text'>",
  100. "<input type='checkbox' name='regex'>",
  101. "<span class='regex'>Regex</span>",
  102. "</div>"
  103. ].join("");
  104. }
  105. /*
  106. * Create a query from advanced-search groups.
  107. */
  108. function assembleQuery(){
  109. var groups = searchGroups.children(".search-group");
  110. var groupQueries = [];
  111. for(var group = 0; group < groups.length; group++){
  112. var inputFields = groups[group].querySelectorAll("input[type=text]");
  113. var regexCheckbox = groups[group].querySelectorAll("input[name=regex]");
  114. var groupQuery = [];
  115. for(var field = 0; field < inputFields.length; field++)
  116. if(inputFields[field].value.length > 0)
  117. groupQuery.push(genFieldQueryString(
  118. inputFields[field], regexCheckbox[field].checked));
  119. if(groupQuery.length > 0)
  120. groupQueries.push(groupQuery.join(" AND "));
  121. }
  122. return groupQueries.join(" OR ");
  123. }
  124. /*
  125. * Generate a processed query string for an input field's value.
  126. *
  127. * @param field (DOM element) An `input[type=text]` element.
  128. * @param hasRegex (boolean) Whether or not the field's value has regex.
  129. */
  130. function genFieldQueryString(field, hasRegex){
  131. var terms = field.value.replace(/\\/g, "\\\\").replace(/\"/g, "\\\"");
  132. var query = field.getAttribute("name") + ":" + (hasRegex?"re:":"") + terms;
  133. return '"' + query + '"';
  134. }