blob: dd4552f7e154b008178c608a62385f981cf76e9b [file] [log] [blame]
The Android Open Source Project88b60792009-03-03 19:28:42 -08001var gSelectedIndex = -1;
2var gSelectedID = -1;
3var gMatches = new Array();
4var gLastText = "";
Roman Nurikaf232982010-04-13 16:23:42 -07005var ROW_COUNT = 20;
The Android Open Source Project88b60792009-03-03 19:28:42 -08006var gInitialized = false;
7var DEFAULT_TEXT = "search developer docs";
8
9function set_row_selected(row, selected)
10{
11 var c1 = row.cells[0];
12 // var c2 = row.cells[1];
13 if (selected) {
14 c1.className = "jd-autocomplete jd-selected";
15 // c2.className = "jd-autocomplete jd-selected jd-linktype";
16 } else {
17 c1.className = "jd-autocomplete";
18 // c2.className = "jd-autocomplete jd-linktype";
19 }
20}
21
22function set_row_values(toroot, row, match)
23{
24 var link = row.cells[0].childNodes[0];
Roman Nurikaf232982010-04-13 16:23:42 -070025 link.innerHTML = match.__hilabel || match.label;
The Android Open Source Project88b60792009-03-03 19:28:42 -080026 link.href = toroot + match.link
27 // row.cells[1].innerHTML = match.type;
28}
29
30function sync_selection_table(toroot)
31{
32 var filtered = document.getElementById("search_filtered");
33 var r; //TR DOM object
34 var i; //TR iterator
35 gSelectedID = -1;
36
37 filtered.onmouseover = function() {
38 if(gSelectedIndex >= 0) {
39 set_row_selected(this.rows[gSelectedIndex], false);
40 gSelectedIndex = -1;
41 }
42 }
43
44 //initialize the table; draw it for the first time (but not visible).
45 if (!gInitialized) {
46 for (i=0; i<ROW_COUNT; i++) {
47 var r = filtered.insertRow(-1);
48 var c1 = r.insertCell(-1);
49 // var c2 = r.insertCell(-1);
50 c1.className = "jd-autocomplete";
51 // c2.className = "jd-autocomplete jd-linktype";
52 var link = document.createElement("a");
53 c1.onmousedown = function() {
54 window.location = this.firstChild.getAttribute("href");
55 }
56 c1.onmouseover = function() {
57 this.className = this.className + " jd-selected";
58 }
59 c1.onmouseout = function() {
60 this.className = "jd-autocomplete";
61 }
62 c1.appendChild(link);
63 }
64 /* var r = filtered.insertRow(-1);
65 var c1 = r.insertCell(-1);
66 c1.className = "jd-autocomplete jd-linktype";
67 c1.colSpan = 2; */
68 gInitialized = true;
69 }
70
71 //if we have results, make the table visible and initialize result info
72 if (gMatches.length > 0) {
73 document.getElementById("search_filtered_div").className = "showing";
74 var N = gMatches.length < ROW_COUNT ? gMatches.length : ROW_COUNT;
75 for (i=0; i<N; i++) {
76 r = filtered.rows[i];
77 r.className = "show-row";
78 set_row_values(toroot, r, gMatches[i]);
79 set_row_selected(r, i == gSelectedIndex);
80 if (i == gSelectedIndex) {
81 gSelectedID = gMatches[i].id;
82 }
83 }
84 //start hiding rows that are no longer matches
85 for (; i<ROW_COUNT; i++) {
86 r = filtered.rows[i];
87 r.className = "no-display";
88 }
89 //if there are more results we're not showing, so say so.
90/* if (gMatches.length > ROW_COUNT) {
91 r = filtered.rows[ROW_COUNT];
92 r.className = "show-row";
93 c1 = r.cells[0];
94 c1.innerHTML = "plus " + (gMatches.length-ROW_COUNT) + " more";
95 } else {
96 filtered.rows[ROW_COUNT].className = "hide-row";
97 }*/
98 //if we have no results, hide the table
99 } else {
100 document.getElementById("search_filtered_div").className = "no-display";
101 }
102}
103
104function search_changed(e, kd, toroot)
105{
106 var search = document.getElementById("search_autocomplete");
Roman Nurikaf232982010-04-13 16:23:42 -0700107 var text = search.value.replace(/(^ +)|( +$)/g, '');
The Android Open Source Project88b60792009-03-03 19:28:42 -0800108
109 // 13 = enter
Scott Main9033c122010-01-25 14:38:43 -0800110 if (e.keyCode == 13) {
The Android Open Source Project88b60792009-03-03 19:28:42 -0800111 document.getElementById("search_filtered_div").className = "no-display";
Scott Main9033c122010-01-25 14:38:43 -0800112 if (kd && gSelectedIndex >= 0) {
The Android Open Source Project88b60792009-03-03 19:28:42 -0800113 window.location = toroot + gMatches[gSelectedIndex].link;
114 return false;
Scott Main9033c122010-01-25 14:38:43 -0800115 } else if (gSelectedIndex < 0) {
116 return true;
The Android Open Source Project88b60792009-03-03 19:28:42 -0800117 }
118 }
119 // 38 -- arrow up
120 else if (kd && (e.keyCode == 38)) {
121 if (gSelectedIndex >= 0) {
122 gSelectedIndex--;
123 }
124 sync_selection_table(toroot);
125 return false;
126 }
127 // 40 -- arrow down
128 else if (kd && (e.keyCode == 40)) {
129 if (gSelectedIndex < gMatches.length-1
130 && gSelectedIndex < ROW_COUNT-1) {
131 gSelectedIndex++;
132 }
133 sync_selection_table(toroot);
134 return false;
135 }
136 else if (!kd) {
137 gMatches = new Array();
138 matchedCount = 0;
139 gSelectedIndex = -1;
Roman Nurikaf232982010-04-13 16:23:42 -0700140 for (var i=0; i<DATA.length; i++) {
The Android Open Source Project88b60792009-03-03 19:28:42 -0800141 var s = DATA[i];
Roman Nurikaf232982010-04-13 16:23:42 -0700142 if (text.length != 0 &&
143 s.label.toLowerCase().indexOf(text.toLowerCase()) != -1) {
The Android Open Source Project88b60792009-03-03 19:28:42 -0800144 gMatches[matchedCount] = s;
The Android Open Source Project88b60792009-03-03 19:28:42 -0800145 matchedCount++;
146 }
147 }
Roman Nurikaf232982010-04-13 16:23:42 -0700148 rank_autocomplete_results(text);
149 for (var i=0; i<gMatches.length; i++) {
150 var s = gMatches[i];
151 if (gSelectedID == s.id) {
152 gSelectedIndex = i;
153 }
154 }
155 highlight_autocomplete_result_labels(text);
The Android Open Source Project88b60792009-03-03 19:28:42 -0800156 sync_selection_table(toroot);
157 return true; // allow the event to bubble up to the search api
158 }
159}
160
Roman Nurikaf232982010-04-13 16:23:42 -0700161function rank_autocomplete_results(query) {
162 query = query || '';
163 if (!gMatches || !gMatches.length)
164 return;
165
166 // helper function that gets the last occurence index of the given regex
167 // in the given string, or -1 if not found
168 var _lastSearch = function(s, re) {
169 if (s == '')
170 return -1;
171 var l = -1;
172 var tmp;
173 while ((tmp = s.search(re)) >= 0) {
174 if (l < 0) l = 0;
175 l += tmp;
176 s = s.substr(tmp + 1);
177 }
178 return l;
179 };
180
181 // helper function that counts the occurrences of a given character in
182 // a given string
183 var _countChar = function(s, c) {
184 var n = 0;
185 for (var i=0; i<s.length; i++)
186 if (s.charAt(i) == c) ++n;
187 return n;
188 };
189
190 var queryLower = query.toLowerCase();
191 var queryAlnum = (queryLower.match(/\w+/) || [''])[0];
192 var partPrefixAlnumRE = new RegExp('\\b' + queryAlnum);
193 var partExactAlnumRE = new RegExp('\\b' + queryAlnum + '\\b');
194
195 var _resultScoreFn = function(result) {
196 // scores are calculated based on exact and prefix matches,
197 // and then number of path separators (dots) from the last
198 // match (i.e. favoring classes and deep package names)
199 var score = 1.0;
200 var labelLower = result.label.toLowerCase();
201 var t;
202 t = _lastSearch(labelLower, partExactAlnumRE);
203 if (t >= 0) {
204 // exact part match
205 var partsAfter = _countChar(labelLower.substr(t + 1), '.');
206 score *= 200 / (partsAfter + 1);
207 } else {
208 t = _lastSearch(labelLower, partPrefixAlnumRE);
209 if (t >= 0) {
210 // part prefix match
211 var partsAfter = _countChar(labelLower.substr(t + 1), '.');
212 score *= 20 / (partsAfter + 1);
213 }
214 }
215
216 return score;
217 };
218
219 for (var i=0; i<gMatches.length; i++) {
220 gMatches[i].__resultScore = _resultScoreFn(gMatches[i]);
221 }
222
223 gMatches.sort(function(a,b){
224 var n = b.__resultScore - a.__resultScore;
225 if (n == 0) // lexicographical sort if scores are the same
226 n = (a.label < b.label) ? -1 : 1;
227 return n;
228 });
229}
230
231function highlight_autocomplete_result_labels(query) {
232 query = query || '';
233 if (!gMatches || !gMatches.length)
234 return;
235
236 var queryLower = query.toLowerCase();
237 var queryAlnumDot = (queryLower.match(/[\w\.]+/) || [''])[0];
238 var queryRE = new RegExp(
239 '(' + queryAlnumDot.replace(/\./g, '\\.') + ')', 'ig');
240 for (var i=0; i<gMatches.length; i++) {
241 gMatches[i].__hilabel = gMatches[i].label.replace(
242 queryRE, '<b>$1</b>');
243 }
244}
245
The Android Open Source Project88b60792009-03-03 19:28:42 -0800246function search_focus_changed(obj, focused)
247{
248 if (focused) {
249 if(obj.value == DEFAULT_TEXT){
250 obj.value = "";
251 obj.style.color="#000000";
252 }
253 } else {
254 if(obj.value == ""){
255 obj.value = DEFAULT_TEXT;
256 obj.style.color="#aaaaaa";
257 }
258 document.getElementById("search_filtered_div").className = "no-display";
259 }
260}
261
262function submit_search() {
263 var query = document.getElementById('search_autocomplete').value;
Scott Mainf1bac522009-10-26 14:44:48 -0700264 document.location = toRoot + 'search.html#q=' + query + '&t=0';
The Android Open Source Project88b60792009-03-03 19:28:42 -0800265 return false;
266}