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

Commit af232984 authored by Roman Nurik's avatar Roman Nurik Committed by Scott Main
Browse files

cherry-pick from master: 42092024

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

Change-Id: I3dd0e4edd7efae5a5758952699c08f1a46bdfeda
parent 135677a7
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) {