Commit 7d9c6a80 authored by csilv@chromium.org's avatar csilv@chromium.org

[web-ui settings] Fixes and improvements for settings page searching.

 - Fixed a bug that prevented searching from the last page of the settings window.
 - Fixed appearance of the extensions page title.
 - Stop the extensions page from listening to NAV_ENTRY_COMMITTED, this event is no longer needed
   since the migration and was generating extension loads for every settings page change.
 - Prevent redundant searches from occurring when the user first starts typing into the search field.
 - Use custom 'searchChanged' events rather than key/mouse events for customizing extensions list
   appearance during a search.

BUG=99047
TEST=See reproduction steps in bug.

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107033 0039d316-1c4b-4281-b951-d872f2087c98
parent bb72307b
...@@ -61,10 +61,9 @@ cr.define('options', function() { ...@@ -61,10 +61,9 @@ cr.define('options', function() {
// Instal global event handlers. // Instal global event handlers.
if (!handlersInstalled) { if (!handlersInstalled) {
this.ownerDocument.addEventListener('keyup', var searchPage = SearchPage.getInstance();
this.upEventHandler_.bind(this)); searchPage.addEventListener('searchChanged',
this.ownerDocument.addEventListener('mouseup', this.searchChangedHandler_.bind(this));
this.upEventHandler_.bind(this));
// Support full keyboard accessibility without making things ugly // Support full keyboard accessibility without making things ugly
// for users who click, by hiding some focus outlines when the user // for users who click, by hiding some focus outlines when the user
...@@ -648,18 +647,18 @@ cr.define('options', function() { ...@@ -648,18 +647,18 @@ cr.define('options', function() {
}, },
/** /**
* Handles the mouse-up and keyboard-up events. This is used to limit the * Handles the 'searchChanged' event. This is used to limit the number of
* number of items to show in the list, when the user is searching for items * items to show in the list, when the user is searching for items with the
* with the search box. Otherwise, if one match is found, the whole list of * search box. Otherwise, if one match is found, the whole list of
* extensions would be shown when we only want the matching items to be * extensions would be shown when we only want the matching items to be
* found. * found.
* @param {Event} e Change event. * @param {Event} e Change event.
* @private * @private
*/ */
upEventHandler_: function(e) { searchChangedHandler_: function(e) {
var searchString = $('search-field').value.toLowerCase(); var searchString = e.searchText;
var child = this.firstChild; var child = this.firstChild;
while (child){ while (child) {
var extension = this.getExtensionWithId_(child.id); var extension = this.getExtensionWithId_(child.id);
if (searchString.length == 0) { if (searchString.length == 0) {
// Show all. // Show all.
......
<div id="extension-settings" class="page" hidden> <div id="extension-settings" class="page" hidden>
<h1 i18n-content="extensionSettingsTitle"></h1> <h1 i18n-content="extensionSettings"></h1>
<div id="dev-toggle"> <div id="dev-toggle">
<input id="toggle-dev-on" type="checkbox" value="off"></input> <input id="toggle-dev-on" type="checkbox" value="off"></input>
<label for="toggle-dev-on" i18n-content="extensionSettingsDeveloperMode" /> <label for="toggle-dev-on" i18n-content="extensionSettingsDeveloperMode" />
......
...@@ -16,9 +16,8 @@ cr.define('options', function() { ...@@ -16,9 +16,8 @@ cr.define('options', function() {
* @class * @class
*/ */
function ExtensionSettings() { function ExtensionSettings() {
OptionsPage.call(this, OptionsPage.call(this, 'extensions',
'extensions', templateData.extensionSettingsTabTitle,
templateData.extensionSettingsTitle,
'extension-settings'); 'extension-settings');
} }
......
...@@ -100,6 +100,7 @@ cr.define('options', function() { ...@@ -100,6 +100,7 @@ cr.define('options', function() {
} }
pageName = targetPage.name.toLowerCase(); pageName = targetPage.name.toLowerCase();
var targetPageWasVisible = targetPage.visible;
// Determine if the root page is 'sticky', meaning that it // Determine if the root page is 'sticky', meaning that it
// shouldn't change when showing a sub-page. This can happen for special // shouldn't change when showing a sub-page. This can happen for special
...@@ -117,14 +118,11 @@ cr.define('options', function() { ...@@ -117,14 +118,11 @@ cr.define('options', function() {
page.willHidePage(); page.willHidePage();
} }
var prevVisible = false;
// Update visibilities to show only the hierarchy of the target page. // Update visibilities to show only the hierarchy of the target page.
for (var name in this.registeredPages) { for (var name in this.registeredPages) {
var page = this.registeredPages[name]; var page = this.registeredPages[name];
if (!page.parentPage && isRootPageLocked) if (!page.parentPage && isRootPageLocked)
continue; continue;
prevVisible = page.visible;
page.visible = name == pageName || page.visible = name == pageName ||
(!document.documentElement.classList.contains('hide-menu') && (!document.documentElement.classList.contains('hide-menu') &&
page.isAncestorOfPage(targetPage)); page.isAncestorOfPage(targetPage));
...@@ -142,7 +140,7 @@ cr.define('options', function() { ...@@ -142,7 +140,7 @@ cr.define('options', function() {
var page = this.registeredPages[name]; var page = this.registeredPages[name];
if (!page.parentPage && isRootPageLocked) if (!page.parentPage && isRootPageLocked)
continue; continue;
if (!prevVisible && page.didShowPage && (name == pageName || if (!targetPageWasVisible && page.didShowPage && (name == pageName ||
page.isAncestorOfPage(targetPage))) page.isAncestorOfPage(targetPage)))
page.didShowPage(); page.didShowPage();
} }
......
...@@ -105,7 +105,6 @@ cr.define('options', function() { ...@@ -105,7 +105,6 @@ cr.define('options', function() {
function SearchPage() { function SearchPage() {
OptionsPage.call(this, 'search', templateData.searchPageTabTitle, OptionsPage.call(this, 'search', templateData.searchPageTabTitle,
'searchPage'); 'searchPage');
this.searchActive = false;
} }
cr.addSingletonGetter(SearchPage); cr.addSingletonGetter(SearchPage);
...@@ -114,6 +113,13 @@ cr.define('options', function() { ...@@ -114,6 +113,13 @@ cr.define('options', function() {
// Inherit SearchPage from OptionsPage. // Inherit SearchPage from OptionsPage.
__proto__: OptionsPage.prototype, __proto__: OptionsPage.prototype,
/**
* A boolean to prevent recursion. Used by setSearchText_().
* @type {Boolean}
* @private
*/
insideSetSearchText_: false,
/** /**
* Initialize the page. * Initialize the page.
*/ */
...@@ -145,7 +151,7 @@ cr.define('options', function() { ...@@ -145,7 +151,7 @@ cr.define('options', function() {
// Handle search events. (No need to throttle, WebKit's search field // Handle search events. (No need to throttle, WebKit's search field
// will do that automatically.) // will do that automatically.)
searchField.onsearch = function(e) { searchField.onsearch = function(e) {
self.setSearchText_(SearchPage.canonicalizeQuery(this.value)); self.setSearchText_(this.value);
}; };
// We update the history stack every time the search field blurs. This way // We update the history stack every time the search field blurs. This way
...@@ -284,6 +290,19 @@ cr.define('options', function() { ...@@ -284,6 +290,19 @@ cr.define('options', function() {
* @private * @private
*/ */
setSearchText_: function(text) { setSearchText_: function(text) {
// Prevent recursive execution of this method.
if (this.insideSetSearchText_) return;
this.insideSetSearchText_ = true;
// Cleanup the search query string.
text = SearchPage.canonicalizeQuery(text);
// Notify listeners about the new search query, some pages may wish to
// show/hide elements based on the query.
var event = new cr.Event('searchChanged');
event.searchText = text;
this.dispatchEvent(event);
// Toggle the search page if necessary. // Toggle the search page if necessary.
if (text.length) { if (text.length) {
if (!this.searchActive_) if (!this.searchActive_)
...@@ -291,6 +310,8 @@ cr.define('options', function() { ...@@ -291,6 +310,8 @@ cr.define('options', function() {
} else { } else {
if (this.searchActive_) if (this.searchActive_)
OptionsPage.showDefaultPage(); OptionsPage.showDefaultPage();
this.insideSetSearchText_ = false;
return; return;
} }
...@@ -381,6 +402,9 @@ cr.define('options', function() { ...@@ -381,6 +402,9 @@ cr.define('options', function() {
length = bubbleControls.length; length = bubbleControls.length;
for (var i = 0; i < length; i++) for (var i = 0; i < length; i++)
this.createSearchBubble_(bubbleControls[i], text); this.createSearchBubble_(bubbleControls[i], text);
// Cleanup the recursion-prevention variable.
this.insideSetSearchText_ = false;
}, },
/** /**
......
...@@ -217,9 +217,6 @@ void ExtensionSettingsHandler::MaybeRegisterForNotifications() { ...@@ -217,9 +217,6 @@ void ExtensionSettingsHandler::MaybeRegisterForNotifications() {
content::Source<Profile>(profile)); content::Source<Profile>(profile));
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_WARNING_CHANGED, registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_WARNING_CHANGED,
content::Source<Profile>(profile)); content::Source<Profile>(profile));
registrar_.Add(this,
content::NOTIFICATION_NAV_ENTRY_COMMITTED,
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, registrar_.Add(this,
content::NOTIFICATION_RENDER_VIEW_HOST_CREATED, content::NOTIFICATION_RENDER_VIEW_HOST_CREATED,
content::NotificationService::AllBrowserContextsAndSources()); content::NotificationService::AllBrowserContextsAndSources());
...@@ -505,10 +502,8 @@ void ExtensionSettingsHandler::GetLocalizedValues( ...@@ -505,10 +502,8 @@ void ExtensionSettingsHandler::GetLocalizedValues(
DCHECK(localized_strings); DCHECK(localized_strings);
RegisterTitle(localized_strings, "extensionSettings", RegisterTitle(localized_strings, "extensionSettings",
IDS_OPTIONS_GENERAL_TAB_LABEL); IDS_MANAGE_EXTENSIONS_SETTING_WINDOWS_TITLE);
localized_strings->SetString("extensionSettingsTitle",
l10n_util::GetStringUTF16(IDS_MANAGE_EXTENSIONS_SETTING_WINDOWS_TITLE));
localized_strings->SetString("extensionSettingsVisitWebsite", localized_strings->SetString("extensionSettingsVisitWebsite",
l10n_util::GetStringUTF16(IDS_EXTENSIONS_VISIT_WEBSITE)); l10n_util::GetStringUTF16(IDS_EXTENSIONS_VISIT_WEBSITE));
...@@ -605,12 +600,7 @@ void ExtensionSettingsHandler::Observe( ...@@ -605,12 +600,7 @@ void ExtensionSettingsHandler::Observe(
// For instance, EXTENSION_LOADED & EXTENSION_PROCESS_CREATED because // For instance, EXTENSION_LOADED & EXTENSION_PROCESS_CREATED because
// we don't know about the views for an extension at EXTENSION_LOADED, but // we don't know about the views for an extension at EXTENSION_LOADED, but
// if we only listen to EXTENSION_PROCESS_CREATED, we'll miss extensions // if we only listen to EXTENSION_PROCESS_CREATED, we'll miss extensions
// that don't have a process at startup. Similarly, NAV_ENTRY_COMMITTED & // that don't have a process at startup.
// RENDER_VIEW_HOST_CREATED because we want to handle both
// the case of navigating from a non-extension page to an extension page in
// a TabContents (which will generate NAV_ENTRY_COMMITTED) as well as
// extension content being shown in popups and balloons (which will generate
// RENDER_VIEW_HOST_CREATED but no NAV_ENTRY_COMMITTED).
// //
// Doing it this way gets everything but causes the page to be rendered // Doing it this way gets everything but causes the page to be rendered
// more than we need. It doesn't seem to result in any noticeable flicker. // more than we need. It doesn't seem to result in any noticeable flicker.
...@@ -635,14 +625,6 @@ void ExtensionSettingsHandler::Observe( ...@@ -635,14 +625,6 @@ void ExtensionSettingsHandler::Observe(
return; return;
MaybeUpdateAfterNotification(); MaybeUpdateAfterNotification();
break; break;
case content::NOTIFICATION_NAV_ENTRY_COMMITTED:
source_profile = Profile::FromBrowserContext(
content::Source<NavigationController>(
source).ptr()->browser_context());
if (!profile->IsSameProfile(source_profile))
return;
MaybeUpdateAfterNotification();
break;
case chrome::NOTIFICATION_EXTENSION_LOADED: case chrome::NOTIFICATION_EXTENSION_LOADED:
case chrome::NOTIFICATION_EXTENSION_PROCESS_CREATED: case chrome::NOTIFICATION_EXTENSION_PROCESS_CREATED:
case chrome::NOTIFICATION_EXTENSION_UNLOADED: case chrome::NOTIFICATION_EXTENSION_UNLOADED:
......
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