Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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('settings', function() { | 5 cr.define('settings', function() { |
| 6 /** @const {string} */ | 6 /** @const {string} */ |
| 7 var WRAPPER_CSS_CLASS = 'search-highlight-wrapper'; | 7 var WRAPPER_CSS_CLASS = 'search-highlight-wrapper'; |
| 8 | 8 |
| 9 /** @const {string} */ | 9 /** @const {string} */ |
| 10 var HIT_CSS_CLASS = 'search-highlight-hit'; | 10 var HIT_CSS_CLASS = 'search-highlight-hit'; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 | 96 |
| 97 /** | 97 /** |
| 98 * Traverses the entire DOM (including Shadow DOM), finds text nodes that | 98 * Traverses the entire DOM (including Shadow DOM), finds text nodes that |
| 99 * match the given regular expression and applies the highlight UI. It also | 99 * match the given regular expression and applies the highlight UI. It also |
| 100 * ensures that <settings-section> instances become visible if any matches | 100 * ensures that <settings-section> instances become visible if any matches |
| 101 * occurred under their subtree. | 101 * occurred under their subtree. |
| 102 * | 102 * |
| 103 * @param {!SearchRequest} request | 103 * @param {!settings.SearchRequest} request |
| 104 * @param {!Node} root The root of the sub-tree to be searched | 104 * @param {!Node} root The root of the sub-tree to be searched |
| 105 * @private | 105 * @private |
| 106 */ | 106 */ |
| 107 function findAndHighlightMatches_(request, root) { | 107 function findAndHighlightMatches_(request, root) { |
| 108 var foundMatches = false; | 108 var foundMatches = false; |
| 109 function doSearch(node) { | 109 function doSearch(node) { |
| 110 if (node.nodeName == 'TEMPLATE' && node.hasAttribute('name') && | 110 if (node.nodeName == 'TEMPLATE' && node.hasAttribute('name') && |
| 111 !node.if) { | 111 !node.if) { |
| 112 getSearchManager().queue_.addRenderTask( | 112 getSearchManager().queue_.addRenderTask( |
| 113 new RenderTask(request, node)); | 113 new RenderTask(request, node)); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 160 parent = parent.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? | 160 parent = parent.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? |
| 161 parent.host : parent.parentNode; | 161 parent.host : parent.parentNode; |
| 162 } | 162 } |
| 163 if (parent) | 163 if (parent) |
| 164 parent.hidden = false; | 164 parent.hidden = false; |
| 165 } | 165 } |
| 166 | 166 |
| 167 /** | 167 /** |
| 168 * @constructor | 168 * @constructor |
| 169 * | 169 * |
| 170 * @param {!SearchRequest} request | 170 * @param {!settings.SearchRequest} request |
| 171 * @param {!Node} node | 171 * @param {!Node} node |
| 172 */ | 172 */ |
| 173 function Task(request, node) { | 173 function Task(request, node) { |
| 174 /** @protected {!SearchRequest} */ | 174 /** @protected {!settings.SearchRequest} */ |
| 175 this.request = request; | 175 this.request = request; |
| 176 | 176 |
| 177 /** @protected {!Node} */ | 177 /** @protected {!Node} */ |
| 178 this.node = node; | 178 this.node = node; |
| 179 } | 179 } |
| 180 | 180 |
| 181 Task.prototype = { | 181 Task.prototype = { |
| 182 /** | 182 /** |
| 183 * @abstract | 183 * @abstract |
| 184 * @return {!Promise} | 184 * @return {!Promise} |
| 185 */ | 185 */ |
| 186 exec: function() {}, | 186 exec: function() {}, |
| 187 }; | 187 }; |
| 188 | 188 |
| 189 /** | 189 /** |
| 190 * A task that takes a <template is="dom-if">...</template> node corresponding | 190 * A task that takes a <template is="dom-if">...</template> node corresponding |
| 191 * to a setting subpage and renders it. A SearchAndHighlightTask is posted for | 191 * to a setting subpage and renders it. A SearchAndHighlightTask is posted for |
| 192 * the newly rendered subtree, once rendering is done. | 192 * the newly rendered subtree, once rendering is done. |
| 193 * @constructor | 193 * @constructor |
| 194 * @extends {Task} | 194 * @extends {Task} |
| 195 * | 195 * |
| 196 * @param {!SearchRequest} request | 196 * @param {!settings.SearchRequest} request |
| 197 * @param {!Node} node | 197 * @param {!Node} node |
| 198 */ | 198 */ |
| 199 function RenderTask(request, node) { | 199 function RenderTask(request, node) { |
| 200 Task.call(this, request, node); | 200 Task.call(this, request, node); |
| 201 } | 201 } |
| 202 | 202 |
| 203 RenderTask.prototype = { | 203 RenderTask.prototype = { |
| 204 /** @override */ | 204 /** @override */ |
| 205 exec: function() { | 205 exec: function() { |
| 206 var subpageTemplate = | 206 var subpageTemplate = |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 220 resolve(); | 220 resolve(); |
| 221 }.bind(this)); | 221 }.bind(this)); |
| 222 }.bind(this)); | 222 }.bind(this)); |
| 223 }, | 223 }, |
| 224 }; | 224 }; |
| 225 | 225 |
| 226 /** | 226 /** |
| 227 * @constructor | 227 * @constructor |
| 228 * @extends {Task} | 228 * @extends {Task} |
| 229 * | 229 * |
| 230 * @param {!SearchRequest} request | 230 * @param {!settings.SearchRequest} request |
| 231 * @param {!Node} node | 231 * @param {!Node} node |
| 232 */ | 232 */ |
| 233 function SearchAndHighlightTask(request, node) { | 233 function SearchAndHighlightTask(request, node) { |
| 234 Task.call(this, request, node); | 234 Task.call(this, request, node); |
| 235 } | 235 } |
| 236 | 236 |
| 237 SearchAndHighlightTask.prototype = { | 237 SearchAndHighlightTask.prototype = { |
| 238 /** @override */ | 238 /** @override */ |
| 239 exec: function() { | 239 exec: function() { |
| 240 var foundMatches = findAndHighlightMatches_(this.request, this.node); | 240 var foundMatches = findAndHighlightMatches_(this.request, this.node); |
| 241 this.request.updateMatches(foundMatches); | 241 this.request.updateMatches(foundMatches); |
| 242 return Promise.resolve(); | 242 return Promise.resolve(); |
| 243 }, | 243 }, |
| 244 }; | 244 }; |
| 245 | 245 |
| 246 /** | 246 /** |
| 247 * @constructor | 247 * @constructor |
| 248 * @extends {Task} | 248 * @extends {Task} |
| 249 * | 249 * |
| 250 * @param {!SearchRequest} request | 250 * @param {!settings.SearchRequest} request |
| 251 * @param {!Node} page | 251 * @param {!Node} page |
| 252 */ | 252 */ |
| 253 function TopLevelSearchTask(request, page) { | 253 function TopLevelSearchTask(request, page) { |
| 254 Task.call(this, request, page); | 254 Task.call(this, request, page); |
| 255 } | 255 } |
| 256 | 256 |
| 257 TopLevelSearchTask.prototype = { | 257 TopLevelSearchTask.prototype = { |
| 258 /** @override */ | 258 /** @override */ |
| 259 exec: function() { | 259 exec: function() { |
| 260 findAndRemoveHighlights_(this.node); | 260 findAndRemoveHighlights_(this.node); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 447 updateMatches: function(found) { | 447 updateMatches: function(found) { |
| 448 this.foundMatches_ = this.foundMatches_ || found; | 448 this.foundMatches_ = this.foundMatches_ || found; |
| 449 }, | 449 }, |
| 450 | 450 |
| 451 /** @return {boolean} Whether any matches were found. */ | 451 /** @return {boolean} Whether any matches were found. */ |
| 452 didFindMatches: function() { | 452 didFindMatches: function() { |
| 453 return this.foundMatches_; | 453 return this.foundMatches_; |
| 454 }, | 454 }, |
| 455 }; | 455 }; |
| 456 | 456 |
| 457 /** @interface */ | |
| 458 var SearchManager = function() {}; | |
| 459 | |
| 460 SearchManager.prototype = { | |
| 461 /** | |
| 462 * @param {string} text The text to search for. | |
| 463 * @param {!Node} page | |
| 464 * @return {!Promise<!settings.SearchRequest>} A signal indicating that | |
| 465 * searching finished. | |
| 466 */ | |
| 467 search: function(text, page) {} | |
| 468 }; | |
| 469 | |
| 457 /** | 470 /** |
| 458 * @constructor | 471 * @constructor |
| 472 * @implements {SearchManager} | |
| 459 */ | 473 */ |
| 460 var SearchManager = function() { | 474 var SearchManagerImpl = function() { |
| 461 /** @private {?SearchRequest} */ | 475 /** @private {?settings.SearchRequest} */ |
| 462 this.activeRequest_ = null; | 476 this.activeRequest_ = null; |
| 463 | 477 |
| 464 /** @private {!TaskQueue} */ | 478 /** @private {!TaskQueue} */ |
| 465 this.queue_ = new TaskQueue(); | 479 this.queue_ = new TaskQueue(); |
| 466 this.queue_.onEmpty(function() { | 480 this.queue_.onEmpty(function() { |
| 467 this.activeRequest_.finished = true; | 481 this.activeRequest_.finished = true; |
| 468 this.activeRequest_.resolver.resolve(this.activeRequest_); | 482 this.activeRequest_.resolver.resolve(this.activeRequest_); |
| 469 this.activeRequest_ = null; | 483 this.activeRequest_ = null; |
| 470 }.bind(this)); | 484 }.bind(this)); |
| 471 }; | 485 }; |
| 472 cr.addSingletonGetter(SearchManager); | 486 cr.addSingletonGetter(SearchManagerImpl); |
| 473 | 487 |
| 474 SearchManager.prototype = { | 488 SearchManagerImpl.prototype = { |
| 475 /** | 489 /** @override */ |
| 476 * @param {string} text The text to search for. | |
| 477 * @param {!Node} page | |
| 478 * @return {!Promise<!SearchRequest>} A signal indicating that searching | |
| 479 * finished. | |
| 480 */ | |
| 481 search: function(text, page) { | 490 search: function(text, page) { |
| 482 // Creating a new request only if the |text| changed. | 491 // Creating a new request only if the |text| changed. |
| 483 if (!this.activeRequest_ || !this.activeRequest_.isSame(text)) { | 492 if (!this.activeRequest_ || !this.activeRequest_.isSame(text)) { |
| 484 // Resolving previous search request without marking it as | 493 // Resolving previous search request without marking it as |
| 485 // 'finisthed', if any, and droping all pending tasks. | 494 // 'finisthed', if any, and droping all pending tasks. |
|
michaelpg
2016/07/30 05:38:44
dropping
michaelpg
2016/07/30 05:38:44
finished
dpapad
2016/08/01 21:23:06
Done.
| |
| 486 this.queue_.reset(); | 495 this.queue_.reset(); |
| 487 if (this.activeRequest_) | 496 if (this.activeRequest_) |
| 488 this.activeRequest_.resolver.resolve(this.activeRequest_); | 497 this.activeRequest_.resolver.resolve(this.activeRequest_); |
| 489 | 498 |
| 490 this.activeRequest_ = new SearchRequest(text); | 499 this.activeRequest_ = new SearchRequest(text); |
| 491 } | 500 } |
| 492 | 501 |
| 493 this.queue_.addTopLevelSearchTask( | 502 this.queue_.addTopLevelSearchTask( |
| 494 new TopLevelSearchTask(this.activeRequest_, page)); | 503 new TopLevelSearchTask(this.activeRequest_, page)); |
| 495 | 504 |
| 496 return this.activeRequest_.resolver.promise; | 505 return this.activeRequest_.resolver.promise; |
| 497 }, | 506 }, |
| 498 }; | 507 }; |
| 499 | 508 |
| 500 /** @return {!SearchManager} */ | 509 /** @return {!SearchManager} */ |
| 501 function getSearchManager() { | 510 function getSearchManager() { |
| 502 return SearchManager.getInstance(); | 511 return SearchManagerImpl.getInstance(); |
| 512 } | |
| 513 | |
| 514 /** | |
| 515 * Sets the SearchManager singleton instance, useful for testing. | |
| 516 * @param {!SearchManager} searchManager | |
| 517 */ | |
| 518 function setSearchManagerForTesting(searchManager) { | |
| 519 SearchManagerImpl.instance_ = searchManager; | |
| 503 } | 520 } |
| 504 | 521 |
| 505 return { | 522 return { |
| 506 getSearchManager: getSearchManager, | 523 getSearchManager: getSearchManager, |
| 524 setSearchManagerForTesting: setSearchManagerForTesting, | |
| 525 SearchRequest: SearchRequest, | |
| 507 }; | 526 }; |
| 508 }); | 527 }); |
| OLD | NEW |