Commit a24060b6 authored by dpapad's avatar dpapad Committed by Commit Bot

Settings WebUI: Allow filtering the search engines list.

Bug: 731467
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: I785ddcb08e90910c508bc38e7bb2a524de854949
Reviewed-on: https://chromium-review.googlesource.com/595194Reviewed-by: default avatarHector Carmona <hcarmona@chromium.org>
Commit-Queue: Demetrios Papadopoulos <dpapad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491244}
parent b94e0073
......@@ -1946,6 +1946,9 @@
<message name="IDS_SETTINGS_SEARCH_ENGINES" desc="Name of the settings page which manages search engines.">
Search Engines
</message>
<message name="IDS_SETTINGS_SEARCH_ENGINES_SEARCH" desc="Label for a text input placeholder allowing the user to search/filter the displayed search engines">
Search
</message>
<message name="IDS_SETTINGS_SEARCH_ENGINES_ADD_SEARCH_ENGINE" desc="Title for a dialog that allows adding a new search engine.">
Add search engine
</message>
......
......@@ -26,10 +26,6 @@
@apply(--settings-list-frame-padding);
}
/* TODO(dbeam): this rule results in incorrectly showing a top border for
* "Other Search Engines", which hides the headers while still adding a
* dividing line (even though there's no content above the other engines
* to actually divide). */
settings-search-engine-entry {
border-top: var(--settings-separator-line);
}
......@@ -48,7 +44,7 @@
}
</style>
<div id="outer">
<div id="headers" class="column-header" hidden$="[[hideHeaders]]">
<div id="headers" class="column-header">
<div class="name">$i18n{searchEnginesSearchEngine}</div>
<div class="keyword">$i18n{searchEnginesKeyword}</div>
<div class="url">$i18n{searchEnginesQueryURL}</div>
......
......@@ -13,9 +13,6 @@ Polymer({
/** @type {!Array<!SearchEngine>} */
engines: Array,
/** Whether column headers should be displayed */
hideHeaders: Boolean,
/**
* The scroll target that this list should use.
* @type {?HTMLElement}
......
......@@ -17,7 +17,8 @@
<template>
<style include="settings-shared action-link">
.extension-engines,
#noOtherEngines {
#noOtherEngines,
.no-search-results {
@apply(--settings-list-frame-padding);
}
......@@ -28,7 +29,12 @@
<div class="settings-box first">
<h2>$i18n{searchEnginesDefault}</h2>
</div>
<settings-search-engines-list engines="[[defaultEngines]]">
<div class="no-search-results" hidden="[[matchingDefaultEngines_.length]]">
$i18n{searchNoResults}
</div>
<settings-search-engines-list
hidden="[[!matchingDefaultEngines_.length]]"
engines="[[matchingDefaultEngines_]]">
</settings-search-engines-list>
<template is="dom-if" if="[[showAddSearchEngineDialog_]]" restamp>
<settings-search-engine-dialog></settings-search-engine-dialog>
......@@ -44,15 +50,25 @@
<div id="noOtherEngines" hidden="[[otherEngines.length]]">
$i18n{searchEnginesNoOtherEngines}
</div>
<settings-search-engines-list id="otherEngines" engines="[[otherEngines]]"
hide-headers scroll-target="[[subpageScrollTarget]]">
<div class="no-search-results"
hidden="[[!showNoResultsMessage_(
otherEngines, matchingOtherEngines_)]]">
$i18n{searchNoResults}
</div>
<settings-search-engines-list id="otherEngines"
hidden="[[!matchingOtherEngines_.length]]"
engines="[[matchingOtherEngines_]]"
scroll-target="[[subpageScrollTarget]]">
</settings-search-engines-list>
<template is="dom-if" if="[[showExtensionsList_]]">
<div class="settings-box first">
<h2>$i18n{searchEnginesExtension}</h2>
</div>
<div class="no-search-results" hidden="[[matchingExtensions_.length]]">
$i18n{searchNoResults}
</div>
<iron-list id="extensions" class="extension-engines fixed-height-list"
items="[[extensions]]" preserve-focus>
items="[[matchingExtensions_]]" preserve-focus>
<template>
<settings-omnibox-extension-entry engine="[[item]]"
tabindex$="[[tabIndex]]" iron-list-tab-index="[[tabIndex]]"
......
......@@ -13,28 +13,13 @@ Polymer({
properties: {
/** @type {!Array<!SearchEngine>} */
defaultEngines: {
type: Array,
value: function() {
return [];
}
},
defaultEngines: Array,
/** @type {!Array<!SearchEngine>} */
otherEngines: {
type: Array,
value: function() {
return [];
}
},
otherEngines: Array,
/** @type {!Array<!SearchEngine>} */
extensions: {
type: Array,
value: function() {
return [];
}
},
extensions: Array,
/**
* Needed by GlobalScrollTargetBehavior.
......@@ -54,6 +39,30 @@ Polymer({
computed: 'computeShowExtensionsList_(extensions)',
},
/** Filters out all search engines that do not match. */
filter: {
type: String,
value: '',
},
/** @private {!Array<!SearchEngine>} */
matchingDefaultEngines_: {
type: Array,
computed: 'computeMatchingEngines_(defaultEngines, filter)',
},
/** @private {!Array<!SearchEngine>} */
matchingOtherEngines_: {
type: Array,
computed: 'computeMatchingEngines_(otherEngines, filter)',
},
/** @private {!Array<!SearchEngine>} */
matchingExtensions_: {
type: Array,
computed: 'computeMatchingEngines_(extensions, filter)',
},
/** @private {HTMLElement} */
omniboxExtensionlastFocused_: Object,
},
......@@ -121,4 +130,31 @@ Polymer({
computeShowExtensionsList_: function() {
return this.extensions.length > 0;
},
/**
* Filters the given list based on the currently existing filter string.
* @param {!Array<!SearchEngine>} list
* @return {!Array<!SearchEngine>}
* @private
*/
computeMatchingEngines_: function(list) {
if (this.filter == '')
return list;
var filter = this.filter.toLowerCase();
return list.filter(e => {
return [e.displayName, e.name, e.keyword, e.url].some(
term => term.toLowerCase().includes(filter));
});
},
/**
* @param {!Array<!SearchEngine>} list The original list.
* @param {!Array<!SearchEngine>} filteredList The filtered list.
* @return {boolean} Whether to show the "no results" message.
* @private
*/
showNoResultsMessage_: function(list, filteredList) {
return list.length > 0 && filteredList.length == 0;
},
});
......@@ -171,8 +171,10 @@
<template is="dom-if" route-path="/searchEngines">
<settings-subpage
associated-control="[[$$('#engines-subpage-trigger')]]"
page-title="$i18n{searchEnginesManage}">
<settings-search-engines-page></settings-search-engines-page>
page-title="$i18n{searchEnginesManage}"
search-label="$i18n{searchEnginesSearch}"
search-term="{{searchEnginesFilter_}}">
<settings-search-engines-page filter="[[searchEnginesFilter_]]">
</settings-subpage>
</template>
<if expr="chromeos">
......
......@@ -25,6 +25,9 @@ Polymer({
}
},
/** @private Filter applied to search engines. */
searchEnginesFilter_: String,
/** @private {!SearchPageHotwordInfo|undefined} */
hotwordInfo_: Object,
......
......@@ -1732,6 +1732,7 @@ void AddSearchEnginesStrings(content::WebUIDataSource* html_source) {
{"searchEnginesNoOtherEngines",
IDS_SETTINGS_SEARCH_ENGINES_NO_OTHER_ENGINES},
{"searchEnginesExtension", IDS_SETTINGS_SEARCH_ENGINES_EXTENSION_ENGINES},
{"searchEnginesSearch", IDS_SETTINGS_SEARCH_ENGINES_SEARCH},
{"searchEnginesSearchEngine", IDS_SETTINGS_SEARCH_ENGINES_SEARCH_ENGINE},
{"searchEnginesKeyword", IDS_SETTINGS_SEARCH_ENGINES_KEYWORD},
{"searchEnginesQueryURL", IDS_SETTINGS_SEARCH_ENGINES_QUERY_URL},
......
......@@ -20,10 +20,10 @@ cr.define('settings_search_engines_page', function() {
displayName: name + " displayName",
iconURL: "http://www.google.com/favicon.ico",
isOmniboxExtension: false,
keyword: "google.com",
keyword: name,
modelIndex: 0,
name: name,
url: "https://search.foo.com/search?p=%s",
url: "https://" + name + ".com/search?p=%s",
urlLocked: false,
};
}
......@@ -283,10 +283,11 @@ cr.define('settings_search_engines_page', function() {
/** @type {!SearchEnginesInfo} */
var searchEnginesInfo = {
defaults: [createSampleSearchEngine('G', false, false, false)],
defaults: [createSampleSearchEngine(
'search_engine_G', false, false, false)],
others: [
createSampleSearchEngine('B', false, false, false),
createSampleSearchEngine('A', false, false, false),
createSampleSearchEngine('search_engine_B', false, false, false),
createSampleSearchEngine('search_engine_A', false, false, false),
],
extensions: [createSampleOmniboxExtension()],
};
......@@ -377,6 +378,70 @@ cr.define('settings_search_engines_page', function() {
Polymer.dom.flush();
assertTrue(!!page.$$('settings-search-engine-dialog'));
});
// Tests that filtering the three search engines lists works, and that the
// "no search results" message is shown as expected.
test('FilterSearchEngines', function() {
Polymer.dom.flush();
function getListItems(listIndex) {
var ironList = listIndex == 2 /* extensions */ ?
page.shadowRoot.querySelector('iron-list') :
page.shadowRoot.querySelectorAll(
'settings-search-engines-list')[listIndex].shadowRoot.
querySelector('iron-list');
return ironList.items;
}
function getDefaultEntries() { return getListItems(0); }
function getOtherEntries() { return getListItems(1); }
function assertSearchResults(
defaultsCount, othersCount, extensionsCount) {
assertEquals(defaultsCount, getListItems(0).length);
assertEquals(othersCount, getListItems(1).length);
assertEquals(extensionsCount, getListItems(2).length);
var noResultsElements = Array.from(
page.shadowRoot.querySelectorAll('.no-search-results'));
assertEquals(defaultsCount > 0, noResultsElements[0].hidden);
assertEquals(othersCount > 0, noResultsElements[1].hidden);
assertEquals(extensionsCount > 0, noResultsElements[2].hidden);
}
assertSearchResults(1, 2, 1);
// Search by name
page.filter = searchEnginesInfo.defaults[0].name;
Polymer.dom.flush();
assertSearchResults(1, 0, 0);
// Search by displayName
page.filter = searchEnginesInfo.others[0].displayName;
Polymer.dom.flush();
assertSearchResults(0, 1, 0);
// Search by keyword
page.filter = searchEnginesInfo.others[1].keyword;
Polymer.dom.flush();
assertSearchResults(0, 1, 0);
// Search by URL
page.filter = 'search?';
Polymer.dom.flush();
assertSearchResults(1, 2, 0);
// Test case where none of the sublists have results.
page.filter = 'does not exist';
Polymer.dom.flush();
assertSearchResults(0, 0, 0);
// Test case where an 'extension' search engine matches.
page.filter = 'extension';
Polymer.dom.flush();
assertSearchResults(0, 0, 1);
});
});
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment