summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcsilv@chromium.org <csilv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-06 22:14:44 +0000
committercsilv@chromium.org <csilv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-06 22:14:44 +0000
commitd65b92c23ff555d478f92d86af5c7c1c65de4965 (patch)
treeeb05728311afa1dd53a602e39ad792e3e8f744c4
parent2d0863d1a274b39d6ce9570fe054c0def60319b5 (diff)
downloadchromium_src-d65b92c23ff555d478f92d86af5c7c1c65de4965.zip
chromium_src-d65b92c23ff555d478f92d86af5c7c1c65de4965.tar.gz
chromium_src-d65b92c23ff555d478f92d86af5c7c1c65de4965.tar.bz2
dom-ui settings:
- Implement search capability for top level panels. - Code cleanups for options_page.js BUG=59267 TEST=Verify search field presents results based on user input. Review URL: http://codereview.chromium.org/5538002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68390 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/resources/options.html3
-rw-r--r--chrome/browser/resources/options/options_page.js78
-rw-r--r--chrome/browser/resources/options/search_page.css3
-rw-r--r--chrome/browser/resources/options/search_page.html2
-rw-r--r--chrome/browser/resources/options/search_page.js182
5 files changed, 223 insertions, 45 deletions
diff --git a/chrome/browser/resources/options.html b/chrome/browser/resources/options.html
index eb6448c..92b3b12 100644
--- a/chrome/browser/resources/options.html
+++ b/chrome/browser/resources/options.html
@@ -28,6 +28,7 @@
<link rel="stylesheet" href="options/personal_options.css">
<link rel="stylesheet" href="options/import_data_overlay.css">
<link rel="stylesheet" href="options/search_engine_manager.css">
+<link rel="stylesheet" href="options/search_page.css">
<link rel="stylesheet" href="options/subpages_tab_controls.css">
<if expr="pp_ifdef('chromeos')">
<link rel="stylesheet" href="options/about_page.css">
@@ -316,7 +317,7 @@ window.onpopstate = function(e) {
</ul>
</div>
<div id="mainview">
- <div class="hidden" id="managed-prefs-banner">
+ <div id="managed-prefs-banner" class="hidden">
<span id="managed-prefs-icon"></span>
<span id="managed-prefs-text"
i18n-content="managedPrefsBannerText"></span>
diff --git a/chrome/browser/resources/options/options_page.js b/chrome/browser/resources/options/options_page.js
index 18b700e..8b360eb 100644
--- a/chrome/browser/resources/options/options_page.js
+++ b/chrome/browser/resources/options/options_page.js
@@ -24,20 +24,27 @@ cr.define('options', function() {
this.managed = false;
}
- OptionsPage.registeredPages_ = {};
+ /**
+ * Main level option pages.
+ * @protected
+ */
+ OptionsPage.registeredPages = {};
/**
- * Pages which are nested under a main page.
+ * Pages which are nested under a main level page.
+ * @protected
*/
- OptionsPage.registeredSubPages_ = {};
+ OptionsPage.registeredSubPages = {};
/**
* Pages which are meant to behave like modal dialogs.
+ * @protected
*/
- OptionsPage.registeredOverlayPages_ = {};
+ OptionsPage.registeredOverlayPages = {};
/**
* Whether or not |initialize| has been called.
+ * @private
*/
OptionsPage.initialized_ = false;
@@ -46,17 +53,34 @@ cr.define('options', function() {
* @param {string} pageName Page name.
*/
OptionsPage.showPageByName = function(pageName) {
- for (var name in OptionsPage.registeredPages_) {
- var page = OptionsPage.registeredPages_[name];
+ // Notify main pages if they will be hidden.
+ for (var name in this.registeredPages) {
+ var page = this.registeredPages[name];
+ if (name != pageName && page.willHidePage)
+ page.willHidePage();
+ }
+
+ // Update the visibility attribute for main pages.
+ for (var name in this.registeredPages) {
+ var page = this.registeredPages[name];
page.visible = name == pageName;
}
- for (var name in OptionsPage.registeredSubPages_) {
- var pageInfo = OptionsPage.registeredSubPages_[name];
+
+ // Update the visibility attribute for sub-pages.
+ for (var name in this.registeredSubPages) {
+ var pageInfo = this.registeredSubPages[name];
var match = name == pageName;
if (match)
pageInfo.parentPage.visible = true;
pageInfo.page.visible = match;
}
+
+ // Notify main pages if they were shown.
+ for (var name in this.registeredPages) {
+ var page = this.registeredPages[name];
+ if (name == pageName && page.didShowPage)
+ page.didShowPage();
+ }
};
/**
@@ -66,9 +90,9 @@ cr.define('options', function() {
* @param {string} hash The value of the hash component of the URL.
*/
OptionsPage.handleHashForPage = function(pageName, hash) {
- var page = OptionsPage.registeredPages_[pageName];
+ var page = this.registeredPages[pageName];
if (!page) {
- page = OptionsPage.registeredSubPages_[pageName].page;
+ page = this.registeredSubPages[pageName].page;
}
page.handleHash(hash);
};
@@ -78,8 +102,8 @@ cr.define('options', function() {
* @param {string} overlayName Page name.
*/
OptionsPage.showOverlay = function(overlayName) {
- if (OptionsPage.registeredOverlayPages_[overlayName]) {
- OptionsPage.registeredOverlayPages_[overlayName].visible = true;
+ if (this.registeredOverlayPages[overlayName]) {
+ this.registeredOverlayPages[overlayName].visible = true;
}
};
@@ -87,20 +111,20 @@ cr.define('options', function() {
* Clears overlays (i.e. hide all overlays).
*/
OptionsPage.clearOverlays = function() {
- for (var name in OptionsPage.registeredOverlayPages_) {
- var page = OptionsPage.registeredOverlayPages_[name];
+ for (var name in this.registeredOverlayPages) {
+ var page = this.registeredOverlayPages[name];
page.visible = false;
}
};
/**
- * Clears overlays if the key event is ESC.
+ * Handle 'keydown' events.
* @param {Event} e Key event.
* @private
*/
- OptionsPage.clearOverlaysOnEsc_ = function(e) {
+ OptionsPage.onKeyDown_ = function(e) {
if (e.keyCode == 27) { // Esc
- OptionsPage.clearOverlays();
+ this.clearOverlays();
}
};
@@ -108,8 +132,8 @@ cr.define('options', function() {
* Closes any currently-open subpage.
*/
OptionsPage.closeSubPage = function() {
- for (var name in OptionsPage.registeredSubPages_) {
- var pageInfo = OptionsPage.registeredSubPages_[name];
+ for (var name in this.registeredSubPages) {
+ var pageInfo = this.registeredSubPages[name];
if (pageInfo.page.visible) {
pageInfo.page.visible = false;
// Since the managed pref banner lives outside the overlay, and the
@@ -149,7 +173,7 @@ cr.define('options', function() {
* @param {OptionsPage} page Page to register.
*/
OptionsPage.register = function(page) {
- OptionsPage.registeredPages_[page.name] = page;
+ this.registeredPages[page.name] = page;
// Create and add new page <li> element to navbar.
var pageNav = document.createElement('li');
pageNav.id = page.name + 'PageNav';
@@ -177,7 +201,7 @@ cr.define('options', function() {
* @param {OptionsPage} page Page to register.
*/
OptionsPage.registerSubPage = function(subPage, parentPage) {
- OptionsPage.registeredSubPages_[subPage.name] = {
+ this.registeredSubPages[subPage.name] = {
page: subPage, parentPage: parentPage };
subPage.tab = undefined;
subPage.isSubPageSheet = true;
@@ -190,7 +214,7 @@ cr.define('options', function() {
* OptionsPage.
*/
OptionsPage.registerOverlay = function(page) {
- OptionsPage.registeredOverlayPages_[page.name] = page;
+ this.registeredOverlayPages[page.name] = page;
page.tab = undefined;
page.isOverlay = true;
page.initializePage();
@@ -202,7 +226,7 @@ cr.define('options', function() {
*/
OptionsPage.setState = function(data) {
if (data && data.pageName) {
- OptionsPage.showPageByName(data.pageName);
+ this.showPageByName(data.pageName);
}
};
@@ -218,7 +242,7 @@ cr.define('options', function() {
// should close the overlay, not fall through to the parent page.
$('subpage-sheet-container').onclick = function(event) {
if (!$('subpage-sheet').contains(event.target))
- OptionsPage.closeSubPage();
+ this.closeSubPage();
event.stopPropagation();
}
};
@@ -284,8 +308,7 @@ cr.define('options', function() {
this.pageDiv.classList.remove('hidden');
if (this.isOverlay) {
$('overlay').classList.remove('hidden');
- document.addEventListener('keydown',
- OptionsPage.clearOverlaysOnEsc_);
+ document.addEventListener('keydown', OptionsPage.onKeyDown_);
} else {
if (this.isSubPageSheet)
$('subpage-sheet-container').classList.remove('hidden');
@@ -302,8 +325,7 @@ cr.define('options', function() {
this.pageDiv.classList.add('hidden');
if (this.isOverlay) {
$('overlay').classList.add('hidden');
- document.removeEventListener('keydown',
- OptionsPage.clearOverlaysOnEsc_);
+ document.removeEventListener('keydown', OptionsPage.onKeyDown_);
} else if (this.isSubPageSheet) {
$('subpage-sheet-container').classList.add('hidden');
}
diff --git a/chrome/browser/resources/options/search_page.css b/chrome/browser/resources/options/search_page.css
new file mode 100644
index 0000000..03a775e
--- /dev/null
+++ b/chrome/browser/resources/options/search_page.css
@@ -0,0 +1,3 @@
+.search-hidden {
+ display: none;
+}
diff --git a/chrome/browser/resources/options/search_page.html b/chrome/browser/resources/options/search_page.html
index 413ce56..9c12cf2 100644
--- a/chrome/browser/resources/options/search_page.html
+++ b/chrome/browser/resources/options/search_page.html
@@ -3,7 +3,7 @@
<div id="searchPageInfo">
<p i18n-content="searchPageInfo"></p>
</div>
- <div id="searchPageNoMatches" class="hidden">
+ <div id="searchPageNoMatches">
<p i18n-content="searchPageNoMatches"></p>
<p><span i18n-content="searchPageHelpLabel"></span>
<a target=_blank" i18n-content="searchPageHelpTitle"
diff --git a/chrome/browser/resources/options/search_page.js b/chrome/browser/resources/options/search_page.js
index 1951f8f..feec95a 100644
--- a/chrome/browser/resources/options/search_page.js
+++ b/chrome/browser/resources/options/search_page.js
@@ -7,9 +7,11 @@ cr.define('options', function() {
/**
* Encapsulated handling of the search page.
+ * @constructor
*/
function SearchPage() {
OptionsPage.call(this, 'search', templateData.searchPage, 'searchPage');
+ this.searchActive = false;
}
cr.addSingletonGetter(SearchPage);
@@ -18,37 +20,187 @@ cr.define('options', function() {
// Inherit SearchPage from OptionsPage.
__proto__: OptionsPage.prototype,
- // Initialize SearchPage.
+ /**
+ * Initialize the page.
+ */
initializePage: function() {
// Call base class implementation to start preference initialization.
OptionsPage.prototype.initializePage.call(this);
+ var self = this;
+
// Create a search field element.
var searchField = document.createElement('input');
searchField.id = 'searchField';
searchField.type = 'search';
searchField.setAttribute('autosave', 'org.chromium.options.search');
searchField.setAttribute('results', '10');
+ searchField.setAttribute('incremental', 'true');
// Replace the contents of the navigation tab with the search field.
- this.tab.textContent = '';
- this.tab.appendChild(searchField);
+ self.tab.textContent = '';
+ self.tab.appendChild(searchField);
+
+ // Handle search events. (No need to throttle, WebKit's search field
+ // will do that automatically.)
+ searchField.onsearch = function(e) {
+ self.setSearchText_(this.value);
+ };
},
- };
- SearchPage.updateForEmptySearch = function() {
- $('searchPageInfo').classList.remove('hidden');
- $('searchPageNoMatches').classList.add('hidden');
- };
+ /**
+ * Called after this page has shown.
+ */
+ didShowPage: function() {
+ // This method is called by the Options page after all pages have
+ // had their visibilty attribute set. At this point we can perform the
+ // search specific DOM manipulation.
+ this.setSearchActive_(true);
+ },
- SearchPage.updateForNoSearchResults = function(message) {
- $('searchPageInfo').classList.add('hidden');
- $('searchPageNoMatches').classList.remove('hidden');
- };
+ /**
+ * Called before this page will be hidden.
+ */
+ willHidePage: function() {
+ // This method is called by the Options page before all pages have
+ // their visibilty attribute set. Before that happens, we need to
+ // undo the search specific DOM manipulation that was performed in
+ // didShowPage.
+ this.setSearchActive_(false);
+ },
+
+ /**
+ * Update the UI to reflect whether we are in a search state.
+ * @param {boolean} active True if we are on the search page.
+ * @private
+ */
+ setSearchActive_: function(active) {
+ // It's fine to exit if search wasn't active and we're not going to
+ // activate it now.
+ if (!this.searchActive_ && !active)
+ return;
+
+ if (this.searchActive_ != active) {
+ this.searchActive_ = active;
+ if (active) {
+ // Reset the search criteria, effectively hiding all the sections.
+ this.setSearchText_('');
+ } else {
+ // Just wipe out any active search text since it's no longer relevant.
+ $('searchField').value = '';
+ }
+ }
+
+ var page, length, childDiv;
+ for (var name in OptionsPage.registeredPages) {
+ if (name == this.name)
+ continue;
+
+ // Update the visible state of all top-level elements that are not
+ // sections (ie titles, button strips). We do this before changing
+ // the page visibility to avoid excessive re-draw.
+ page = OptionsPage.registeredPages[name];
+ length = page.pageDiv.childNodes.length;
+ for (var i = 0; i < length; i++) {
+ childDiv = page.pageDiv.childNodes[i];
+ if (childDiv.nodeType == 1) {
+ if (active) {
+ if (childDiv.nodeName.toLowerCase() != 'section')
+ childDiv.classList.add('search-hidden');
+ } else {
+ childDiv.classList.remove('search-hidden');
+ }
+ }
+ }
+
+ // Toggle the visibility state of the page.
+ if (active) {
+ // When search is active, remove the 'hidden' tag. This tag may have
+ // been added by the OptionsPage.
+ page.pageDiv.classList.remove('hidden');
+ } else {
+ page.visible = false;
+ }
+ }
+ },
+
+ /**
+ * Set the current search criteria.
+ * @param {string} text Search text.
+ * @private
+ */
+ setSearchText_: function(text) {
+ var searchText = text.toLowerCase();
+ var foundMatches = false;
+
+ // Build a list of pages to search. Omit the search page.
+ var pagesToSearch = [];
+ for (var name in OptionsPage.registeredPages) {
+ if (name != this.name)
+ pagesToSearch.push(OptionsPage.registeredPages[name]);
+ }
+
+ // Hide all sections. If the search string matches a title page, show
+ // all sections of that page.
+ for (var key in pagesToSearch) {
+ var page = pagesToSearch[key];
+ var pageTitle = page.title.toLowerCase();
+ // Hide non-sections in each page.
+ for (var i = 0; i < page.pageDiv.childNodes.length; i++) {
+ var childDiv = page.pageDiv.childNodes[i];
+ if (childDiv.nodeType == 1 &&
+ childDiv.nodeName.toLowerCase() == 'section') {
+ if (pageTitle == searchText) {
+ childDiv.classList.remove('search-hidden');
+ foundMatches = true;
+ } else {
+ childDiv.classList.add('search-hidden');
+ }
+ }
+ }
+ }
+
+ // Now search all sections for anchored string matches.
+ if (!foundMatches && searchText.length) {
+ var searchRegEx = new RegExp('\\b' + searchText, 'i');
+ for (var key in pagesToSearch) {
+ var page = pagesToSearch[key];
+ for (var i = 0; i < page.pageDiv.childNodes.length; i++) {
+ var childDiv = page.pageDiv.childNodes[i];
+ if (childDiv.nodeType == 1 &&
+ childDiv.nodeName.toLowerCase() == 'section') {
+ var isMatch = false;
+ var sectionElements = childDiv.getElementsByTagName("*");
+ var length = sectionElements.length;
+ var element;
+ for (var j = 0; j < length; j++) {
+ element = sectionElements[j];
+ if (searchRegEx.test(element.textContent)) {
+ isMatch = true;
+ break;
+ }
+ }
+ if (isMatch) {
+ childDiv.classList.remove('search-hidden');
+ foundMatches = true;
+ }
+ }
+ }
+ }
+ }
- SearchPage.updateForSuccessfulSearch = function(enable) {
- $('searchPageInfo').classList.add('hidden');
- $('searchPageNoMatches').classList.add('hidden');
+ // Configure elements on the search results page based on search results.
+ if (searchText.length == 0) {
+ $('searchPageInfo').classList.remove('search-hidden');
+ $('searchPageNoMatches').classList.add('search-hidden');
+ } else if (foundMatches) {
+ $('searchPageInfo').classList.add('search-hidden');
+ $('searchPageNoMatches').classList.add('search-hidden');
+ } else {
+ $('searchPageInfo').classList.add('search-hidden');
+ $('searchPageNoMatches').classList.remove('search-hidden');
+ }
+ }
};
// Export