summaryrefslogtreecommitdiffstats
path: root/tools/droiddoc
diff options
context:
space:
mode:
authorRoman Nurik <romannurik@google.com>2010-04-13 16:23:42 -0700
committerRoman Nurik <romannurik@google.com>2010-04-19 14:28:18 -0700
commit42092024ebd81896e741829c50f37a7e0095392e (patch)
tree35f18b0fc750838467f266c2607bb40e31cb6455 /tools/droiddoc
parentd9ec1f1c5dc7e88595e98fcacbf2b1bd5bfd366f (diff)
downloadbuild-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.css2
-rw-r--r--tools/droiddoc/templates/assets/search_autocomplete.js107
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) {