var gSelectedID = -1;
var gMatches = new Array();
var gLastText = "";
-var ROW_COUNT = 30;
+var ROW_COUNT = 20;
var gInitialized = false;
var DEFAULT_TEXT = "search developer docs";
function set_row_values(toroot, row, match)
{
var link = row.cells[0].childNodes[0];
- link.innerHTML = match.label;
+ link.innerHTML = match.__hilabel || match.label;
link.href = toroot + match.link
// row.cells[1].innerHTML = match.type;
}
function search_changed(e, kd, toroot)
{
var search = document.getElementById("search_autocomplete");
- var text = search.value;
+ var text = search.value.replace(/(^ +)|( +$)/g, '');
// 13 = enter
if (e.keyCode == 13) {
gMatches = new Array();
matchedCount = 0;
gSelectedIndex = -1;
- for (i=0; i<DATA.length; i++) {
+ for (var i=0; i<DATA.length; i++) {
var s = DATA[i];
- if (text.length != 0 && s.label.indexOf(text) != -1) {
+ if (text.length != 0 &&
+ s.label.toLowerCase().indexOf(text.toLowerCase()) != -1) {
gMatches[matchedCount] = s;
- if (gSelectedID == s.id) {
- gSelectedIndex = matchedCount;
- }
matchedCount++;
}
}
+ rank_autocomplete_results(text);
+ for (var i=0; i<gMatches.length; i++) {
+ var s = gMatches[i];
+ if (gSelectedID == s.id) {
+ gSelectedIndex = i;
+ }
+ }
+ highlight_autocomplete_result_labels(text);
sync_selection_table(toroot);
return true; // allow the event to bubble up to the search api
}
}
+function rank_autocomplete_results(query) {
+ query = query || '';
+ if (!gMatches || !gMatches.length)
+ return;
+
+ // helper function that gets the last occurence index of the given regex
+ // in the given string, or -1 if not found
+ var _lastSearch = function(s, re) {
+ if (s == '')
+ return -1;
+ var l = -1;
+ var tmp;
+ while ((tmp = s.search(re)) >= 0) {
+ if (l < 0) l = 0;
+ l += tmp;
+ s = s.substr(tmp + 1);
+ }
+ return l;
+ };
+
+ // helper function that counts the occurrences of a given character in
+ // a given string
+ var _countChar = function(s, c) {
+ var n = 0;
+ for (var i=0; i<s.length; i++)
+ if (s.charAt(i) == c) ++n;
+ return n;
+ };
+
+ var queryLower = query.toLowerCase();
+ var queryAlnum = (queryLower.match(/\w+/) || [''])[0];
+ var partPrefixAlnumRE = new RegExp('\\b' + queryAlnum);
+ var partExactAlnumRE = new RegExp('\\b' + queryAlnum + '\\b');
+
+ var _resultScoreFn = function(result) {
+ // scores are calculated based on exact and prefix matches,
+ // and then number of path separators (dots) from the last
+ // match (i.e. favoring classes and deep package names)
+ var score = 1.0;
+ var labelLower = result.label.toLowerCase();
+ var t;
+ t = _lastSearch(labelLower, partExactAlnumRE);
+ if (t >= 0) {
+ // exact part match
+ var partsAfter = _countChar(labelLower.substr(t + 1), '.');
+ score *= 200 / (partsAfter + 1);
+ } else {
+ t = _lastSearch(labelLower, partPrefixAlnumRE);
+ if (t >= 0) {
+ // part prefix match
+ var partsAfter = _countChar(labelLower.substr(t + 1), '.');
+ score *= 20 / (partsAfter + 1);
+ }
+ }
+
+ return score;
+ };
+
+ for (var i=0; i<gMatches.length; i++) {
+ gMatches[i].__resultScore = _resultScoreFn(gMatches[i]);
+ }
+
+ gMatches.sort(function(a,b){
+ var n = b.__resultScore - a.__resultScore;
+ if (n == 0) // lexicographical sort if scores are the same
+ n = (a.label < b.label) ? -1 : 1;
+ return n;
+ });
+}
+
+function highlight_autocomplete_result_labels(query) {
+ query = query || '';
+ if (!gMatches || !gMatches.length)
+ return;
+
+ var queryLower = query.toLowerCase();
+ var queryAlnumDot = (queryLower.match(/[\w\.]+/) || [''])[0];
+ var queryRE = new RegExp(
+ '(' + queryAlnumDot.replace(/\./g, '\\.') + ')', 'ig');
+ for (var i=0; i<gMatches.length; i++) {
+ gMatches[i].__hilabel = gMatches[i].label.replace(
+ queryRE, '<b>$1</b>');
+ }
+}
+
function search_focus_changed(obj, focused)
{
if (focused) {