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 /** 11 * Runs a search with the given query. 12 * 13 * @param {string} query The regex to do the search with. 14 * @param {function} callback The callback called with the search results; 15 * not called if doSearch() is called again while the search is running. 16 */ 17 var doSearch = function(query, callback) { 18 var searchId = ++currSearchId; 19 try { 20 var regex = new RegExp(query); 21 chrome.sync.getAllNodes(query, function(allNodes) { 22 if (currSearchId != searchId) { 23 return; 24 } 25 callback(allNodes.filter(function(elem) { 26 return regex.test(JSON.stringify(elem, null, 2)); 27 }), null); 28 }); 29 } catch (err) { 30 // Sometimes the provided regex is invalid. This and other errors will 31 // be caught and handled here. 32 callback([], err); 33 } 34 }; 35 36 /** 37 * Decorates the various search controls. 38 * 39 * @param {!HTMLInputElement} queryControl The <input> object of 40 * type=search where the user types in his query. 41 * @param {!HTMLElement} statusControl The <span> object display the 42 * search status. 43 * @param {!HTMLElement} listControl The <list> object which holds 44 * the list of returned results. 45 * @param {!HTMLPreElement} detailsControl The <pre> object which 46 * holds the details of the selected result. 47 */ 48 function decorateSearchControls(queryControl, statusControl, 49 resultsControl, detailsControl) { 50 var resultsDataModel = new cr.ui.ArrayDataModel([]); 51 52 // Decorate search box. 53 queryControl.onsearch = function() { 54 var query = queryControl.value; 55 statusControl.textContent = ''; 56 resultsDataModel.splice(0, resultsDataModel.length); 57 if (!query) { 58 return; 59 } 60 statusControl.textContent = 'Searching for ' + query + '...'; 61 queryControl.removeAttribute('error'); 62 var timer = chrome.sync.makeTimer(); 63 doSearch(query, function(nodes, error) { 64 if (error) { 65 statusControl.textContent = 'Error: ' + error; 66 queryControl.setAttribute('error', ''); 67 } else { 68 statusControl.textContent = 69 'Found ' + nodes.length + ' nodes in ' + 70 timer.elapsedSeconds + 's'; 71 queryControl.removeAttribute('error'); 72 73 // TODO(akalin): Write a nicer list display. 74 for (var i = 0; i < nodes.length; ++i) { 75 nodes[i].toString = function() { 76 return this.NON_UNIQUE_NAME; 77 }; 78 } 79 resultsDataModel.push.apply(resultsDataModel, nodes); 80 // Workaround for http://crbug.com/83452 . 81 resultsControl.redraw(); 82 } 83 }); 84 }; 85 queryControl.value = ''; 86 87 // Decorate results list. 88 cr.ui.List.decorate(resultsControl); 89 resultsControl.dataModel = resultsDataModel; 90 resultsControl.selectionModel.addEventListener('change', function(event) { 91 detailsControl.textContent = ''; 92 var selected = resultsControl.selectedItem; 93 if (selected) { 94 detailsControl.textContent = JSON.stringify(selected, null, 2); 95 } 96 }); 97 } 98 99 return { 100 decorateSearchControls: decorateSearchControls 101 }; 102 }); 103