Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: chrome/browser/resources/options/search_page.js

Issue 5992004: dom-ui settings: Enable searching for sub-pages... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 cr.define('options', function() { 5 cr.define('options', function() {
6 const OptionsPage = options.OptionsPage; 6 const OptionsPage = options.OptionsPage;
7 7
8 /** 8 /**
9 * Encapsulated handling of the search page. 9 * Encapsulated handling of the search page.
10 * @constructor 10 * @constructor
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 self.tab.appendChild(searchField); 42 self.tab.appendChild(searchField);
43 43
44 // Handle search events. (No need to throttle, WebKit's search field 44 // Handle search events. (No need to throttle, WebKit's search field
45 // will do that automatically.) 45 // will do that automatically.)
46 searchField.onsearch = function(e) { 46 searchField.onsearch = function(e) {
47 self.setSearchText_(this.value); 47 self.setSearchText_(this.value);
48 }; 48 };
49 }, 49 },
50 50
51 /** 51 /**
52 * @inheritDoc
53 */
54 get sticky() {
55 return true;
56 },
57
58 /**
52 * Called after this page has shown. 59 * Called after this page has shown.
53 */ 60 */
54 didShowPage: function() { 61 didShowPage: function() {
55 // This method is called by the Options page after all pages have 62 // This method is called by the Options page after all pages have
56 // had their visibilty attribute set. At this point we can perform the 63 // had their visibilty attribute set. At this point we can perform the
57 // search specific DOM manipulation. 64 // search specific DOM manipulation.
58 this.setSearchActive_(true); 65 this.setSearchActive_(true);
59 }, 66 },
60 67
61 /** 68 /**
(...skipping 22 matching lines...) Expand all
84 this.searchActive_ = active; 91 this.searchActive_ = active;
85 if (active) { 92 if (active) {
86 // Reset the search criteria, effectively hiding all the sections. 93 // Reset the search criteria, effectively hiding all the sections.
87 this.setSearchText_(''); 94 this.setSearchText_('');
88 } else { 95 } else {
89 // Just wipe out any active search text since it's no longer relevant. 96 // Just wipe out any active search text since it's no longer relevant.
90 $('search-field').value = ''; 97 $('search-field').value = '';
91 } 98 }
92 } 99 }
93 100
94 var page, length, childDiv; 101 var page, key, length, childDiv, i;
95 var pagesToSearch = this.getSearchablePages_(); 102 var pagesToSearch = this.getSearchablePages_();
96 for (var key in pagesToSearch) { 103 for (key in pagesToSearch) {
97 var page = pagesToSearch[key]; 104 page = pagesToSearch[key];
98 105
99 if (!active) { 106 if (!active)
100 page.visible = false; 107 page.visible = false;
101 this.unhighlightMatches_(page.tab);
102 this.unhighlightMatches_(page.pageDiv);
103 }
104 108
105 // Update the visible state of all top-level elements that are not 109 // Update the visible state of all top-level elements that are not
106 // sections (ie titles, button strips). We do this before changing 110 // sections (ie titles, button strips). We do this before changing
107 // the page visibility to avoid excessive re-draw. 111 // the page visibility to avoid excessive re-draw.
108 length = page.pageDiv.childNodes.length; 112 length = page.pageDiv.childNodes.length;
109 for (var i = 0; i < length; i++) { 113 for (i = 0; i < length; i++) {
110 childDiv = page.pageDiv.childNodes[i]; 114 childDiv = page.pageDiv.childNodes[i];
111 if (childDiv.nodeType == document.ELEMENT_NODE) { 115 if (childDiv.nodeType == document.ELEMENT_NODE) {
112 if (active) { 116 if (active) {
113 if (childDiv.nodeName.toLowerCase() != 'section') 117 if (childDiv.nodeName.toLowerCase() != 'section')
114 childDiv.classList.add('search-hidden'); 118 childDiv.classList.add('search-hidden');
115 } else { 119 } else {
116 childDiv.classList.remove('search-hidden'); 120 childDiv.classList.remove('search-hidden');
117 } 121 }
118 } 122 }
119 } 123 }
120 124
121 // Toggle the visibility state of the page.
122 if (active) { 125 if (active) {
123 // When search is active, remove the 'hidden' tag. This tag may have 126 // When search is active, remove the 'hidden' tag. This tag may have
124 // been added by the OptionsPage. 127 // been added by the OptionsPage.
125 page.pageDiv.classList.remove('hidden'); 128 page.pageDiv.classList.remove('hidden');
126 } 129 }
127 } 130 }
131
132 // After hiding all page content, remove any highlighted matches.
133 if (!active)
134 this.unhighlightMatches_();
128 }, 135 },
129 136
130 /** 137 /**
131 * Set the current search criteria. 138 * Set the current search criteria.
132 * @param {string} text Search text. 139 * @param {string} text Search text.
133 * @private 140 * @private
134 */ 141 */
135 setSearchText_: function(text) { 142 setSearchText_: function(text) {
136 var foundMatches = false; 143 var foundMatches = false;
137 144
145 // Remove any highlighted matches.
146 this.unhighlightMatches_();
147
138 // Generate search text by applying lowercase and escaping any characters 148 // Generate search text by applying lowercase and escaping any characters
139 // that would be problematic for regular expressions. 149 // that would be problematic for regular expressions.
140 var searchText = 150 var searchText =
141 text.toLowerCase().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); 151 text.toLowerCase().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
142 152
143 // Generate a regular expression and replace string for hilighting 153 // Generate a regular expression and replace string for hilighting
144 // search terms. 154 // search terms.
145 var regEx = new RegExp('(\\b' + searchText + ')', 'ig'); 155 var regEx = new RegExp('(\\b' + searchText + ')', 'ig');
146 var replaceString = '<span class="search-highlighted">$1</span>'; 156 var replaceString = '<span class="search-highlighted">$1</span>';
147 157
148 // Initialize all sections. If the search string matches a title page, 158 // Initialize all sections. If the search string matches a title page,
149 // show sections for that page. 159 // show sections for that page.
160 var page, key, pageMatch, childDiv, i;
150 var pagesToSearch = this.getSearchablePages_(); 161 var pagesToSearch = this.getSearchablePages_();
151 for (var key in pagesToSearch) { 162 for (key in pagesToSearch) {
152 var page = pagesToSearch[key]; 163 page = pagesToSearch[key];
153 this.unhighlightMatches_(page.tab); 164 pageMatch = false;
154 this.unhighlightMatches_(page.pageDiv);
155 var pageMatch = false;
156 if (searchText.length) { 165 if (searchText.length) {
157 pageMatch = this.performReplace_(regEx, replaceString, page.tab); 166 pageMatch = this.performReplace_(regEx, replaceString, page.tab);
158 } 167 }
159 if (pageMatch) 168 if (pageMatch)
160 foundMatches = true; 169 foundMatches = true;
161 for (var i = 0; i < page.pageDiv.childNodes.length; i++) { 170 for (i = 0; i < page.pageDiv.childNodes.length; i++) {
162 var childDiv = page.pageDiv.childNodes[i]; 171 childDiv = page.pageDiv.childNodes[i];
163 if (childDiv.nodeType == document.ELEMENT_NODE && 172 if (childDiv.nodeType == document.ELEMENT_NODE &&
164 childDiv.nodeName.toLowerCase() == 'section') { 173 childDiv.nodeName.toLowerCase() == 'section') {
165 if (pageMatch) { 174 if (pageMatch) {
166 childDiv.classList.remove('search-hidden'); 175 childDiv.classList.remove('search-hidden');
167 } else { 176 } else {
168 childDiv.classList.add('search-hidden'); 177 childDiv.classList.add('search-hidden');
169 } 178 }
170 } 179 }
171 } 180 }
172 } 181 }
173 182
174 // Search all sections for anchored string matches.
175 if (searchText.length) { 183 if (searchText.length) {
176 for (var key in pagesToSearch) { 184 // Search all sub-pages, generating an array of top-level sections that
177 var page = pagesToSearch[key]; 185 // we need to make visible.
178 for (var i = 0; i < page.pageDiv.childNodes.length; i++) { 186 var subPagesToSearch = this.getSearchableSubPages_();
179 var childDiv = page.pageDiv.childNodes[i]; 187 var control, node;
188 for (key in subPagesToSearch) {
189 page = subPagesToSearch[key];
190 if (this.performReplace_(regEx, replaceString, page.pageDiv)) {
191 section = page.associatedSection;
192 if (section)
193 section.classList.remove('search-hidden');
194 controls = page.associatedControls;
195 if (controls) {
196 // TODO(csilv): highlight each control.
197 }
198
199 foundMatches = true;
200 }
201 }
202
203 // Search all top-level sections for anchored string matches.
204 for (key in pagesToSearch) {
205 page = pagesToSearch[key];
206 for (i = 0; i < page.pageDiv.childNodes.length; i++) {
207 childDiv = page.pageDiv.childNodes[i];
180 if (childDiv.nodeType == document.ELEMENT_NODE && 208 if (childDiv.nodeType == document.ELEMENT_NODE &&
181 childDiv.nodeName.toLowerCase() == 'section' && 209 childDiv.nodeName.toLowerCase() == 'section' &&
182 this.performReplace_(regEx, replaceString, childDiv)) { 210 this.performReplace_(regEx, replaceString, childDiv)) {
183 childDiv.classList.remove('search-hidden'); 211 childDiv.classList.remove('search-hidden');
184 foundMatches = true; 212 foundMatches = true;
185 } 213 }
186 } 214 }
187 } 215 }
188 } 216 }
189 217
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 tmp.parentNode.removeChild(tmp); 273 tmp.parentNode.removeChild(tmp);
246 } else { 274 } else {
247 node = walker.nextNode(); 275 node = walker.nextNode();
248 } 276 }
249 } 277 }
250 278
251 return found; 279 return found;
252 }, 280 },
253 281
254 /** 282 /**
255 * Removes all search highlight tags from a container element. 283 * Removes all search highlight tags from the document.
256 * @param {Element} element An HTML container element.
257 * @private 284 * @private
258 */ 285 */
259 unhighlightMatches_: function(element) { 286 unhighlightMatches_: function() {
260 // Find all search highlight elements. 287 // Find all search highlight elements.
261 var elements = element.querySelectorAll('.search-highlighted'); 288 var elements = document.querySelectorAll('.search-highlighted');
262 289
263 // For each element, remove the highlighting. 290 // For each element, remove the highlighting.
264 var node, parent, i, length = elements.length; 291 var node, parent, i, length = elements.length;
265 for (i = 0; i < length; i++) { 292 for (i = 0; i < length; i++) {
266 node = elements[i]; 293 node = elements[i];
267 parent = node.parentNode; 294 parent = node.parentNode;
268 295
269 // Replace the highlight element with the first child (the text node). 296 // Replace the highlight element with the first child (the text node).
270 parent.replaceChild(node.firstChild, node); 297 parent.replaceChild(node.firstChild, node);
271 298
272 // Normalize the parent so that multiple text nodes will be combined. 299 // Normalize the parent so that multiple text nodes will be combined.
273 parent.normalize(); 300 parent.normalize();
274 } 301 }
275 }, 302 },
276 303
277 /** 304 /**
278 * Builds a list of pages to search. Omits the search page. 305 * Builds a list of top-level pages to search. Omits the search page and
306 * all sub-pages.
279 * @returns {Array} An array of pages to search. 307 * @returns {Array} An array of pages to search.
280 * @private 308 * @private
281 */ 309 */
282 getSearchablePages_: function() { 310 getSearchablePages_: function() {
283 var pages = []; 311 var name, page, pages = [];
284 for (var name in OptionsPage.registeredPages) { 312 for (name in OptionsPage.registeredPages) {
285 if (name != this.name) 313 if (name != this.name) {
286 pages.push(OptionsPage.registeredPages[name]); 314 page = OptionsPage.registeredPages[name];
315 if (!page.parentPage)
316 pages.push(page);
317 }
318 }
319 return pages;
320 },
321
322 /**
323 * Builds a list of sub-pages (and overlay pages) to search. Ignore pages
324 * that have no associated controls.
325 * @returns {Array} An array of pages to search.
326 * @private
327 */
328 getSearchableSubPages_: function() {
329 var name, pageInfo, page, pages = [];
330 for (name in OptionsPage.registeredPages) {
331 page = OptionsPage.registeredPages[name];
332 if (page.parentPage && page.associatedSection)
333 pages.push(page);
334 }
335 for (name in OptionsPage.registeredOverlayPages) {
336 page = OptionsPage.registeredOverlayPages[name];
337 if (page.associatedSection && page.pageDiv != undefined)
338 pages.push(page);
287 } 339 }
288 return pages; 340 return pages;
289 } 341 }
290 }; 342 };
291 343
292 // Export 344 // Export
293 return { 345 return {
294 SearchPage: SearchPage 346 SearchPage: SearchPage
295 }; 347 };
296 348
297 }); 349 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698