ni_nitdoc: moved JS quick search to Nitdoc.QuickSearch module
authorAlexandre Terrasa <alexandre@moz-code.org>
Tue, 17 Sep 2013 02:43:39 +0000 (22:43 -0400)
committerAlexandre Terrasa <alexandre@moz-code.org>
Tue, 17 Sep 2013 02:43:39 +0000 (22:43 -0400)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

share/ni_nitdoc/scripts/Nitdoc.QuickSearch.js
share/ni_nitdoc/styles/Nitdoc.QuickSearch.css [new file with mode: 0644]
share/ni_nitdoc/styles/main.css
src/ni_nitdoc.nit

index 7f88149..a8b127c 100644 (file)
+/* This file is part of NIT ( http://www.nitlanguage.org ).
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+   Documentation generator for the nit language.
+   Generate API documentation in HTML format from nit source code.
+*/
+
+var Nitdoc = Nitdoc || {};
+
 /*
- *     QuickSearch
+ * Nitdoc QuickSearch module
+ *
  */
 
-// Current search results preview table
-var currentTable = null;
-
-//Hightlighted index in search result preview table
-var currentIndex = -1;
+Nitdoc.QuickSearch = function() {
+       var rawList = nitdocQuickSearchRawList; // List of raw resulsts generated by nitdoc tool
+       var searchField = null; // <input:text> search field
+       var currentTable = null; // current search results <table>
+       var currentIndex = -1; // current cursor position into search results table
 
-$(document).ready(function() {
+       // Enable QuickSearch plugin
+       var enableQuickSearch = function(containerSelector) {
+               searchField = $(document.createElement("input"))
+               .attr({
+                       id: "nitdoc-qs-field",
+                       type: "text",
+                       autocomplete: "off",
+                       value: "quick search..."
+               })
+               .addClass("nitdoc-qs-notused")
+               .keyup(function(event) {
+                       Nitdoc.QuickSearch.doKeyAction(event.keyCode);
+               })
+               .focusout(function() {
+                       if($(this).val() == "") {
+                               $(this).addClass("nitdoc-qs-notused");
+                               $(this).val("quick search...");
+                       }
+               })
+               .focusin(function() {
+                       if($(this).val() == "quick search...") {
+                               $(this).removeClass("nitdoc-qs-notused");
+                               $(this).val("");
+                       }
+               });
 
-       // Insert search field
-       $("nav.main ul")
-       .append(
-               $(document.createElement("li"))
-               .append(
-                       $(document.createElement("form"))
+               $(containerSelector).append(
+                       $(document.createElement("li"))
                        .append(
-                               $(document.createElement("input"))
-                               .attr({
-                                       id: "search",
-                                       type:   "text",
-                                       autocomplete: "off",
-                                       value: "quick search..."
-                               })
-                               .addClass("notUsed")
-
-                               // Key management
-                               .keyup(function(e) {
-                                       switch(e.keyCode) {
-                                               // Up
-                                               case 38:
-                                                       Nitdoc.QuickSearch.selectPrevResult();
-                                               break;
-
-                                               // Down
-                                               case 40:
-                                                       Nitdoc.QuickSearch.selectNextResult();
-                                               break;
-                                               // Enter
-                                               case 13:
-                                                       Nitdoc.QuickSearch.goToResult();
-                                                       return false;
-                                               break;
-
-                                               // Escape
-                                               case 27:
-                                                       $(this).blur();
-                                                       Nitdoc.QuickSearch.close();
-                                               break;
-
-                                               // Other keys
-                                               default:
-                                                       var query = $("#search").val();
-                                                       if(!query) {
-                                                               return false;
-                                                       }
-                                                       var results = Nitdoc.QuickSearch.search(query);
-                                                       Nitdoc.QuickSearch.showResults(query, results);
-                                               break;
-                                       }
-                               })
-                               .focusout(function() {
-                                       if($(this).val() == "") {
-                                               $(this).addClass("notUsed");
-                                               $(this).val("quick search...");
-                                       }
-                               })
-                               .focusin(function() {
-                                       if($(this).val() == "quick search...") {
-                                               $(this).removeClass("notUsed");
-                                               $(this).val("");
-                                       }
+                               $(document.createElement("form"))
+                               .append(searchField)
+                               .submit(function() {
+                                       return false;
                                })
                        )
-                       .submit( function() {
+               );
+
+               // Close quicksearch list on click
+               $(document).click(function(e) {
+                       Nitdoc.QuickSearch.closeResultsTable();
+               });
+       }
+
+       // Respond to key event
+       var doKeyAction = function(key) {
+               switch(key) {
+                       case 38: // Up
+                               selectPrevResult();
+                       break;
+
+                       case 40: // Down
+                               selectNextResult();
+                       break;
+
+                       case 13: // Enter
+                               goToResult();
                                return false;
-                       })
-               )
-        );
-
-        // Close quicksearch list on click
-        $(document).click(function(e) {
-               Nitdoc.QuickSearch.close();
-        });
-});
+                       break;
 
-var Nitdoc = Nitdoc || {};
-Nitdoc.QuickSearch = {};
-
-// Do search
-Nitdoc.QuickSearch.search = function(query) {
-       // Escape regexp related characters in query
-       query = query.replace(/\\/gi, "\\\\");
-       query = query.replace(/\[/gi, "\\[");
-       query = query.replace(/\|/gi, "\\|");
-       query = query.replace(/\*/gi, "\\*");
-       query = query.replace(/\+/gi, "\\+");
-       query = query.replace(/\?/gi, "\\?");
-       query = query.replace(/\(/gi, "\\(");
-       query = query.replace(/\)/gi, "\\)");
-       query = query.replace(/&/gi, "&&");
-       // Look for matches in JSON entries
-       var results = new Array();
-       var regexp = new RegExp("^" + query, "i");
-       for(var entry in entries) {
-               for(var i in entries[entry]) {
-                       var result = entries[entry][i];
-                       result.entry = entry;
-                       result.distance = query.dice(entry);
-                       results[results.length] = result;
+                       case 27: // Escape
+                               $(this).blur();
+                               closeResultsTable();
+                       break;
+
+                       default: // Other keys
+                               var query = searchField.val();
+                               if(!query) {
+                                       return false;
+                               }
+                               var results = rankResults(query);
+                               results.sort(resultsSort);
+                               displayResultsTable(query, results);
+                       break;
                }
        }
-       results.sort(Nitdoc.QuickSearch.resultSorter);
-       return results;
-}
 
-// Sort an array of results
-Nitdoc.QuickSearch.resultSorter = function(a, b){
-       if(a.distance < b.distance) {
-               return 1;
-       } else if(a.distance > b.distance) {
-               return -1;
+       // Rank raw list entries corresponding to query
+       var rankResults = function(query) {
+               var results = new Array();
+               for(var entry in rawList) {
+                       for(var i in rawList[entry]) {
+                               var result = rawList[entry][i];
+                               result.entry = entry;
+                               result.distance = query.dice(entry);
+                               results[results.length] = result;
+                       }
+               }
+               return results;
        }
-       return 0;
-}
 
-// Display resulsts in popup table
-Nitdoc.QuickSearch.showResults = function(query, results) {
-       // Remove previous table
-       if(currentTable != null) {
-               currentTable.remove();
-       }
-       // Build results table
-       currentIndex = -1;
-       currentTable = $(document.createElement("table"));
-       var overflow = 0;
-       for(var i in results) {
-               if(i > 10) {
-                       overflow++;
-                       break;
+       // Sort an array of results
+       var resultsSort = function(a, b){
+               if(a.distance < b.distance) {
+                       return 1;
+               } else if(a.distance > b.distance) {
+                       return -1;
                }
-               var result = results[i];
-               currentTable.append(
-                       $(document.createElement("tr"))
-                       .data("searchDetails", {name: result.entry, url: result.url})
-                       .data("index", i)
-                       .append($(document.createElement("td")).html(result.entry))
-                       .append(
-                               $(document.createElement("td"))
-                                       .addClass("entryInfo")
-                                       .html(result.txt + "&nbsp;&raquo;")
-                       )
-                       .mouseover( function() {
-                               $(currentTable.find("tr")[currentIndex]).removeClass("activeSearchResult");
-                               $(this).addClass("activeSearchResult");
-                               currentIndex = $(this).data("index");
-                       })
-                       .mouseout( function() {
-                               $(this).removeClass("activeSearchResult");
-                        })
-                       .click( function() {
-                               window.location = $(this).data("searchDetails")["url"];
-                       })
-               );
+               return 0;
        }
-       if(overflow > 0) {
+
+       // Display results in a popup table
+       var displayResultsTable = function(query, results) {
+               // Clear results table
+               if(currentTable) currentTable.remove();
+
+               // Build results table
+               currentIndex = -1;
+               currentTable = $(document.createElement("table"));
+
+               for(var i in results) {
+                       if(i > 10) {
+                               break;
+                       }
+                       var result = results[i];
+                       currentTable.append(
+                               $(document.createElement("tr"))
+                               .data("searchDetails", {name: result.entry, url: result.url})
+                               .data("index", i)
+                               .append($(document.createElement("td")).html(result.entry))
+                               .append(
+                                       $(document.createElement("td"))
+                                               .addClass("nitdoc-qs-info")
+                                               .html(result.txt + "&nbsp;&raquo;")
+                               )
+                               .mouseover( function() {
+                                       $(currentTable.find("tr")[currentIndex]).removeClass("nitdoc-qs-active");
+                                       $(this).addClass("nitdoc-qs-active");
+                                       currentIndex = $(this).data("index");
+                               })
+                               .mouseout( function() {
+                                       $(this).removeClass("nitdoc-qs-active");
+                                })
+                               .click( function() {
+                                       window.location = $(this).data("searchDetails")["url"];
+                               })
+                       );
+               }
                currentTable.append(
-                       $("<tr class='overflow'>")
+                       $("<tr class='nitdoc-qs-overflow'>")
                        .append(
                                $("<td colspan='2'>")
-                               .append(
-                                       $("<a href='#' title='Show all results' data-query='"+ query +"'>" + overflow + " more results for '" + query + "'</a>")
-                                       .click(function() {
-                                               window.location = "search.html#q=" + $(this).attr("data-query");
-                                               if(window.location.href.indexOf("search.html") > -1) {
-                                                       location.reload();
-                                               }
-                                       })
-                               )
+                               .html("Best results for '" + query + "'")
                        )
                );
-       }
-       // Initialize table properties
-       currentTable.attr("id", "searchTable");
-       currentTable.css("position", "absolute");
-       currentTable.width($("#search").outerWidth());
-       $("body").append(currentTable);
-       currentTable.offset({left: $("#search").offset().left + ($("#search").outerWidth() - currentTable.outerWidth()), top: $("#search").offset().top + $("#search").outerHeight()});
-       // Preselect first entry
-       if(currentTable.find("tr").length > 0) {
-               currentIndex = 0;
-               $(currentTable.find("tr")[currentIndex]).addClass("activeSearchResult");
-               $("#search").focus();
-       }
-}
 
-// Select the previous result
-Nitdoc.QuickSearch.selectPrevResult = function() {
-       // If already on first result, focus search input
-       if(currentIndex == 0) {
-               $("#search").val($(currentTable.find("tr")[currentIndex]).data("searchDetails").name);
-               $("#search").focus();
-       // Else select previous result
-       } else if(currentIndex > 0) {
-               $(currentTable.find("tr")[currentIndex]).removeClass("activeSearchResult");
-               currentIndex--;
-               $(currentTable.find("tr")[currentIndex]).addClass("activeSearchResult");
-               $("#search").val($(currentTable.find("tr")[currentIndex]).data("searchDetails").name);
-               $("#search").focus();
+               // Initialize table properties
+               currentTable.attr("id", "nitdoc-qs-table");
+               currentTable.css("position", "absolute");
+               currentTable.width(searchField.outerWidth());
+               $("body").append(currentTable);
+               currentTable.offset({left: searchField.offset().left + (searchField.outerWidth() - currentTable.outerWidth()), top: searchField.offset().top + searchField.outerHeight()});
+               // Preselect first entry
+               if(currentTable.find("tr").length > 0) {
+                       currentIndex = 0;
+                       $(currentTable.find("tr")[currentIndex]).addClass("nitdoc-qs-active");
+                       searchField.focus();
+               }
        }
-}
 
-// Select the next result
-Nitdoc.QuickSearch.selectNextResult = function() {
-       if(currentIndex < currentTable.find("tr").length - 1) {
-               if($(currentTable.find("tr")[currentIndex + 1]).hasClass("overflow")) {
-                       return;
+       // Select the previous result on current table
+       var selectPrevResult = function() {
+               // If already on first result, focus search input
+               if(currentIndex == 0) {
+                       searchField.val($(currentTable.find("tr")[currentIndex]).data("searchDetails").name);
+                       searchField.focus();
+               // Else select previous result
+               } else if(currentIndex > 0) {
+                       $(currentTable.find("tr")[currentIndex]).removeClass("nitdoc-qs-active");
+                       currentIndex--;
+                       $(currentTable.find("tr")[currentIndex]).addClass("nitdoc-qs-active");
+                       searchField.val($(currentTable.find("tr")[currentIndex]).data("searchDetails").name);
+                       searchField.focus();
                }
-               $(currentTable.find("tr")[currentIndex]).removeClass("activeSearchResult");
-               currentIndex++;
-               $(currentTable.find("tr")[currentIndex]).addClass("activeSearchResult");
-               $("#search").val($(currentTable.find("tr")[currentIndex]).data("searchDetails").name);
-               $("#search").focus();
        }
-}
 
-// Load selected search result
-Nitdoc.QuickSearch.goToResult = function() {
-       if(currentIndex > -1) {
-               window.location = $(currentTable.find("tr")[currentIndex]).data("searchDetails").url;
-               return;
+       // Select the next result on current table
+       var selectNextResult = function() {
+               if(currentIndex < currentTable.find("tr").length - 1) {
+                       if($(currentTable.find("tr")[currentIndex + 1]).hasClass("nitdoc-qs-overflow")) {
+                               return;
+                       }
+                       $(currentTable.find("tr")[currentIndex]).removeClass("nitdoc-qs-active");
+                       currentIndex++;
+                       $(currentTable.find("tr")[currentIndex]).addClass("nitdoc-qs-active");
+                       searchField.val($(currentTable.find("tr")[currentIndex]).data("searchDetails").name);
+                       searchField.focus();
+               }
        }
 
-       if($("#search").val().length == 0) { return; }
+       // Load selected search result page
+       var goToResult = function() {
+               if(currentIndex > -1) {
+                       window.location = $(currentTable.find("tr")[currentIndex]).data("searchDetails").url;
+                       return;
+               }
 
-       window.location = "search.html#q=" + $("#search").val();
-       if(window.location.href.indexOf("search.html") > -1) {
-               location.reload();
+               if(searchField.val().length == 0) { return; }
+
+               window.location = "search.html#q=" + searchField.val();
+               if(window.location.href.indexOf("search.html") > -1) {
+                       location.reload();
+               }
        }
-}
 
-// Close the QuickSearch results
-Nitdoc.QuickSearch.close = function(target) {
-       if(target != $("#search")[0] && target != $("#searchTable")[0]) {
-               if(currentTable != null) {
-                       currentTable.remove();
-                       currentTable = null;
+       // Close the results table
+       closeResultsTable = function(target) {
+               if(target != searchField && target != currentTable) {
+                       if(currentTable != null) {
+                               currentTable.remove();
+                               currentTable = null;
+                       }
                }
        }
-}
 
-/* Utils */
+       // Public interface
+       var quicksearch = {
+               enableQuickSearch: enableQuickSearch,
+               doKeyAction: doKeyAction,
+               closeResultsTable: closeResultsTable
+       };
+
+       return quicksearch;
+}();
+
+$(document).ready(function() {
+       Nitdoc.QuickSearch.enableQuickSearch("nav.main ul");
+});
+
+/*
+ * Utils
+ */
 
 // Calculate levenshtein distance beetween two strings
 // see: http://en.wikipedia.org/wiki/Levenshtein_distance
@@ -314,3 +322,4 @@ String.prototype.dice = function(other) {
        }
        return (2.0 * intersection) / (length1 + length2);
 }
+
diff --git a/share/ni_nitdoc/styles/Nitdoc.QuickSearch.css b/share/ni_nitdoc/styles/Nitdoc.QuickSearch.css
new file mode 100644 (file)
index 0000000..09cdaec
--- /dev/null
@@ -0,0 +1,63 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+   http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+   Documentation generator for the nit language.\r
+   Generate API documentation in HTML format from nit source code.\r
+*/\r
+\r
+/* \r
+ * Nitdoc Quick Search JS module \r
+ */\r
+\r
+#nitdoc-qs-field {\r
+       width: 300px;\r
+}\r
+\r
+#nitdoc-qs-field.nitdoc-qs-notused {\r
+       color: #999;\r
+       font-style: italic;\r
+}\r
+\r
+#nitdoc-qs-table {\r
+       background-color: #FFFFFF;\r
+       border: 1px solid #E0E0E0;\r
+       border-spacing: 0px;\r
+       z-index: 10; /* the menu must be over the rest of the page. */\r
+}\r
+\r
+#nitdoc-qs-table .nitdoc-qs-active {\r
+       cursor: pointer;\r
+       background: #EEE;\r
+}\r
+\r
+#nitdoc-qs-table td {\r
+       white-space: nowrap;\r
+       overflow: hidden;\r
+       line-height: 22px;\r
+       padding: 2px;\r
+       width: 25%;\r
+}\r
+\r
+#nitdoc-qs-table td.nitdoc-qs-info {\r
+       color: #0D8921;\r
+       font-size: small;\r
+       width: 75%;\r
+       text-align: right;\r
+}\r
+\r
+#nitdoc-qs-table tr.nitdoc-qs-overflow td {\r
+       text-align: center;\r
+       background-color: #E0E0E0;\r
+}\r
+\r
index f371529..8e38d25 100644 (file)
@@ -416,44 +416,6 @@ nav.main form {
        float: right;\r
 }\r
 \r
-/* Quick Search */\r
-\r
-#search {\r
-       width: 300px;\r
-}\r
-\r
-#searchTable {\r
-       background-color: #FFFFFF;\r
-       border: 1px solid #E0E0E0;\r
-       border-spacing: 0px;\r
-       z-index: 10; /* the menu must be over the rest of the page. */\r
-}\r
-\r
-#searchTable .activeSearchResult {\r
-       cursor: pointer;\r
-       background: #EEE;\r
-}\r
-\r
-#searchTable td {\r
-       white-space: nowrap;\r
-       overflow: hidden;\r
-       line-height: 22px;\r
-       padding: 2px;\r
-       width: 25%;\r
-}\r
-\r
-#searchTable td.entryInfo {\r
-       color: #0D8921;\r
-       font-size: small;\r
-       width: 75%;\r
-       text-align: right;\r
-}\r
-\r
-#searchTable tr.overflow td {\r
-       text-align: center;\r
-       background-color: #E0E0E0;\r
-}\r
-\r
 /* New comments style */\r
 \r
 .content .nitdoc {\r
index ff6f12c..36b98df 100644 (file)
@@ -163,7 +163,7 @@ class NitdocContext
 
        private fun quicksearch_list do
                var file = new OFStream.open("{output_dir.to_s}/quicksearch-list.js")
-               file.write("var entries = \{ ")
+               file.write("var nitdocQuickSearchRawList = \{ ")
                for mmodule in model.mmodules do
                        file.write("\"{mmodule.name}\": [")
                        file.write("\{txt: \"{mmodule.full_name}\", url:\"{mmodule.url}\" \},")
@@ -212,12 +212,13 @@ abstract class NitdocPage
                append("<script type='text/javascript' src='scripts/ZeroClipboard.min.js'></script>")
                append("<script type='text/javascript' src='scripts/Nitdoc.UI.js'></script>")
                append("<script type='text/javascript' src='scripts/Markdown.Converter.js'></script>")
-               append("<script type='text/javascript' src='quicksearch-list.js'></script>")
                append("<script type='text/javascript' src='scripts/base64.js'></script>")
                append("<script type='text/javascript' src='scripts/github.js'></script>")
+               append("<script type='text/javascript' src='quicksearch-list.js'></script>")
                append("<script type='text/javascript' src='scripts/Nitdoc.QuickSearch.js'></script>")
                append("<link rel='stylesheet' href='styles/main.css' type='text/css' media='screen'/>")
                append("<link rel='stylesheet' href='styles/Nitdoc.UI.css' type='text/css' media='screen'/>")
+               append("<link rel='stylesheet' href='styles/Nitdoc.QuickSearch.css' type='text/css' media='screen'/>")
                append("<link rel='stylesheet' href='styles/github.css' type='text/css' media='screen'/>")
                var title = ""
                if ctx.opt_custom_title.value != null then