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.
 
 
 
 
 
 

130 lines
6.9 KiB

  1. /*
  2. * @file Manages all query entry, `index.html` server querying, and results
  3. * diplay.
  4. */
  5. FINISH_TYPING_INTERVAL = 650;
  6. searchBar = $("form#search-bar input[type='text']")[0];
  7. resultsDiv = $("div#results")[0];
  8. var typingTimer, lastValue;
  9. //Obtained by parsing python file with pygments
  10. var codeExample = '<div class="hll"><pre><span class="sd">&quot;&quot;&quot;</span>\n<span class="sd">Module to contain all the project&#39;s Flask server plumbing.</span>\n<span class="sd">&quot;&quot;&quot;</span>\n\n<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span>\n<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">render_template</span><span class="p">,</span> <span class="n">session</span>\n\n<span class="kn">from</span> <span class="nn">bitshift</span> <span class="kn">import</span> <span class="n">assets</span>\n<span class="c"># from bitshift.database import Database</span>\n<span class="c"># from bitshift.query import parse_query</span>\n\n<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>\n<span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_object</span><span class="p">(</span><span class="s">&quot;bitshift.config&quot;</span><span class="p">)</span>\n\n<span class="n">app_env</span> <span class="o">=</span> <span class="n">app</span><span class="o">.</span><span class="n">jinja_env</span>\n<span class="n">app_env</span><span class="o">.</span><span class="n">line_statement_prefix</span> <span class="o">=</span> <span class="s">&quot;=&quot;</span>\n<span class="n">app_env</span><span class="o">.</span><span class="n">globals</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">assets</span><span class="o">=</span><span class="n">assets</span><span class="p">)</span>\n\n<span class="c"># database = Database()</span>\n\n<span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">)</span>\n<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>\n <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&quot;index.html&quot;</span><span class="p">)</span>\n\n<span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/search/&lt;query&gt;&quot;</span><span class="p">)</span>\n<span class="k">def</span> <span class="nf">search</span><span class="p">(</span><span class="n">query</span><span class="p">):</span>\n <span class="c"># tree = parse_query(query)</span>\n <span class="c"># database.search(tree)</span>\n <span class="k">pass</span>\n\n<span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/about&quot;</span><span class="p">)</span>\n<span class="k">def</span> <span class="nf">about</span><span class="p">():</span>\n <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&quot;about.html&quot;</span><span class="p">)</span>\n\n<span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/developers&quot;</span><span class="p">)</span>\n<span class="k">def</span> <span class="nf">developers</span><span class="p">():</span>\n <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&quot;developers.html&quot;</span><span class="p">)</span>\n\n<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>\n <span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">debug</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>\n</pre></div>\n'
  11. searchBar.onkeyup = typingTimer;
  12. // Enable infinite scrolling down the results page.
  13. $(window).scroll(function() {
  14. if($(window).scrollTop() + $(window).height() == $(document).height()){
  15. loadMoreResults();
  16. }
  17. });
  18. // Enable capturing the `enter` key.
  19. $("form#search-bar").submit(function(event){
  20. event.preventDefault();
  21. return false;
  22. });
  23. /*
  24. * Clear the existing timer and set a new one the the user types text into the
  25. * search bar.
  26. */
  27. function typingTimer(event){
  28. clearTimeout(typingTimer);
  29. var enterKeyCode = 13;
  30. if(event.keyCode != enterKeyCode){
  31. if(lastValue != searchBar.value)
  32. typingTimer = setTimeout(finishedTyping, FINISH_TYPING_INTERVAL);
  33. }
  34. else {
  35. event.preventDefault();
  36. finishedTyping();
  37. return false;
  38. }
  39. };
  40. /*
  41. * Callback which queries the server whenver the user stops typing.
  42. *
  43. * Whenever the user doesn't type for a `FINISH_TYPING_INTERVAL` after having
  44. * entered new text in the search bar, send the current query request to the
  45. * server.
  46. */
  47. function finishedTyping(){
  48. lastValue = searchBar.value;
  49. var searchField = $("div#search-field");
  50. clearResults();
  51. if(searchBar.value){
  52. if(!searchField.hasClass("partly-visible"))
  53. searchField.addClass("partly-visible");
  54. populateResults();
  55. }
  56. else
  57. searchField.removeClass("partly-visible");
  58. }
  59. /*
  60. * Removes any child elements of `div#results`.
  61. */
  62. function clearResults(){
  63. while(resultsDiv.firstChild)
  64. resultsDiv.removeChild(resultsDiv.firstChild);
  65. }
  66. /*
  67. * Query the server with the current search string, and populate `div#results`
  68. * with its response.
  69. */
  70. function populateResults(){
  71. var results = queryServer();
  72. for(var result = 0; result < results.length; result++){
  73. var newDiv = results[result];
  74. resultsDiv.appendChild(newDiv);
  75. setTimeout(
  76. (function(divReference){
  77. return function(){
  78. divReference.classList.add("cascade");
  79. };
  80. }(newDiv)), result * 20);
  81. }
  82. }
  83. /*
  84. * AJAX the current query string to the server, and return its response.
  85. *
  86. * @return {Array} The server's response in the form of `div.result` DOM
  87. * elements, to fill `div#results`.
  88. */
  89. function queryServer(){
  90. var resultDivs = []
  91. for(var result = 0; result < 20; result++){
  92. var newDiv = document.createElement("div");
  93. newDiv.classList.add("result");
  94. newDiv.innerHTML = codeExample;
  95. resultDivs.push(newDiv);
  96. }
  97. return resultDivs;
  98. }
  99. /*
  100. * Adds more results to `div#results`.
  101. */
  102. function loadMoreResults(){
  103. results = queryServer();
  104. for(var result = 0; result < results.length; result++){
  105. var newDiv = results[result];
  106. resultsDiv.appendChild(newDiv);
  107. setTimeout(
  108. (function(divReference){
  109. return function(){
  110. divReference.classList.add("cascade");
  111. };
  112. }(newDiv)), result * 20);
  113. }
  114. }