DOMUI Prefs: Split search engines into two lists

BUG=70332
TEST=Search engine list headers should match autofill options.

Review URL: http://codereview.chromium.org/6248015

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72224 0039d316-1c4b-4281-b951-d872f2087c98
parent 67306603
...@@ -50,6 +50,10 @@ void SearchEngineManagerHandler::GetLocalizedValues( ...@@ -50,6 +50,10 @@ void SearchEngineManagerHandler::GetLocalizedValues(
localized_strings->SetString("searchEngineManagerPage", localized_strings->SetString("searchEngineManagerPage",
l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE)); l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE));
localized_strings->SetString("defaultSearchEngineListTitle",
l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAIN_SEPARATOR));
localized_strings->SetString("otherSearchEngineListTitle",
l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_OTHER_SEPARATOR));
localized_strings->SetString("searchEngineTableNameHeader", localized_strings->SetString("searchEngineTableNameHeader",
l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN)); l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN));
localized_strings->SetString("searchEngineTableKeywordHeader", localized_strings->SetString("searchEngineTableKeywordHeader",
...@@ -98,33 +102,31 @@ void SearchEngineManagerHandler::OnModelChanged() { ...@@ -98,33 +102,31 @@ void SearchEngineManagerHandler::OnModelChanged() {
if (!list_controller_->loaded()) if (!list_controller_->loaded())
return; return;
ListValue engine_list;
// Find the default engine. // Find the default engine.
const TemplateURL* default_engine = const TemplateURL* default_engine =
list_controller_->url_model()->GetDefaultSearchProvider(); list_controller_->url_model()->GetDefaultSearchProvider();
int default_index = list_controller_->table_model()->IndexOfTemplateURL( int default_index = list_controller_->table_model()->IndexOfTemplateURL(
default_engine); default_engine);
// Add the first group (default search engine options). // Build the first list (default search engine options).
engine_list.Append(CreateDictionaryForHeading(0)); ListValue defaults_list;
int last_default_engine_index = int last_default_engine_index =
list_controller_->table_model()->last_search_engine_index(); list_controller_->table_model()->last_search_engine_index();
for (int i = 0; i < last_default_engine_index; ++i) { for (int i = 0; i < last_default_engine_index; ++i) {
engine_list.Append(CreateDictionaryForEngine(i, i == default_index)); defaults_list.Append(CreateDictionaryForEngine(i, i == default_index));
} }
// Add the second group (other search templates). // Build the second list (other search templates).
engine_list.Append(CreateDictionaryForHeading(1)); ListValue others_list;
if (last_default_engine_index < 0) if (last_default_engine_index < 0)
last_default_engine_index = 0; last_default_engine_index = 0;
int engine_count = list_controller_->table_model()->RowCount(); int engine_count = list_controller_->table_model()->RowCount();
for (int i = last_default_engine_index; i < engine_count; ++i) { for (int i = last_default_engine_index; i < engine_count; ++i) {
engine_list.Append(CreateDictionaryForEngine(i, i == default_index)); others_list.Append(CreateDictionaryForEngine(i, i == default_index));
} }
dom_ui_->CallJavascriptFunction(L"SearchEngineManager.updateSearchEngineList", dom_ui_->CallJavascriptFunction(L"SearchEngineManager.updateSearchEngineList",
engine_list); defaults_list, others_list);
} }
void SearchEngineManagerHandler::OnItemsChanged(int start, int length) { void SearchEngineManagerHandler::OnItemsChanged(int start, int length) {
...@@ -139,15 +141,6 @@ void SearchEngineManagerHandler::OnItemsRemoved(int start, int length) { ...@@ -139,15 +141,6 @@ void SearchEngineManagerHandler::OnItemsRemoved(int start, int length) {
OnModelChanged(); OnModelChanged();
} }
DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForHeading(
int group_index) {
ui::TableModel::Groups groups = list_controller_->table_model()->GetGroups();
DictionaryValue* dict = new DictionaryValue();
dict->SetString("heading", groups[group_index].title);
return dict;
}
DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForEngine( DictionaryValue* SearchEngineManagerHandler::CreateDictionaryForEngine(
int index, bool is_default) { int index, bool is_default) {
TemplateURLTableModel* table_model = list_controller_->table_model(); TemplateURLTableModel* table_model = list_controller_->table_model();
......
...@@ -64,8 +64,6 @@ class SearchEngineManagerHandler : public OptionsPageUIHandler, ...@@ -64,8 +64,6 @@ class SearchEngineManagerHandler : public OptionsPageUIHandler,
// Called from DOMUI. // Called from DOMUI.
void EditCompleted(const ListValue* args); void EditCompleted(const ListValue* args);
// Returns a dictionary to pass to DOMUI representing the given group heading.
DictionaryValue* CreateDictionaryForHeading(int group_index);
// Returns a dictionary to pass to DOMUI representing the given search engine. // Returns a dictionary to pass to DOMUI representing the given search engine.
DictionaryValue* CreateDictionaryForEngine(int index, bool is_default); DictionaryValue* CreateDictionaryForEngine(int index, bool is_default);
......
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cr.define('options', function() {
const ListSelectionController = cr.ui.ListSelectionController;
/**
* Creates a selection controller with a delegate that controls whether or
* not individual items are selectable. This is used for lists containing
* subgroups with headings that are in the list, since the headers themselves
* should not be selectable.
*
* @param {cr.ui.ListSelectionModel} selectionModel The selection model to
* interact with.
* @param {*} selectabilityDelegate A delegate responding to
* canSelectIndex(index).
*
* @constructor
* @extends {!cr.ui.ListSelectionController}
*/
function ListInlineHeaderSelectionController(selectionModel,
selectabilityDelegate) {
ListSelectionController.call(this, selectionModel);
this.selectabilityDelegate_ = selectabilityDelegate;
}
ListInlineHeaderSelectionController.prototype = {
__proto__: ListSelectionController.prototype,
/** @inheritDoc */
getIndexBelow: function(index) {
var next = ListSelectionController.prototype.getIndexBelow.call(this,
index);
if (next == -1 || this.canSelect(next))
return next;
return this.getIndexBelow(next);
},
/** @inheritDoc */
getNextIndex: function(index) {
return this.getIndexBelow(index);
},
/** @inheritDoc */
getIndexAbove: function(index) {
var previous = ListSelectionController.prototype.getIndexAbove.call(
this, index);
if (previous == -1 || this.canSelect(previous))
return previous;
return this.getIndexAbove(previous);
},
/** @inheritDoc */
getPreviousIndex: function(index) {
return this.getIndexAbove(index);
},
/** @inheritDoc */
getFirstIndex: function(index) {
var first = ListSelectionController.prototype.getFirstIndex.call(this);
if (this.canSelect(first))
return first;
return this.getNextIndex(first);
},
/** @inheritDoc */
getLastIndex: function(index) {
var last = ListSelectionController.prototype.getLastIndex.call(this);
if (this.canSelect(last))
return last;
return this.getPreviousIndex(last);
},
/** @inheritDoc */
handleMouseDownUp: function(e, index) {
if (this.canSelect(index)) {
ListSelectionController.prototype.handleMouseDownUp.call(
this, e, index);
}
},
/**
* Returns true if the given index is selectable.
* @private
* @param {number} index The index to check.
*/
canSelect: function(index) {
return this.selectabilityDelegate_.canSelectIndex(index);
}
};
return {
ListInlineHeaderSelectionController: ListInlineHeaderSelectionController
};
});
...@@ -61,7 +61,6 @@ ...@@ -61,7 +61,6 @@
<script src="pref_ui.js"></script> <script src="pref_ui.js"></script>
<script src="deletable_item_list.js"></script> <script src="deletable_item_list.js"></script>
<script src="inline_editable_list.js"></script> <script src="inline_editable_list.js"></script>
<script src="list_inline_header_selection_controller.js"></script>
<script src="options_page.js"></script> <script src="options_page.js"></script>
<if expr="pp_ifdef('chromeos')"> <if expr="pp_ifdef('chromeos')">
<script src="about_page.js"></script> <script src="about_page.js"></script>
......
#searchEngineList { .search-engine-list > div {
-webkit-border-radius: 2px;
border-bottom: 1px solid #d9d9d9;
height: auto;
}
#searchEngineList .heading {
-webkit-border-radius: 2px;
color: black;
border-bottom: 1px solid #d9d9d9;
}
#searchEngineList .heading:not(:nth-child(2)) {
border-top: 1px solid #d9d9d9;
}
#searchEngineList .heading .name-column {
font-weight: bold;
}
#searchEngineList > div:not(.heading) {
border-left: 1px solid #d9d9d9;
border-right: 1px solid #d9d9d9;
}
#searchEngineList > div, #searchEngineHeading {
display: -webkit-box; display: -webkit-box;
} }
#searchEngineList .favicon { .search-engine-list .favicon {
padding: 1px 7px 0px 7px; padding: 1px 7px 0px 7px;
height: 16px; height: 16px;
} }
#searchEngineList .name-column { .search-engine-list .name-column {
-webkit-padding-end: 1ex;
box-sizing: border-box; box-sizing: border-box;
width: 37%; width: 37%;
} }
#searchEngineList .keyword-column { .search-engine-list .keyword-column {
width: 26%; width: 26%;
} }
#searchEngineList .url-column { .search-engine-list .url-column {
width: 37%; width: 37%;
} }
#searchEngineList > div:not(.heading) .keyword-column, .search-engine-list .keyword-column,
#searchEngineList > div:not(.heading) .url-column { .search-engine-list .url-column {
color: #666666;
}
#searchEngineList .name-column,
#searchEngineList .keyword-column,
#searchEngineList .url-column {
-webkit-padding-end: 1ex; -webkit-padding-end: 1ex;
color: #666666;
} }
#searchEngineList .default { .search-engine-list .default .name-column,
.search-engine-list .default .keyword-column {
font-weight: bold; font-weight: bold;
} }
#searchEngineList .default .url-column { .search-engine-list .name-column {
font-weight: normal;
}
#searchEngineList .name-column {
display: -webkit-box; display: -webkit-box;
} }
#searchEngineList .name-column :last-child { .search-engine-list .name-column :last-child {
-webkit-box-flex: 1; -webkit-box-flex: 1;
} }
#searchEngineList input { .search-engine-list input {
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
width: 100%; width: 100%;
} }
/* For temporary Make Default button */ /* For temporary Make Default button */
#searchEngineList .url-column { .search-engine-list .url-column {
display: -webkit-box; display: -webkit-box;
-webkit-box-align: center; -webkit-box-align: center;
} }
#searchEngineList .url-column :first-child { .search-engine-list .url-column :first-child {
-webkit-box-flex: 1; -webkit-box-flex: 1;
} }
#searchEngineList .url-column button { .search-engine-list .url-column button {
background: #8aaaed; background: #8aaaed;
color: #fff; color: #fff;
-webkit-margin-start: 3px; -webkit-margin-start: 3px;
} }
#searchEngineList > :not(:hover):not([editing]) .url-column button { .search-engine-list > :not(:hover):not([editing]) .url-column button {
display: none; display: none;
} }
/* End temporary Make Default button styling */ /* End temporary Make Default button styling */
<div class="page hidden" id="searchEngineManagerPage"> <div class="page hidden" id="searchEngineManagerPage">
<h1 i18n-content="searchEngineManagerPage"></h1> <h1 i18n-content="searchEngineManagerPage"></h1>
<list id="searchEngineList"></list> <h3 i18n-content="defaultSearchEngineListTitle"></h3>
<list id="defaultSearchEngineList"
class="search-engine-list settings-list"></list>
<h3 i18n-content="otherSearchEngineListTitle"></h3>
<list id="otherSearchEngineList"
class=" search-engine-list settings-list"></list>
</div> </div>
...@@ -22,39 +22,73 @@ cr.define('options', function() { ...@@ -22,39 +22,73 @@ cr.define('options', function() {
SearchEngineManager.prototype = { SearchEngineManager.prototype = {
__proto__: OptionsPage.prototype, __proto__: OptionsPage.prototype,
list_: null,
/**
* List for default search engine options
* @type {boolean}
* @private
*/
defaultsList_: null,
/**
* List for other search engine options
* @type {boolean}
* @private
*/
othersList_: null,
/** inheritDoc */
initializePage: function() { initializePage: function() {
OptionsPage.prototype.initializePage.call(this); OptionsPage.prototype.initializePage.call(this);
this.list_ = $('searchEngineList') this.defaultsList_ = $('defaultSearchEngineList');
options.search_engines.SearchEngineList.decorate(this.list_); this.setUpList_(this.defaultsList_);
var selectionModel = new ListSingleSelectionModel;
this.list_.selectionModel = selectionModel; this.othersList_ = $('otherSearchEngineList');
this.list_.autoExpands = true; this.setUpList_(this.othersList_);
},
/**
* Sets up the given list as a search engine list
* @param {List} list The list to set up.
* @private
*/
setUpList_: function(list) {
options.search_engines.SearchEngineList.decorate(list);
list.selectionModel = new ListSingleSelectionModel;
list.autoExpands = true;
}, },
/** /**
* Updates the search engine list with the given entries. * Updates the search engine list with the given entries.
* @private * @private
* @param {Array} engineList List of available search engines. * @param {Array} defaultEngines List of possible default search engines.
* @param {Array} otherEngines List of other search engines.
*/ */
updateSearchEngineList_: function(engineList) { updateSearchEngineList_: function(defaultEngines, otherEngines) {
var model = new ArrayDataModel(engineList); this.defaultsList_.dataModel = new ArrayDataModel(defaultEngines);
model.push({ var othersModel = new ArrayDataModel(otherEngines);
// Add a "new engine" row.
othersModel.push({
'modelIndex': '-1' 'modelIndex': '-1'
}); });
this.list_.dataModel = model; this.othersList_.dataModel = othersModel;
}, },
}; };
SearchEngineManager.updateSearchEngineList = function(engineList) { SearchEngineManager.updateSearchEngineList = function(defaultEngines,
SearchEngineManager.getInstance().updateSearchEngineList_(engineList); otherEngines) {
SearchEngineManager.getInstance().updateSearchEngineList_(defaultEngines,
otherEngines);
}; };
SearchEngineManager.validityCheckCallback = function(validity, modelIndex) { SearchEngineManager.validityCheckCallback = function(validity, modelIndex) {
SearchEngineManager.getInstance().list_.validationComplete(validity, // Forward to both lists; the one without a matching modelIndex will ignore
modelIndex); // it.
SearchEngineManager.getInstance().defaultsList_.validationComplete(
validity, modelIndex);
SearchEngineManager.getInstance().othersList_.validationComplete(
validity, modelIndex);
}; };
// Export // Export
......
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
cr.define('options.search_engines', function() { cr.define('options.search_engines', function() {
const InlineEditableItemList = options.InlineEditableItemList; const InlineEditableItemList = options.InlineEditableItemList;
const InlineEditableItem = options.InlineEditableItem; const InlineEditableItem = options.InlineEditableItem;
const ListInlineHeaderSelectionController = const ListSelectionController = cr.ui.ListSelectionController;
options.ListInlineHeaderSelectionController;
/** /**
* Creates a new search engine list item. * Creates a new search engine list item.
...@@ -90,50 +89,37 @@ cr.define('options.search_engines', function() { ...@@ -90,50 +89,37 @@ cr.define('options.search_engines', function() {
this.currentlyValid_ = !this.isPlaceholder_; this.currentlyValid_ = !this.isPlaceholder_;
if (engine['heading']) { if (engine['default'])
this.classList.add('heading');
this.editable = false;
} else if (engine['default']) {
this.classList.add('default'); this.classList.add('default');
}
this.deletable = engine['canBeRemoved']; this.deletable = engine['canBeRemoved'];
var nameText = engine['name'];
var keywordText = engine['keyword'];
var urlText = engine['url'];
if (engine['heading']) {
nameText = engine['heading'];
keywordText = localStrings.getString('searchEngineTableKeywordHeader');
urlText = localStrings.getString('searchEngineTableURLHeader');
}
// Construct the name column. // Construct the name column.
var nameColEl = this.ownerDocument.createElement('div'); var nameColEl = this.ownerDocument.createElement('div');
nameColEl.className = 'name-column'; nameColEl.className = 'name-column';
this.contentElement.appendChild(nameColEl); this.contentElement.appendChild(nameColEl);
// For non-heading rows, start with a favicon. // Add the favicon.
if (!engine['heading']) { var faviconDivEl = this.ownerDocument.createElement('div');
var faviconDivEl = this.ownerDocument.createElement('div'); faviconDivEl.className = 'favicon';
faviconDivEl.className = 'favicon'; var imgEl = this.ownerDocument.createElement('img');
var imgEl = this.ownerDocument.createElement('img'); imgEl.src = 'chrome://favicon/iconurl/' + engine['iconURL'];
imgEl.src = 'chrome://favicon/iconurl/' + engine['iconURL']; faviconDivEl.appendChild(imgEl);
faviconDivEl.appendChild(imgEl); nameColEl.appendChild(faviconDivEl);
nameColEl.appendChild(faviconDivEl);
}
var nameEl = this.createEditableTextCell(nameText, this.isPlaceholder_); var nameEl = this.createEditableTextCell(engine['name'],
this.isPlaceholder_);
nameColEl.appendChild(nameEl); nameColEl.appendChild(nameEl);
// Then the keyword column. // Then the keyword column.
var keywordEl = this.createEditableTextCell(keywordText, var keywordEl = this.createEditableTextCell(engine['keyword'],
this.isPlaceholder_); this.isPlaceholder_);
keywordEl.className = 'keyword-column'; keywordEl.className = 'keyword-column';
this.contentElement.appendChild(keywordEl); this.contentElement.appendChild(keywordEl);
// And the URL column. // And the URL column.
var urlEl = this.createEditableTextCell(urlText, this.isPlaceholder_); var urlEl = this.createEditableTextCell(engine['url'],
this.isPlaceholder_);
var urlWithButtonEl = this.ownerDocument.createElement('div'); var urlWithButtonEl = this.ownerDocument.createElement('div');
urlWithButtonEl.appendChild(urlEl); urlWithButtonEl.appendChild(urlEl);
urlWithButtonEl.className = 'url-column'; urlWithButtonEl.className = 'url-column';
...@@ -142,6 +128,7 @@ cr.define('options.search_engines', function() { ...@@ -142,6 +128,7 @@ cr.define('options.search_engines', function() {
// is implemented. When this is removed, remove the extra div above. // is implemented. When this is removed, remove the extra div above.
if (engine['canBeDefault']) { if (engine['canBeDefault']) {
var makeDefaultButtonEl = this.ownerDocument.createElement('button'); var makeDefaultButtonEl = this.ownerDocument.createElement('button');
makeDefaultButtonEl.className = "raw-button";
makeDefaultButtonEl.textContent = makeDefaultButtonEl.textContent =
templateData.makeDefaultSearchEngineButton; templateData.makeDefaultSearchEngineButton;
makeDefaultButtonEl.onclick = function(e) { makeDefaultButtonEl.onclick = function(e) {
...@@ -155,27 +142,25 @@ cr.define('options.search_engines', function() { ...@@ -155,27 +142,25 @@ cr.define('options.search_engines', function() {
} }
// Do final adjustment to the input fields. // Do final adjustment to the input fields.
if (!engine['heading']) { this.nameField_ = nameEl.querySelector('input');
this.nameField_ = nameEl.querySelector('input'); this.keywordField_ = keywordEl.querySelector('input');
this.keywordField_ = keywordEl.querySelector('input'); this.urlField_ = urlEl.querySelector('input');
this.urlField_ = urlEl.querySelector('input');
if (engine['urlLocked'])
if (engine['urlLocked']) this.urlField_.disabled = true;
this.urlField_.disabled = true;
if (this.isPlaceholder_) {
if (this.isPlaceholder_) { this.nameField_.placeholder =
this.nameField_.placeholder = localStrings.getString('searchEngineTableNamePlaceholder');
localStrings.getString('searchEngineTableNamePlaceholder'); this.keywordField_.placeholder =
this.keywordField_.placeholder = localStrings.getString('searchEngineTableKeywordPlaceholder');
localStrings.getString('searchEngineTableKeywordPlaceholder'); this.urlField_.placeholder =
this.urlField_.placeholder = localStrings.getString('searchEngineTableURLPlaceholder');
localStrings.getString('searchEngineTableURLPlaceholder'); }
}
var fields = [ this.nameField_, this.keywordField_, this.urlField_ ];
var fields = [ this.nameField_, this.keywordField_, this.urlField_ ]; for (var i = 0; i < fields.length; i++) {
for (var i = 0; i < fields.length; i++) { fields[i].oninput = this.startFieldValidation_.bind(this);
fields[i].oninput = this.startFieldValidation_.bind(this);
}
} }
// Listen for edit events. // Listen for edit events.
...@@ -302,25 +287,12 @@ cr.define('options.search_engines', function() { ...@@ -302,25 +287,12 @@ cr.define('options.search_engines', function() {
return new SearchEngineListItem(searchEngine); return new SearchEngineListItem(searchEngine);
}, },
/** @inheritDoc */
createSelectionController: function(sm) {
return new ListInlineHeaderSelectionController(sm, this);
},
/** @inheritDoc */ /** @inheritDoc */
deleteItemAtIndex: function(index) { deleteItemAtIndex: function(index) {
var modelIndex = this.dataModel.item(index)['modelIndex'] var modelIndex = this.dataModel.item(index)['modelIndex']
chrome.send('removeSearchEngine', [String(modelIndex)]); chrome.send('removeSearchEngine', [String(modelIndex)]);
}, },
/**
* Returns true if the given item is selectable.
* @param {number} index The index to check.
*/
canSelectIndex: function(index) {
return !this.dataModel.item(index).hasOwnProperty('heading');
},
/** /**
* Passes the results of an input validation check to the requesting row * Passes the results of an input validation check to the requesting row
* if it's still being edited. * if it's still being edited.
...@@ -330,6 +302,8 @@ cr.define('options.search_engines', function() { ...@@ -330,6 +302,8 @@ cr.define('options.search_engines', function() {
validationComplete: function(validity, modelIndex) { validationComplete: function(validity, modelIndex) {
// If it's not still being edited, it no longer matters. // If it's not still being edited, it no longer matters.
var currentSelection = this.selectedItem; var currentSelection = this.selectedItem;
if (!currentSelection)
return;
var listItem = this.getListItem(currentSelection); var listItem = this.getListItem(currentSelection);
if (listItem.editing && currentSelection['modelIndex'] == modelIndex) if (listItem.editing && currentSelection['modelIndex'] == modelIndex)
listItem.validationComplete(validity); listItem.validationComplete(validity);
......
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