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.
20 * Nitdoc QuickSearch widget
27 ], function($
, ui
, utils
) {
28 $
.widget("nitdoc.quicksearch", {
31 list
: {}, // List of raw results generated by nitdoc tool
32 fieldNotUsedClass
: "nitdoc-qs-field-notused",
35 value
: "quick search..."
37 tableID
: "nitdoc-qs-table",
39 "position": "absolute"
41 rowClass
: "nitdoc-qs-row",
42 rowCatClass
: "nitdoc-qs-cat",
43 rowSubClass
: "nitdoc-qs-sub",
44 rowActiveClass
: "nitdoc-qs-active",
45 rowOverflowClass
: "nitdoc-qs-overflow",
46 rowOverflowActive
: "nitdoc-qs-overflow-active",
47 rowNoResultClass
: "nitdoc-qs-noresult",
48 overflowUpHtml
: "▲",
49 overflowDownHtml
: "▼",
50 noresultText
: "Sorry, there is no match, best results are:",
51 infoClass
: "nitdoc-qs-info",
52 gotoPage
: "search.html",
58 .attr(this.options
.fieldAttrs
)
59 .addClass(this.options
.fieldNotUsedClass
)
60 .keydown($
.proxy(this._doKeyDown
, this))
61 .keyup($
.proxy(this._doKeyUp
, this))
62 .focusout($
.proxy(this._doFocusOut
, this))
63 .focusin($
.proxy(this._doFocusIn
, this));
65 this._table
= $
("<table/>")
66 .attr("id", this.options
.tableID
)
67 .css(this.options
.tableCSS
)
68 .css("min-width", this.element
.outerWidth());
69 $
("body").append(this._table
);
71 $
(document
).click($
.proxy(this.closeTable
, this));
76 _doKeyDown
: function(event
) {
77 switch(event
.keyCode
) {
89 _doKeyUp
: function(event
) {
90 switch(event
.keyCode
) {
101 default: // Other keys
102 utils
.delayEvent($
.proxy(this.search
, this));
107 _doFocusOut
: function() {
108 if(this.element
.val() == "") {
109 this.element
.addClass(this.options
.fieldNotUsedClass
);
110 this.element
.val(this.options
.fieldAttrs
.value
);
114 _doFocusIn
: function() {
115 if(this.element
.val() == this.options
.fieldAttrs
.value
) {
116 this.element
.removeClass(this.options
.fieldNotUsedClass
);
117 this.element
.val("");
123 _getResults
: function(query
) {
125 results
.matches
= [];
126 for(var entry
in this.options
.list
) {
127 if(!entry
.startsWith(query
, true)) {
132 entries
: this.options
.list
[entry]
134 results
.matches
[results
.matches
.length
] = cat
;
138 } else if(entry
.toUpperCase() == query
.toUpperCase()) {
141 cat
.rank
= 1 + query
.dice(entry
);
144 results
.matches
.sort(this._rankSorter
);
145 results
.partials
= new Array();
146 if(results
.matches
.length
== 0) {
147 for(var entry
in this.options
.list
) {
150 entries
: this.options
.list
[entry]
152 cat
.rank
= query
.dice(entry
);
154 results
.partials
[results
.partials
.length
] = cat
;
157 results
.partials
.sort(this._rankSorter
);
162 _rankSorter
: function(a
, b
){
163 if(a
.rank
< b
.rank
) {
165 } else if(a
.rank
> b
.rank
) {
174 var query
= this.element
.val();
176 var results
= this._getResults(query
);
177 this.openTable(query
, results
);
181 openTable
: function(query
, results
) {
186 var resultSet
= results
.matches
;
187 if(resultSet
.length
== 0) {
188 resultSet
= results
.partials
191 for(var i
in resultSet
) {
192 var cat
= resultSet
[i];
193 var result
= cat
.entries
[0];
194 this.addRow(cat
.name
, result
.txt
, result
.url
, this.options
.rowCatClass
)
195 for(var j
= 1; j
< cat
.entries
.length
; j
++) {
196 var result
= cat
.entries
[j];
197 this.addRow(cat
.name
, result
.txt
, result
.url
, this.options
.rowSubClass
)
201 if(this._rows
.length
>= this.options
.maxSize
) {
202 this.addOverflowUp();
203 this.addOverflowDown();
205 if(results
.matches
.length
== 0) {
206 this.addNoResultRow();
209 if(resultSet
.length
> 0) {
213 this._autosizeTable();
216 closeTable
: function(target
) {
217 if(target
!= this.element
&& target
!= this._table
) {
222 addRow
: function(name
, txt
, url
, cls
) {
224 .addClass(this.options
.rowClass
)
225 .data("searchDetails", {name
: name
, url
: url
})
226 .data("index", this._rows
.length
)
234 .html(txt
+ " »")
235 .addClass(this.options
.infoClass
)
237 .mouseover($
.proxy(this._mouseOverRow
, this))
238 .click($
.proxy(this._clickRow
, this))
239 this._rows
.push(row
);
240 if(this._rows
.length
>= this.options
.maxSize
) {
243 this._table
.append(row
);
246 addOverflowUp
: function() {
249 .addClass(this.options
.rowOverflowClass
)
253 .html(this.options
.overflowUpHtml
)
255 .click($
.proxy(this._clickPrev
, this))
259 addOverflowDown
: function() {
262 .addClass(this.options
.rowOverflowClass
)
263 .addClass(this.options
.rowOverflowActive
)
267 .html(this.options
.overflowDownHtml
)
269 .click($
.proxy(this._clickNext
, this))
273 addNoResultRow
: function() {
276 .addClass(this.options
.rowNoResultClass
)
279 .attr("colspan", "2")
280 .text(this.options
.noresultText
)
285 _autosizeTable
: function() {
286 this._table
.position({
293 _hasIndex
: function(index
) {
294 return index
>= 0 && index
< this._rows
.length
;
297 _hasPrev
: function(index
) {
298 return index
- 1 >= 0;
301 _hasNext
: function(index
) {
302 return index
+ 1 < this._rows
.length
;
305 _setIndex
: function(index
) {
306 if(this._hasIndex(this._index
)) {
307 this._rows
[this._index
].removeClass(this.options
.rowActiveClass
);
310 if(this._hasIndex(this._index
)) {
311 this._rows
[this._index
].addClass(this.options
.rowActiveClass
);
315 _selectPrev
: function() {
316 if(this._hasPrev(this._index
)) {
317 this._setIndex(this._index
- 1);
318 if(!this._rows
[this._index
].is(":visible")) {
319 this._table
.find("tr." + this.options
.rowClass
+ ":visible").last().hide();
320 this._table
.find("tr." + this.options
.rowOverflowClass
).addClass(this.options
.rowOverflowActive
);
321 this._rows
[this._index
].show();
322 if(!this._hasPrev(this._index
)) {
323 this._table
.find("tr." + this.options
.rowOverflowClass
).removeClass(this.options
.rowOverflowActive
);
325 this._autosizeTable();
330 _selectNext
: function() {
331 if(this._hasNext(this._index
)) {
332 this._setIndex(this._index
+ 1);
333 if(!this._rows
[this._index
].is(":visible")) {
334 this._table
.find("tr." + this.options
.rowClass
+ ":visible").first().hide();
335 this._table
.find("tr." + this.options
.rowOverflowClass
).addClass(this.options
.rowOverflowActive
);
336 this._rows
[this._index
].show();
337 if(!this._hasNext(this._index
)) {
338 this._table
.find("tr." + this.options
.rowOverflowClass
).removeClass(this.options
.rowOverflowActive
);
340 this._autosizeTable();
345 // Load selected search result page
346 _loadResult
: function() {
347 if(this._index
> -1) {
348 window
.location
= this._rows
[this._index
].data("searchDetails").url
;
351 if(this.element
.val().length
== 0) { return; }
353 window
.location
= this.options
.gotoPage
+ "#q=" + this.element
.val();
354 if(window
.location
.href
.indexOf(this.options
.gotoPage
) > -1) {
361 _clickNext
: function(event
) {
362 event
.stopPropagation();
366 _clickPrev
: function(event
) {
367 event
.stopPropagation();
371 _clickRow
: function(event
) {
372 window
.location
= $
(event
.currentTarget
).data("searchDetails")["url"];
375 _mouseOverRow
: function(event
) {
376 this._setIndex($
(event
.currentTarget
).data("index"));
380 var searchField
= $
("<input/>")
381 .addClass("nitdoc-qs-field-notused")
383 id
: "nitdoc-qs-field",
387 $
("nav.main ul").append(
389 .attr("id", "nitdoc-qs-li")
393 searchField
.quicksearch({
394 list
: this.nitdocQuickSearchRawList