1 /* This file is part of NIT ( http://www.nitlanguage.org ).
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
7 http://www.apache.org/licenses/LICENSE-2.0
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
15 Documentation generator for the nit language.
16 Generate API documentation in HTML format from nit source code.
19 var Nitdoc
= Nitdoc ||
{};
22 * Nitdoc QuickSearch module
26 Nitdoc
.QuickSearch
= function() {
27 var rawList
= nitdocQuickSearchRawList
; // List of raw resulsts generated by nitdoc tool
28 var searchField
= null; // <input:text> search field
29 var currentTable
= null; // current search results <table>
30 var currentIndex
= -1; // current cursor position into search results table
32 // Enable QuickSearch plugin
33 var enableQuickSearch
= function(containerSelector
) {
34 searchField
= $
(document
.createElement("input"))
36 id
: "nitdoc-qs-field",
39 value
: "quick search..."
41 .addClass("nitdoc-qs-field-notused")
42 .keydown(function(event
) {
43 return Nitdoc
.QuickSearch
.doKeyDownAction(event
.keyCode
);
45 .keyup(function(event
) {
46 Nitdoc
.QuickSearch
.doKeyUpAction(event
.keyCode
);
48 .focusout(function() {
49 if($
(this).val() == "") {
50 $
(this).addClass("nitdoc-qs-field-notused");
51 $
(this).val("quick search...");
55 if($
(this).val() == "quick search...") {
56 $
(this).removeClass("nitdoc-qs-field-notused");
61 $
(containerSelector
).append(
62 $
(document
.createElement("li"))
63 .attr("id", "nitdoc-qs-li")
67 // Close quicksearch list on click
68 $
(document
).click(function(e
) {
69 Nitdoc
.QuickSearch
.closeResultsTable();
73 var doKeyDownAction
= function(key
) {
86 var doKeyUpAction
= function(key
) {
102 default: // Other keys
103 var query
= searchField
.val();
107 var results
= getResults(query
);
108 displayResultsTable(query
, results
);
113 // Get results corresponding to search query
114 var getResults
= function(query
) {
116 results
.matches
= new Array();
117 for(var entry
in rawList
) {
118 if(!entry
.startsWith(query
, true)) {
121 var cat
= new Object();
123 cat
.entries
= rawList
[entry];
124 results
.matches
[results
.matches
.length
] = cat
;
128 } else if(entry
.toUpperCase() == query
.toUpperCase()) {
131 cat
.rank
= 1 + query
.dice(entry
);
134 results
.matches
.sort(rankSorter
);
135 results
.partials
= new Array();
136 if(results
.matches
.length
== 0) {
137 for(var entry
in rawList
) {
138 var cat
= new Object();
140 cat
.entries
= rawList
[entry];
141 cat
.rank
= query
.dice(entry
);
143 results
.partials
[results
.partials
.length
] = cat
;
146 results
.partials
.sort(rankSorter
);
151 // Sort an array of results by rank
152 var rankSorter
= function(a
, b
){
153 if(a
.rank
< b
.rank
) {
155 } else if(a
.rank
> b
.rank
) {
161 // Display results in a popup table
162 var displayResultsTable
= function(query
, results
) {
163 // Clear results table
164 if(currentTable
) currentTable
.remove();
166 // Build results table
168 currentTable
= $
(document
.createElement("table"));
169 currentTable
.attr("id", "nitdoc-qs-table");
170 currentTable
.css("position", "absolute");
171 currentTable
.width(searchField
.outerWidth());
176 if(results
.matches
.length
== 0) {
177 resultSet
= results
.partials
179 resultSet
= results
.matches
181 for(var i
in resultSet
) {
182 var cat
= resultSet
[i];
183 var result
= cat
.entries
[0];
185 addResultRow(count
, cat
.name
, result
.txt
, result
.url
, "nitdoc-qs-cat")
186 if(count
>= maxSize
) {
187 currentTable
.find("tbody").children().last().hide();
191 for(var j
= 1; j
< cat
.entries
.length
; j
++) {
192 var result
= cat
.entries
[j];
193 addResultRow(count
, cat
.name
, result
.txt
, result
.url
, "nitdoc-qs-sub")
194 if(count
>= maxSize
) {
195 currentTable
.find("tr.nitdoc-qs-row").last().hide();
200 if(count
>= maxSize
) {
201 currentTable
.prepend(
202 $
(document
.createElement("tr"))
203 .addClass("nitdoc-qs-overflow-up")
204 .addClass("nitdoc-qs-overflow-inactive")
206 $
(document
.createElement("td"))
210 .click( function(e
) {
216 $
(document
.createElement("tr"))
217 .addClass("nitdoc-qs-overflow-down")
218 .addClass(count
>= maxSize ?
"nitdoc-qs-overflow-active" : "nitdoc-qs-overflow-inactive")
220 $
(document
.createElement("td"))
224 .click( function(e
) {
231 if(results
.matches
.length
== 0) {
232 currentTable
.prepend(
233 $
("<tr class='nitdoc-qs-noresult'>")
235 $
("<td colspan='2'>")
236 .html("Sorry, there is no match, best results are:")
242 $
("body").append(currentTable
);
243 resizeResultsTable();
244 if(currentTable
.find("tr").length
> 0) {
249 // adds a result row to the current result table
250 var addResultRow
= function(index
, name
, txt
, url
, cls
) {
252 $
(document
.createElement("tr"))
253 .addClass("nitdoc-qs-row")
254 .data("searchDetails", {name
: name
, url
: url
})
255 .data("index", index
)
257 $
(document
.createElement("td")).html(name
)
261 $
(document
.createElement("td"))
262 .addClass("nitdoc-qs-info")
263 .html(txt
+ " »")
265 .mouseover( function() {
266 setIndex($
(this).data("index"));
268 .mouseout( function() {
269 $
(this).removeClass("nitdoc-qs-active");
272 window
.location
= $
(this).data("searchDetails")["url"];
277 // adapts result table to content
278 var resizeResultsTable
= function() {
279 currentTable
.offset({
280 left
: searchField
.offset().left
+ (searchField
.outerWidth() - currentTable
.outerWidth()),
281 top
: searchField
.offset().top
+ searchField
.outerHeight()
285 // select row at index
286 var setIndex
= function(index
) {
287 $
(currentTable
.find("tr.nitdoc-qs-row")[currentIndex]).removeClass("nitdoc-qs-active");
288 currentIndex
= index
;
289 var currentRow
= $
(currentTable
.find("tr.nitdoc-qs-row")[currentIndex]);
290 currentRow
.addClass("nitdoc-qs-active");
291 //searchField.val(currentRow.data("searchDetails").name);
294 var hasPrev
= function(index
) {
295 return index
- 1 >= 0;
298 var hasNext
= function(index
) {
299 return index
+ 1 < currentTable
.find("tr.nitdoc-qs-row").length
;
302 var selectPrevResult
= function() {
303 if(hasPrev(currentIndex
)) {
304 setIndex(currentIndex
- 1);
305 if(!$
(currentTable
.find("tr.nitdoc-qs-row")[currentIndex]).is(":visible")) {
306 currentTable
.find("tr.nitdoc-qs-row:visible").last().hide();
307 currentTable
.find("tr.nitdoc-qs-overflow-down").addClass("nitdoc-qs-overflow-active");
308 $
(currentTable
.find("tr.nitdoc-qs-row")[currentIndex]).show();
309 if(!hasPrev(currentIndex
)) {
310 currentTable
.find("tr.nitdoc-qs-overflow-up").removeClass("nitdoc-qs-overflow-active");
312 resizeResultsTable();
317 var selectNextResult
= function() {
318 if(hasNext(currentIndex
)) {
319 setIndex(currentIndex
+ 1);
320 if(!$
(currentTable
.find("tr.nitdoc-qs-row")[currentIndex]).is(":visible")) {
321 currentTable
.find("tr.nitdoc-qs-row:visible").first().hide();
322 currentTable
.find("tr.nitdoc-qs-overflow-up").addClass("nitdoc-qs-overflow-active");
323 $
(currentTable
.find("tr.nitdoc-qs-row")[currentIndex]).show();
324 if(!hasNext(currentIndex
)) {
325 currentTable
.find("tr.nitdoc-qs-overflow-down").removeClass("nitdoc-qs-overflow-active");
327 resizeResultsTable();
332 // Load selected search result page
333 var goToResult
= function() {
334 if(currentIndex
> -1) {
335 window
.location
= $
(currentTable
.find("tr.nitdoc-qs-row")[currentIndex]).data("searchDetails").url
;
339 if(searchField
.val().length
== 0) { return; }
341 window
.location
= "search.html#q=" + searchField
.val();
342 if(window
.location
.href
.indexOf("search.html") > -1) {
347 // Close the results table
348 closeResultsTable
= function(target
) {
349 if(target
!= searchField
&& target
!= currentTable
) {
350 if(currentTable
!= null) {
351 currentTable
.remove();
359 enableQuickSearch
: enableQuickSearch
,
360 doKeyUpAction
: doKeyUpAction
,
361 doKeyDownAction
: doKeyDownAction
,
362 closeResultsTable
: closeResultsTable
368 $
(document
).ready(function() {
369 Nitdoc
.QuickSearch
.enableQuickSearch("nav.main ul");
376 String
.prototype.startsWith
= function(prefix
, caseSensitive
) {
378 return this.toUpperCase().indexOf(prefix
.toUpperCase()) === 0;
380 return this.indexOf(prefix
) === 0;
383 // Compare two strings using Sorensen-Dice Coefficient
384 // see: http://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient
385 String
.prototype.dice
= function(other
) {
386 var length1
= this.length
- 1;
387 var length2
= other
.length
- 1;
388 if(length1
< 1 || length2
< 1) return 0;
391 for(var i
= 0; i
< length2
; i
++) {
392 bigrams2
.push(other
.substr(i
, 2));
395 var intersection
= 0;
396 for(var i
= 0; i
< length1
; i
++) {
397 var bigram1
= this.substr(i
, 2);
398 for(var j
= 0; j
< length2
; j
++) {
399 if(bigram1
== bigrams2
[j]) {
406 return (2.0 * intersection
) / (length1
+ length2
);