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
22 $
.widget("nitdoc.quicksearch", {
25 list
: {}, // List of raw results generated by nitdoc tool
29 tableID
: "nitdoc-qs-table",
31 "position": "absolute"
33 rowClass
: "nitdoc-qs-row",
34 rowCatClass
: "nitdoc-qs-cat",
35 rowSubClass
: "nitdoc-qs-sub",
36 rowActiveClass
: "nitdoc-qs-active",
37 rowOverflowClass
: "nitdoc-qs-overflow",
38 rowOverflowActive
: "nitdoc-qs-overflow-active",
39 rowNoResultClass
: "nitdoc-qs-noresult",
40 overflowUpHtml
: "▲",
41 overflowDownHtml
: "▼",
42 noresultText
: "Sorry, there is no match, best results are:",
43 infoClass
: "nitdoc-qs-info",
44 gotoPage
: "search.html",
50 this.element
.attr(this.options
.fieldAttrs
);
52 this._on(this.element
, {
53 "keydown": this._doKeyDown
,
54 "keyup": this._doKeyUp
,
55 "input": this._doInput
57 // add result table element once
58 this._table
= $
("<table/>")
59 .attr("id", this.options
.tableID
)
60 .css(this.options
.tableCSS
)
61 .css("min-width", this.element
.outerWidth());
62 $
("body").append(this._table
);
63 // make table disappear when a click occurs outside
64 $
(document
).click($
.proxy(this.closeTable
, this));
69 _doKeyDown
: function(event
) {
70 switch(event
.keyCode
) {
82 _doKeyUp
: function(event
) {
83 switch(event
.keyCode
) {
94 default: // Other keys
99 _doInput
: function(event
) {
100 Utils
.delayEvent($
.proxy(this.search
, this));
105 _getResults
: function(query
) {
107 results
.matches
= [];
108 for(var entry
in this.options
.list
) {
109 if(!entry
.startsWith(query
, true)) {
114 entries
: this.options
.list
[entry]
116 results
.matches
[results
.matches
.length
] = cat
;
120 } else if(entry
.toUpperCase() == query
.toUpperCase()) {
123 cat
.rank
= 1 + query
.dice(entry
);
126 results
.matches
.sort(this._rankSorter
);
127 results
.partials
= new Array();
128 if(results
.matches
.length
== 0) {
129 for(var entry
in this.options
.list
) {
132 entries
: this.options
.list
[entry]
134 cat
.rank
= query
.dice(entry
);
136 results
.partials
[results
.partials
.length
] = cat
;
139 results
.partials
.sort(this._rankSorter
);
144 _rankSorter
: function(a
, b
){
145 if(a
.rank
< b
.rank
) {
147 } else if(a
.rank
> b
.rank
) {
156 var query
= this.element
.val();
158 var results
= this._getResults(query
);
159 this.openTable(query
, results
);
163 openTable
: function(query
, results
) {
168 var resultSet
= results
.matches
;
169 if(resultSet
.length
== 0) {
170 resultSet
= results
.partials
173 for(var i
in resultSet
) {
174 var cat
= resultSet
[i];
175 var result
= cat
.entries
[0];
176 this.addRow(cat
.name
, result
.txt
, result
.url
, this.options
.rowCatClass
)
177 for(var j
= 1; j
< cat
.entries
.length
; j
++) {
178 var result
= cat
.entries
[j];
179 this.addRow(cat
.name
, result
.txt
, result
.url
, this.options
.rowSubClass
)
183 if(this._rows
.length
>= this.options
.maxSize
) {
184 this.addOverflowUp();
185 this.addOverflowDown();
187 if(results
.matches
.length
== 0) {
188 this.addNoResultRow();
191 if(resultSet
.length
> 0) {
195 this._autosizeTable();
198 closeTable
: function(target
) {
199 if(target
!= this.element
&& target
!= this._table
) {
204 addRow
: function(name
, txt
, url
, cls
) {
206 .addClass(this.options
.rowClass
)
207 .data("searchDetails", {name
: name
, url
: url
})
208 .data("index", this._rows
.length
)
216 .html(txt
+ " »")
217 .addClass(this.options
.infoClass
)
219 .mouseover($
.proxy(this._mouseOverRow
, this))
220 .click($
.proxy(this._clickRow
, this))
221 this._rows
.push(row
);
222 if(this._rows
.length
>= this.options
.maxSize
) {
225 this._table
.append(row
);
228 addOverflowUp
: function() {
231 .addClass(this.options
.rowOverflowClass
)
235 .html(this.options
.overflowUpHtml
)
237 .click($
.proxy(this._clickPrev
, this))
241 addOverflowDown
: function() {
244 .addClass(this.options
.rowOverflowClass
)
245 .addClass(this.options
.rowOverflowActive
)
249 .html(this.options
.overflowDownHtml
)
251 .click($
.proxy(this._clickNext
, this))
255 addNoResultRow
: function() {
258 .addClass(this.options
.rowNoResultClass
)
261 .attr("colspan", "2")
262 .text(this.options
.noresultText
)
267 _autosizeTable
: function() {
268 this._table
.position({
275 _hasIndex
: function(index
) {
276 return index
>= 0 && index
< this._rows
.length
;
279 _hasPrev
: function(index
) {
280 return index
- 1 >= 0;
283 _hasNext
: function(index
) {
284 return index
+ 1 < this._rows
.length
;
287 _setIndex
: function(index
) {
288 if(this._hasIndex(this._index
)) {
289 this._rows
[this._index
].removeClass(this.options
.rowActiveClass
);
292 if(this._hasIndex(this._index
)) {
293 this._rows
[this._index
].addClass(this.options
.rowActiveClass
);
297 _selectPrev
: function() {
298 if(this._hasPrev(this._index
)) {
299 this._setIndex(this._index
- 1);
300 if(!this._rows
[this._index
].is(":visible")) {
301 this._table
.find("tr." + this.options
.rowClass
+ ":visible").last().hide();
302 this._table
.find("tr." + this.options
.rowOverflowClass
).addClass(this.options
.rowOverflowActive
);
303 this._rows
[this._index
].show();
304 if(!this._hasPrev(this._index
)) {
305 this._table
.find("tr." + this.options
.rowOverflowClass
).removeClass(this.options
.rowOverflowActive
);
307 this._autosizeTable();
312 _selectNext
: function() {
313 if(this._hasNext(this._index
)) {
314 this._setIndex(this._index
+ 1);
315 if(!this._rows
[this._index
].is(":visible")) {
316 this._table
.find("tr." + this.options
.rowClass
+ ":visible").first().hide();
317 this._table
.find("tr." + this.options
.rowOverflowClass
).addClass(this.options
.rowOverflowActive
);
318 this._rows
[this._index
].show();
319 if(!this._hasNext(this._index
)) {
320 this._table
.find("tr." + this.options
.rowOverflowClass
).removeClass(this.options
.rowOverflowActive
);
322 this._autosizeTable();
327 // Load selected search result page
328 _loadResult
: function() {
329 if(this._index
> -1) {
330 window
.location
= this._rows
[this._index
].data("searchDetails").url
;
333 if(this.element
.val().length
== 0) { return; }
335 window
.location
= this.options
.gotoPage
+ "#q=" + this.element
.val();
336 if(window
.location
.href
.indexOf(this.options
.gotoPage
) > -1) {
343 _clickNext
: function(event
) {
344 event
.stopPropagation();
348 _clickPrev
: function(event
) {
349 event
.stopPropagation();
353 _clickRow
: function(event
) {
354 window
.location
= $
(event
.currentTarget
).data("searchDetails")["url"];
357 _mouseOverRow
: function(event
) {
358 this._setIndex($
(event
.currentTarget
).data("index"));
362 var searchField
= $
("<input/>")
363 .addClass("form-control input-sm")
365 id
: "nitdoc-qs-field",
367 placeholder
: "Search..."
370 $
("#topmenu-collapse").append(
372 .addClass("navbar-form navbar-right")
375 .addClass("form-group")
380 searchField
.quicksearch({
381 list
: this.nitdocQuickSearchRawList