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
35 tableID
: "nitdoc-qs-table",
37 "position": "absolute"
39 rowClass
: "nitdoc-qs-row",
40 rowCatClass
: "nitdoc-qs-cat",
41 rowSubClass
: "nitdoc-qs-sub",
42 rowActiveClass
: "nitdoc-qs-active",
43 rowOverflowClass
: "nitdoc-qs-overflow",
44 rowOverflowActive
: "nitdoc-qs-overflow-active",
45 rowNoResultClass
: "nitdoc-qs-noresult",
46 overflowUpHtml
: "▲",
47 overflowDownHtml
: "▼",
48 noresultText
: "Sorry, there is no match, best results are:",
49 infoClass
: "nitdoc-qs-info",
50 gotoPage
: "search.html",
56 this.element
.attr(this.options
.fieldAttrs
);
58 this._on(this.element
, {
59 "keydown": this._doKeyDown
,
60 "keyup": this._doKeyUp
,
61 "input": this._doInput
63 // add result table element once
64 this._table
= $
("<table/>")
65 .attr("id", this.options
.tableID
)
66 .css(this.options
.tableCSS
)
67 .css("min-width", this.element
.outerWidth());
68 $
("body").append(this._table
);
69 // make table disappear when a click occurs outside
70 $
(document
).click($
.proxy(this.closeTable
, this));
75 _doKeyDown
: function(event
) {
76 switch(event
.keyCode
) {
88 _doKeyUp
: function(event
) {
89 switch(event
.keyCode
) {
100 default: // Other keys
105 _doInput
: function(event
) {
106 utils
.delayEvent($
.proxy(this.search
, this));
111 _getResults
: function(query
) {
113 results
.matches
= [];
114 for(var entry
in this.options
.list
) {
115 if(!entry
.startsWith(query
, true)) {
120 entries
: this.options
.list
[entry]
122 results
.matches
[results
.matches
.length
] = cat
;
126 } else if(entry
.toUpperCase() == query
.toUpperCase()) {
129 cat
.rank
= 1 + query
.dice(entry
);
132 results
.matches
.sort(this._rankSorter
);
133 results
.partials
= new Array();
134 if(results
.matches
.length
== 0) {
135 for(var entry
in this.options
.list
) {
138 entries
: this.options
.list
[entry]
140 cat
.rank
= query
.dice(entry
);
142 results
.partials
[results
.partials
.length
] = cat
;
145 results
.partials
.sort(this._rankSorter
);
150 _rankSorter
: function(a
, b
){
151 if(a
.rank
< b
.rank
) {
153 } else if(a
.rank
> b
.rank
) {
162 var query
= this.element
.val();
164 var results
= this._getResults(query
);
165 this.openTable(query
, results
);
169 openTable
: function(query
, results
) {
174 var resultSet
= results
.matches
;
175 if(resultSet
.length
== 0) {
176 resultSet
= results
.partials
179 for(var i
in resultSet
) {
180 var cat
= resultSet
[i];
181 var result
= cat
.entries
[0];
182 this.addRow(cat
.name
, result
.txt
, result
.url
, this.options
.rowCatClass
)
183 for(var j
= 1; j
< cat
.entries
.length
; j
++) {
184 var result
= cat
.entries
[j];
185 this.addRow(cat
.name
, result
.txt
, result
.url
, this.options
.rowSubClass
)
189 if(this._rows
.length
>= this.options
.maxSize
) {
190 this.addOverflowUp();
191 this.addOverflowDown();
193 if(results
.matches
.length
== 0) {
194 this.addNoResultRow();
197 if(resultSet
.length
> 0) {
201 this._autosizeTable();
204 closeTable
: function(target
) {
205 if(target
!= this.element
&& target
!= this._table
) {
210 addRow
: function(name
, txt
, url
, cls
) {
212 .addClass(this.options
.rowClass
)
213 .data("searchDetails", {name
: name
, url
: url
})
214 .data("index", this._rows
.length
)
222 .html(txt
+ " »")
223 .addClass(this.options
.infoClass
)
225 .mouseover($
.proxy(this._mouseOverRow
, this))
226 .click($
.proxy(this._clickRow
, this))
227 this._rows
.push(row
);
228 if(this._rows
.length
>= this.options
.maxSize
) {
231 this._table
.append(row
);
234 addOverflowUp
: function() {
237 .addClass(this.options
.rowOverflowClass
)
241 .html(this.options
.overflowUpHtml
)
243 .click($
.proxy(this._clickPrev
, this))
247 addOverflowDown
: function() {
250 .addClass(this.options
.rowOverflowClass
)
251 .addClass(this.options
.rowOverflowActive
)
255 .html(this.options
.overflowDownHtml
)
257 .click($
.proxy(this._clickNext
, this))
261 addNoResultRow
: function() {
264 .addClass(this.options
.rowNoResultClass
)
267 .attr("colspan", "2")
268 .text(this.options
.noresultText
)
273 _autosizeTable
: function() {
274 this._table
.position({
281 _hasIndex
: function(index
) {
282 return index
>= 0 && index
< this._rows
.length
;
285 _hasPrev
: function(index
) {
286 return index
- 1 >= 0;
289 _hasNext
: function(index
) {
290 return index
+ 1 < this._rows
.length
;
293 _setIndex
: function(index
) {
294 if(this._hasIndex(this._index
)) {
295 this._rows
[this._index
].removeClass(this.options
.rowActiveClass
);
298 if(this._hasIndex(this._index
)) {
299 this._rows
[this._index
].addClass(this.options
.rowActiveClass
);
303 _selectPrev
: function() {
304 if(this._hasPrev(this._index
)) {
305 this._setIndex(this._index
- 1);
306 if(!this._rows
[this._index
].is(":visible")) {
307 this._table
.find("tr." + this.options
.rowClass
+ ":visible").last().hide();
308 this._table
.find("tr." + this.options
.rowOverflowClass
).addClass(this.options
.rowOverflowActive
);
309 this._rows
[this._index
].show();
310 if(!this._hasPrev(this._index
)) {
311 this._table
.find("tr." + this.options
.rowOverflowClass
).removeClass(this.options
.rowOverflowActive
);
313 this._autosizeTable();
318 _selectNext
: function() {
319 if(this._hasNext(this._index
)) {
320 this._setIndex(this._index
+ 1);
321 if(!this._rows
[this._index
].is(":visible")) {
322 this._table
.find("tr." + this.options
.rowClass
+ ":visible").first().hide();
323 this._table
.find("tr." + this.options
.rowOverflowClass
).addClass(this.options
.rowOverflowActive
);
324 this._rows
[this._index
].show();
325 if(!this._hasNext(this._index
)) {
326 this._table
.find("tr." + this.options
.rowOverflowClass
).removeClass(this.options
.rowOverflowActive
);
328 this._autosizeTable();
333 // Load selected search result page
334 _loadResult
: function() {
335 if(this._index
> -1) {
336 window
.location
= this._rows
[this._index
].data("searchDetails").url
;
339 if(this.element
.val().length
== 0) { return; }
341 window
.location
= this.options
.gotoPage
+ "#q=" + this.element
.val();
342 if(window
.location
.href
.indexOf(this.options
.gotoPage
) > -1) {
349 _clickNext
: function(event
) {
350 event
.stopPropagation();
354 _clickPrev
: function(event
) {
355 event
.stopPropagation();
359 _clickRow
: function(event
) {
360 window
.location
= $
(event
.currentTarget
).data("searchDetails")["url"];
363 _mouseOverRow
: function(event
) {
364 this._setIndex($
(event
.currentTarget
).data("index"));
368 var searchField
= $
("<input/>")
369 .addClass("form-control input-sm")
371 id
: "nitdoc-qs-field",
373 placeholder
: "Search..."
376 $
("#topmenu-collapse").append(
378 .addClass("navbar-form navbar-right")
381 .addClass("form-group")
386 searchField
.quicksearch({
387 list
: this.nitdocQuickSearchRawList