Home | History | Annotate | Download | only in sync_internals
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // require: cr.js
      6 
      7 cr.define('chrome.sync', function() {
      8   var currSearchId = 0;
      9 
     10   var setQueryString = function(queryControl, query) {
     11     queryControl.value = query;
     12   };
     13 
     14   var createDoQueryFunction = function(queryControl, submitControl, query) {
     15     return function() {
     16       setQueryString(queryControl, query);
     17       submitControl.click();
     18     };
     19   };
     20 
     21   /**
     22    * Decorates the quick search controls
     23    *
     24    * @param {Array of DOM elements} quickLinkArray The <a> object which
     25    *     will be given a link to a quick filter option.
     26    * @param {!HTMLInputElement} queryControl The <input> object of
     27    *     type=search where the user types in his query.
     28    */
     29   var decorateQuickQueryControls = function(quickLinkArray, submitControl,
     30                                             queryControl) {
     31     for (var index = 0; index < allLinks.length; ++index) {
     32       var quickQuery = allLinks[index].getAttribute('data-query');
     33       var quickQueryFunction = createDoQueryFunction(queryControl,
     34           submitControl, quickQuery);
     35       allLinks[index].addEventListener('click', quickQueryFunction);
     36     }
     37   };
     38 
     39   /**
     40    * Runs a search with the given query.
     41    *
     42    * @param {string} query The regex to do the search with.
     43    * @param {function} callback The callback called with the search results;
     44    *     not called if doSearch() is called again while the search is running.
     45    */
     46   var doSearch = function(query, callback) {
     47     var searchId = ++currSearchId;
     48     try {
     49       var regex = new RegExp(query);
     50       chrome.sync.getAllNodes(function(node_map) {
     51         // Put all nodes into one big list that ignores the type.
     52         var nodes = node_map.
     53             map(function(x) { return x.nodes; }).
     54             reduce(function(a, b) { return a.concat(b); });
     55 
     56         if (currSearchId != searchId) {
     57           return;
     58         }
     59         callback(nodes.filter(function(elem) {
     60           return regex.test(JSON.stringify(elem, null, 2));
     61         }), null);
     62       });
     63     } catch (err) {
     64       // Sometimes the provided regex is invalid.  This and other errors will
     65       // be caught and handled here.
     66       callback([], err);
     67     }
     68   };
     69 
     70   /**
     71    * Decorates the various search controls.
     72    *
     73    * @param {!HTMLInputElement} queryControl The <input> object of
     74    *     type=search where the user types in his query.
     75    * @param {!HTMLButtonElement} submitControl The <button> object
     76    *     where the user can click to do his query.
     77    * @param {!HTMLElement} statusControl The <span> object display the
     78    *     search status.
     79    * @param {!HTMLElement} listControl The <list> object which holds
     80    *     the list of returned results.
     81    * @param {!HTMLPreElement} detailsControl The <pre> object which
     82    *     holds the details of the selected result.
     83    */
     84   function decorateSearchControls(queryControl, submitControl, statusControl,
     85                                   resultsControl, detailsControl) {
     86     var resultsDataModel = new cr.ui.ArrayDataModel([]);
     87 
     88     var searchFunction = function() {
     89       var query = queryControl.value;
     90       statusControl.textContent = '';
     91       resultsDataModel.splice(0, resultsDataModel.length);
     92       if (!query) {
     93         return;
     94       }
     95       statusControl.textContent = 'Searching for ' + query + '...';
     96       queryControl.removeAttribute('error');
     97       var timer = chrome.sync.makeTimer();
     98       doSearch(query, function(nodes, error) {
     99         if (error) {
    100           statusControl.textContent = 'Error: ' + error;
    101           queryControl.setAttribute('error', '');
    102         } else {
    103           statusControl.textContent =
    104             'Found ' + nodes.length + ' nodes in ' +
    105             timer.getElapsedSeconds() + 's';
    106           queryControl.removeAttribute('error');
    107 
    108           // TODO(akalin): Write a nicer list display.
    109           for (var i = 0; i < nodes.length; ++i) {
    110             nodes[i].toString = function() {
    111               return this.NON_UNIQUE_NAME;
    112             };
    113           }
    114           resultsDataModel.push.apply(resultsDataModel, nodes);
    115           // Workaround for http://crbug.com/83452 .
    116           resultsControl.redraw();
    117         }
    118       });
    119     };
    120 
    121     submitControl.addEventListener('click', searchFunction);
    122     // Decorate search box.
    123     queryControl.onsearch = searchFunction;
    124     queryControl.value = '';
    125 
    126     // Decorate results list.
    127     cr.ui.List.decorate(resultsControl);
    128     resultsControl.dataModel = resultsDataModel;
    129     resultsControl.selectionModel.addEventListener('change', function(event) {
    130       detailsControl.textContent = '';
    131       var selected = resultsControl.selectedItem;
    132       if (selected) {
    133         detailsControl.textContent = JSON.stringify(selected, null, 2);
    134       }
    135     });
    136   }
    137 
    138   return {
    139     decorateSearchControls: decorateSearchControls,
    140     decorateQuickQueryControls: decorateQuickQueryControls
    141   };
    142 });
    143