diff options
author | Roman Nurik <romannurik@google.com> | 2010-04-13 16:23:42 -0700 |
---|---|---|
committer | Roman Nurik <romannurik@google.com> | 2010-04-19 14:28:18 -0700 |
commit | 42092024ebd81896e741829c50f37a7e0095392e (patch) | |
tree | 35f18b0fc750838467f266c2607bb40e31cb6455 /tools/droiddoc | |
parent | d9ec1f1c5dc7e88595e98fcacbf2b1bd5bfd366f (diff) | |
download | build-42092024ebd81896e741829c50f37a7e0095392e.zip build-42092024ebd81896e741829c50f37a7e0095392e.tar.gz build-42092024ebd81896e741829c50f37a7e0095392e.tar.bz2 |
Enable query highlighting and result ranking for search autocomplete on d.a.c. Also make it case-insensitive.
Change-Id: Ifa52bb48c7b03c9aa7ad03cfe3e0049024f71a8d
Diffstat (limited to 'tools/droiddoc')
-rw-r--r-- | tools/droiddoc/templates/assets/android-developer-core.css | 2 | ||||
-rw-r--r-- | tools/droiddoc/templates/assets/search_autocomplete.js | 107 |
2 files changed, 100 insertions, 9 deletions
diff --git a/tools/droiddoc/templates/assets/android-developer-core.css b/tools/droiddoc/templates/assets/android-developer-core.css index 750567e..92e4c53 100644 --- a/tools/droiddoc/templates/assets/android-developer-core.css +++ b/tools/droiddoc/templates/assets/android-developer-core.css @@ -519,7 +519,7 @@ div.indent { padding-right: 6px; padding-top: 1px; padding-bottom: 1px; - font-size: .8em; + font-size: 0.81em; border: none; margin: 0; line-height: 1.05em; diff --git a/tools/droiddoc/templates/assets/search_autocomplete.js b/tools/droiddoc/templates/assets/search_autocomplete.js index 4fa47a5..dd4552f 100644 --- a/tools/droiddoc/templates/assets/search_autocomplete.js +++ b/tools/droiddoc/templates/assets/search_autocomplete.js @@ -2,7 +2,7 @@ var gSelectedIndex = -1; 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"; @@ -22,7 +22,7 @@ function set_row_selected(row, selected) 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; } @@ -104,7 +104,7 @@ function sync_selection_table(toroot) 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) { @@ -137,21 +137,112 @@ function search_changed(e, kd, toroot) 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) { |