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

Side by Side Diff: chrome/browser/resources/settings/search_settings.js

Issue 2739323005: MD Settings: Allow search within settings to track multiple requests separately. (Closed)
Patch Set: Fix test error. Created 3 years, 9 months 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
OLDNEW
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 ORIGINAL_CONTENT_CSS_CLASS = 'search-highlight-original-content'; 10 var ORIGINAL_CONTENT_CSS_CLASS = 'search-highlight-original-content';
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 * 118 *
119 * @param {!settings.SearchRequest} request 119 * @param {!settings.SearchRequest} request
120 * @param {!Node} root The root of the sub-tree to be searched 120 * @param {!Node} root The root of the sub-tree to be searched
121 * @private 121 * @private
122 */ 122 */
123 function findAndHighlightMatches_(request, root) { 123 function findAndHighlightMatches_(request, root) {
124 var foundMatches = false; 124 var foundMatches = false;
125 function doSearch(node) { 125 function doSearch(node) {
126 if (node.nodeName == 'TEMPLATE' && node.hasAttribute('route-path') && 126 if (node.nodeName == 'TEMPLATE' && node.hasAttribute('route-path') &&
127 !node.if && !node.hasAttribute(SKIP_SEARCH_CSS_ATTRIBUTE)) { 127 !node.if && !node.hasAttribute(SKIP_SEARCH_CSS_ATTRIBUTE)) {
128 getSearchManager().queue_.addRenderTask( 128 request.queue_.addRenderTask(new RenderTask(request, node));
129 new RenderTask(request, node));
130 return; 129 return;
131 } 130 }
132 131
133 if (IGNORED_ELEMENTS.has(node.nodeName)) 132 if (IGNORED_ELEMENTS.has(node.nodeName))
134 return; 133 return;
135 134
136 if (node instanceof HTMLElement) { 135 if (node instanceof HTMLElement) {
137 var element = /** @type {HTMLElement} */(node); 136 var element = /** @type {HTMLElement} */(node);
138 if (element.hasAttribute(SKIP_SEARCH_CSS_ATTRIBUTE) || 137 if (element.hasAttribute(SKIP_SEARCH_CSS_ATTRIBUTE) ||
139 element.hasAttribute('hidden') || 138 element.hasAttribute('hidden') ||
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 assert(!this.node.if); 296 assert(!this.node.if);
298 this.node.if = true; 297 this.node.if = true;
299 298
300 return new Promise(function(resolve, reject) { 299 return new Promise(function(resolve, reject) {
301 var parent = this.node.parentNode; 300 var parent = this.node.parentNode;
302 parent.async(function() { 301 parent.async(function() {
303 var renderedNode = 302 var renderedNode =
304 parent.querySelector('[route-path="' + routePath + '"]'); 303 parent.querySelector('[route-path="' + routePath + '"]');
305 // Register a SearchAndHighlightTask for the part of the DOM that was 304 // Register a SearchAndHighlightTask for the part of the DOM that was
306 // just rendered. 305 // just rendered.
307 getSearchManager().queue_.addSearchAndHighlightTask( 306 this.request.queue_.addSearchAndHighlightTask(
Dan Beam 2017/03/14 00:44:27 should this be this.request_?
dpapad 2017/03/14 03:28:11 This is a protected member variable from the super
308 new SearchAndHighlightTask(this.request, assert(renderedNode))); 307 new SearchAndHighlightTask(this.request, assert(renderedNode)));
309 resolve(); 308 resolve();
310 }.bind(this)); 309 }.bind(this));
311 }.bind(this)); 310 }.bind(this));
312 }, 311 },
313 }; 312 };
314 313
315 /** 314 /**
316 * @constructor 315 * @constructor
317 * @extends {Task} 316 * @extends {Task}
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 setSectionsVisibility_: function(visible) { 364 setSectionsVisibility_: function(visible) {
366 var sections = this.node.querySelectorAll('settings-section'); 365 var sections = this.node.querySelectorAll('settings-section');
367 366
368 for (var i = 0; i < sections.length; i++) 367 for (var i = 0; i < sections.length; i++)
369 sections[i].hiddenBySearch = !visible; 368 sections[i].hiddenBySearch = !visible;
370 }, 369 },
371 }; 370 };
372 371
373 /** 372 /**
374 * @constructor 373 * @constructor
374 * @param {!settings.SearchRequest} request
375 */ 375 */
376 function TaskQueue() { 376 function TaskQueue(request) {
377 /** @private {!settings.SearchRequest} */
378 this.request_ = request;
379
377 /** 380 /**
378 * @private {{ 381 * @private {{
379 * high: !Array<!Task>, 382 * high: !Array<!Task>,
380 * middle: !Array<!Task>, 383 * middle: !Array<!Task>,
381 * low: !Array<!Task> 384 * low: !Array<!Task>
382 * }} 385 * }}
383 */ 386 */
384 this.queues_; 387 this.queues_;
385 this.reset(); 388 this.reset();
386 389
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 var task = this.popNextTask_(); 448 var task = this.popNextTask_();
446 if (!task) { 449 if (!task) {
447 this.running_ = false; 450 this.running_ = false;
448 if (this.onEmptyCallback_) 451 if (this.onEmptyCallback_)
449 this.onEmptyCallback_(); 452 this.onEmptyCallback_();
450 return; 453 return;
451 } 454 }
452 455
453 this.running_ = true; 456 this.running_ = true;
454 window.requestIdleCallback(function() { 457 window.requestIdleCallback(function() {
455 function startNextTask() { 458 if (!this.request_.canceled) {
456 this.running_ = false; 459 task.exec().then(function() {
457 this.consumePending_(); 460 this.running_ = false;
461 this.consumePending_();
462 }.bind(this));
458 } 463 }
459 if (task.request.id == 464 // Nothing to do otherwise. Since the request corresponding to this
460 getSearchManager().activeRequest_.id) { 465 // queue was canceled, the queue is disposed along with the request.
461 task.exec().then(startNextTask.bind(this));
462 } else {
463 // Dropping this task without ever executing it, since a new search
464 // has been issued since this task was queued.
465 startNextTask.call(this);
466 }
467 }.bind(this)); 466 }.bind(this));
468 return; 467 return;
469 } 468 }
470 }, 469 },
471 }; 470 };
472 471
473 /** 472 /**
474 * @constructor 473 * @constructor
474 *
475 * @param {string} rawQuery
476 * @param {!HTMLElement} root
475 */ 477 */
476 var SearchRequest = function(rawQuery) { 478 var SearchRequest = function(rawQuery, root) {
477 /** @type {number} */
478 this.id = SearchRequest.nextId_++;
479
480 /** @private {string} */ 479 /** @private {string} */
481 this.rawQuery_ = rawQuery; 480 this.rawQuery_ = rawQuery;
482 481
482 /** @private {!HTMLElement} */
483 this.root = root;
Dan Beam 2017/03/14 00:44:27 if this is private, root_
dpapad 2017/03/14 03:28:11 Done.
484
483 /** @type {?RegExp} */ 485 /** @type {?RegExp} */
484 this.regExp = this.generateRegExp_(); 486 this.regExp = this.generateRegExp_();
485 487
486 /** 488 /**
487 * Whether this request was fully processed. 489 * Whether this request was canceled before completing.
488 * @type {boolean} 490 * @type {boolean}
489 */ 491 */
490 this.finished = false; 492 this.canceled = false;
491 493
492 /** @private {boolean} */ 494 /** @private {boolean} */
493 this.foundMatches_ = false; 495 this.foundMatches_ = false;
494 496
495 /** @type {!PromiseResolver} */ 497 /** @type {!PromiseResolver} */
496 this.resolver = new PromiseResolver(); 498 this.resolver = new PromiseResolver();
499
500 /** @private {!TaskQueue} */
501 this.queue_ = new TaskQueue(this);
502 this.queue_.onEmpty(function() {
503 this.resolver.resolve(this);
504 }.bind(this));
497 }; 505 };
498 506
499 /** @private {number} */
500 SearchRequest.nextId_ = 0;
501
502 /** @private {!RegExp} */ 507 /** @private {!RegExp} */
503 SearchRequest.SANITIZE_REGEX_ = /[-[\]{}()*+?.,\\^$|#\s]/g; 508 SearchRequest.SANITIZE_REGEX_ = /[-[\]{}()*+?.,\\^$|#\s]/g;
504 509
505 SearchRequest.prototype = { 510 SearchRequest.prototype = {
506 /** 511 /**
512 * Fires this search request.
513 */
514 start: function() {
515 this.queue_.addTopLevelSearchTask(
516 new TopLevelSearchTask(this, this.root));
517 },
518
519 /**
507 * @return {?RegExp} 520 * @return {?RegExp}
508 * @private 521 * @private
509 */ 522 */
510 generateRegExp_: function() { 523 generateRegExp_: function() {
511 var regExp = null; 524 var regExp = null;
512 525
513 // Generate search text by escaping any characters that would be 526 // Generate search text by escaping any characters that would be
514 // problematic for regular expressions. 527 // problematic for regular expressions.
515 var searchText = this.rawQuery_.trim().replace( 528 var searchText = this.rawQuery_.trim().replace(
516 SearchRequest.SANITIZE_REGEX_, '\\$&'); 529 SearchRequest.SANITIZE_REGEX_, '\\$&');
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 * searching finished. 567 * searching finished.
555 */ 568 */
556 search: function(text, page) {} 569 search: function(text, page) {}
557 }; 570 };
558 571
559 /** 572 /**
560 * @constructor 573 * @constructor
561 * @implements {SearchManager} 574 * @implements {SearchManager}
562 */ 575 */
563 var SearchManagerImpl = function() { 576 var SearchManagerImpl = function() {
564 /** @private {?settings.SearchRequest} */ 577 /** @private {!Set<!settings.SearchRequest>} */
565 this.activeRequest_ = null; 578 this.activeRequests_ = new Set();
566 579
567 /** @private {!TaskQueue} */ 580 /** @private {?string} */
568 this.queue_ = new TaskQueue(); 581 this.lastSearchedText_ = null;
569 this.queue_.onEmpty(function() {
570 this.activeRequest_.finished = true;
571 this.activeRequest_.resolver.resolve(this.activeRequest_);
572 this.activeRequest_ = null;
573 }.bind(this));
574 }; 582 };
575 cr.addSingletonGetter(SearchManagerImpl); 583 cr.addSingletonGetter(SearchManagerImpl);
576 584
577 SearchManagerImpl.prototype = { 585 SearchManagerImpl.prototype = {
578 /** @override */ 586 /** @override */
579 search: function(text, page) { 587 search: function(text, page) {
580 // Creating a new request only if the |text| changed. 588 // Cancel any pending requests if a request with different text is
581 if (!this.activeRequest_ || !this.activeRequest_.isSame(text)) { 589 // submitted.
582 // Resolving previous search request without marking it as 590 if (text != this.lastSearchedText_) {
583 // 'finished', if any, and dropping all pending tasks. 591 this.activeRequests_.forEach(function(request) {
584 this.queue_.reset(); 592 request.canceled = true;
585 if (this.activeRequest_) 593 request.resolver.resolve(request);
586 this.activeRequest_.resolver.resolve(this.activeRequest_); 594 });
587 595 this.activeRequests_.clear();
588 this.activeRequest_ = new SearchRequest(text);
589 } 596 }
590 597
591 this.queue_.addTopLevelSearchTask( 598 this.lastSearchedText_ = text;
592 new TopLevelSearchTask(this.activeRequest_, page)); 599 var request = new SearchRequest(text, page);
593 600 this.activeRequests_.add(request);
594 return this.activeRequest_.resolver.promise; 601 request.start();
602 return request.resolver.promise.then(function() {
603 // Stop tracking requests that finished.
604 this.activeRequests_.delete(request);
605 return request;
606 }.bind(this));
595 }, 607 },
596 }; 608 };
597 609
598 /** @return {!SearchManager} */ 610 /** @return {!SearchManager} */
599 function getSearchManager() { 611 function getSearchManager() {
600 return SearchManagerImpl.getInstance(); 612 return SearchManagerImpl.getInstance();
601 } 613 }
602 614
603 /** 615 /**
604 * Sets the SearchManager singleton instance, useful for testing. 616 * Sets the SearchManager singleton instance, useful for testing.
605 * @param {!SearchManager} searchManager 617 * @param {!SearchManager} searchManager
606 */ 618 */
607 function setSearchManagerForTesting(searchManager) { 619 function setSearchManagerForTesting(searchManager) {
608 SearchManagerImpl.instance_ = searchManager; 620 SearchManagerImpl.instance_ = searchManager;
609 } 621 }
610 622
611 return { 623 return {
612 getSearchManager: getSearchManager, 624 getSearchManager: getSearchManager,
613 setSearchManagerForTesting: setSearchManagerForTesting, 625 setSearchManagerForTesting: setSearchManagerForTesting,
614 SearchRequest: SearchRequest, 626 SearchRequest: SearchRequest,
615 }; 627 };
616 }); 628 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698