Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 42092024 authored by Roman Nurik's avatar Roman Nurik
Browse files

Enable query highlighting and result ranking for search autocomplete on d.a.c....

Enable query highlighting and result ranking for search autocomplete on d.a.c. Also make it case-insensitive.

Change-Id: Ifa52bb48c7b03c9aa7ad03cfe3e0049024f71a8d
parent d9ec1f1c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+99 −8
Original line number Diff line number Diff line
@@ -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) {