summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcsilv@chromium.org <csilv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-09 18:54:54 +0000
committercsilv@chromium.org <csilv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-09 18:54:54 +0000
commit829ddb955ec68f169f1dcd24af6d90f58307e8b7 (patch)
treeaab8599bd73b4f54645700bca915c9e525ef4cfe
parent32e1dee439ca0946f80508eeeedaebfbc2cc907c (diff)
downloadchromium_src-829ddb955ec68f169f1dcd24af6d90f58307e8b7.zip
chromium_src-829ddb955ec68f169f1dcd24af6d90f58307e8b7.tar.gz
chromium_src-829ddb955ec68f169f1dcd24af6d90f58307e8b7.tar.bz2
webui settings:
- Add basic highlighting for search results. - Allow partial page title search matches. BUG=59267 TEST=Perform searches in the webui settings window. Review URL: http://codereview.chromium.org/5562011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68751 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/resources/options/search_page.css4
-rw-r--r--chrome/browser/resources/options/search_page.js127
2 files changed, 92 insertions, 39 deletions
diff --git a/chrome/browser/resources/options/search_page.css b/chrome/browser/resources/options/search_page.css
index 03a775e..e5e44d6 100644
--- a/chrome/browser/resources/options/search_page.css
+++ b/chrome/browser/resources/options/search_page.css
@@ -1,3 +1,7 @@
.search-hidden {
display: none;
}
+
+.search-highlighted {
+ background-color: #fff29f;
+}
diff --git a/chrome/browser/resources/options/search_page.js b/chrome/browser/resources/options/search_page.js
index feec95a..5e76496 100644
--- a/chrome/browser/resources/options/search_page.js
+++ b/chrome/browser/resources/options/search_page.js
@@ -92,14 +92,19 @@ cr.define('options', function() {
}
var page, length, childDiv;
- for (var name in OptionsPage.registeredPages) {
- if (name == this.name)
- continue;
+ var pagesToSearch = this.getSearchablePages_();
+ for (var key in pagesToSearch) {
+ var page = pagesToSearch[key];
+
+ if (!active) {
+ page.visible = false;
+ this.unhighlightMatches_(page.tab);
+ this.unhighlightMatches_(page.pageDiv);
+ }
// 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];
@@ -108,7 +113,7 @@ cr.define('options', function() {
if (childDiv.nodeName.toLowerCase() != 'section')
childDiv.classList.add('search-hidden');
} else {
- childDiv.classList.remove('search-hidden');
+ childDiv.classList.remove('search-hidden');
}
}
}
@@ -118,8 +123,6 @@ cr.define('options', function() {
// 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;
}
}
},
@@ -130,29 +133,43 @@ cr.define('options', function() {
* @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]);
- }
+ // Generate search text by applying lowercase and escaping any characters
+ // that would be problematic for regular expressions.
+ var searchText =
+ text.toLowerCase().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
+
+ // Generate a regular expression and transform string for searching the
+ // navigation sidebar.
+ var navRegEx = new RegExp('(\\b' + searchText + ')', 'ig');
+ var navTransform = '<span class="search-highlighted">$1</span>';
- // Hide all sections. If the search string matches a title page, show
- // all sections of that page.
+ // Generate a regular expression and transform string for searching the
+ // pages.
+ var sectionRegEx =
+ new RegExp('>([^<]*)?(\\b' + searchText + ')([^>]*)?<', 'ig');
+ var sectionTransform = '>$1<span class="search-highlighted">$2</span>$3<';
+
+ // Initialize all sections. If the search string matches a title page,
+ // show sections for that page.
+ var pagesToSearch = this.getSearchablePages_();
for (var key in pagesToSearch) {
var page = pagesToSearch[key];
- var pageTitle = page.title.toLowerCase();
- // Hide non-sections in each page.
+ this.unhighlightMatches_(page.tab);
+ this.unhighlightMatches_(page.pageDiv);
+ var pageMatch = false;
+ if (searchText.length) {
+ pageMatch = this.performReplace_(navRegEx, navTransform, page.tab);
+ }
+ if (pageMatch)
+ foundMatches = true;
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) {
+ if (pageMatch) {
childDiv.classList.remove('search-hidden');
- foundMatches = true;
} else {
childDiv.classList.add('search-hidden');
}
@@ -160,30 +177,18 @@ cr.define('options', function() {
}
}
- // Now search all sections for anchored string matches.
- if (!foundMatches && searchText.length) {
- var searchRegEx = new RegExp('\\b' + searchText, 'i');
+ // Search all sections for anchored string matches.
+ if (searchText.length) {
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;
- }
+ childDiv.nodeName.toLowerCase() == 'section' &&
+ this.performReplace_(sectionRegEx, sectionTransform,
+ childDiv)) {
+ childDiv.classList.remove('search-hidden');
+ foundMatches = true;
}
}
}
@@ -200,6 +205,50 @@ cr.define('options', function() {
$('searchPageInfo').classList.add('search-hidden');
$('searchPageNoMatches').classList.remove('search-hidden');
}
+ },
+
+ /**
+ * Performs a string replacement based on a regex and transform.
+ * @param {RegEx} regex A regular expression for finding search matches.
+ * @param {String} transform A string to apply the replace operation.
+ * @param {Element} element An HTML container element.
+ * @returns {Boolean} true if the element was changed.
+ * @private
+ */
+ performReplace_: function(regex, transform, element) {
+ var originalHTML = element.innerHTML;
+ var newHTML = originalHTML.replace(regex, transform);
+ if (originalHTML != newHTML) {
+ element.innerHTML = newHTML;
+ return true;
+ } else {
+ return false;
+ }
+ },
+
+ /**
+ * Removes all search highlight tags from a container element.
+ * @param {Element} element An HTML container element.
+ * @private
+ */
+ unhighlightMatches_: function(element) {
+ var regex =
+ new RegExp('<span class="search-highlighted">(.*?)</span>', 'g');
+ element.innerHTML = element.innerHTML.replace(regex, '$1');
+ },
+
+ /**
+ * Builds a list of pages to search. Omits the search page.
+ * @returns {Array} An array of pages to search.
+ * @private
+ */
+ getSearchablePages_: function() {
+ var pages = [];
+ for (var name in OptionsPage.registeredPages) {
+ if (name != this.name)
+ pages.push(OptionsPage.registeredPages[name]);
+ }
+ return pages;
}
};