| Index: chrome/browser/resources/options/search_page.js
|
| ===================================================================
|
| --- chrome/browser/resources/options/search_page.js (revision 68355)
|
| +++ chrome/browser/resources/options/search_page.js (working copy)
|
| @@ -7,9 +7,11 @@
|
|
|
| /**
|
| * 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 @@
|
| // 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);
|
| + },
|
|
|
| - SearchPage.updateForSuccessfulSearch = function(enable) {
|
| - $('searchPageInfo').classList.add('hidden');
|
| - $('searchPageNoMatches').classList.add('hidden');
|
| + /**
|
| + * 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;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + // 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
|
|
|