| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 /** | 6 /** |
| 7 * @unrestricted | 7 * @unrestricted |
| 8 * @implements {UI.ListDelegate} | 8 * @implements {UI.ListDelegate} |
| 9 */ | 9 */ |
| 10 QuickOpen.FilteredListWidget = class extends UI.VBox { | 10 QuickOpen.FilteredListWidget = class extends UI.VBox { |
| 11 /** | 11 /** |
| 12 * @param {?QuickOpen.FilteredListWidget.Provider} provider | 12 * @param {?QuickOpen.FilteredListWidget.Provider} provider |
| 13 * @param {!Array<string>=} promptHistory | 13 * @param {!Array<string>=} promptHistory |
| 14 * @param {function(string)=} queryChangedCallback | 14 * @param {function(string)=} queryChangedCallback |
| 15 */ | 15 */ |
| 16 constructor(provider, promptHistory, queryChangedCallback) { | 16 constructor(provider, promptHistory, queryChangedCallback) { |
| 17 super(true); | 17 super(true); |
| 18 this._promptHistory = promptHistory || []; | 18 this._promptHistory = promptHistory || []; |
| 19 | 19 |
| 20 this.contentElement.classList.add('filtered-list-widget'); | 20 this.contentElement.classList.add('filtered-list-widget'); |
| 21 this.contentElement.addEventListener('keydown', this._onKeyDown.bind(this),
true); | 21 this.contentElement.addEventListener('keydown', this._onKeyDown.bind(this),
true); |
| 22 this.registerRequiredCSS('quick_open/filteredListWidget.css'); | 22 this.registerRequiredCSS('quick_open/filteredListWidget.css'); |
| 23 | 23 |
| 24 this._promptElement = this.contentElement.createChild('div', 'filtered-list-
widget-input'); | 24 var promptContainer = this.contentElement.createChild('div', 'filtered-list-
widget-input-container'); |
| 25 this._iconContainer = promptContainer.createChild('div'); |
| 26 var container = promptContainer.createChild('div', 'filtered-list-widget-inp
ut'); |
| 27 this._promptElement = container.createChild('div'); |
| 25 this._promptElement.setAttribute('spellcheck', 'false'); | 28 this._promptElement.setAttribute('spellcheck', 'false'); |
| 26 this._promptElement.setAttribute('contenteditable', 'plaintext-only'); | 29 this._promptElement.setAttribute('contenteditable', 'plaintext-only'); |
| 27 this._prompt = new UI.TextPrompt(); | 30 this._prompt = new UI.TextPrompt(); |
| 28 this._prompt.initialize(() => Promise.resolve([])); | 31 this._prompt.initialize(() => Promise.resolve([])); |
| 29 var promptProxy = this._prompt.attach(this._promptElement); | 32 var promptProxy = this._prompt.attach(this._promptElement); |
| 30 promptProxy.addEventListener('input', this._onInput.bind(this), false); | 33 promptProxy.addEventListener('input', this._onInput.bind(this), false); |
| 31 promptProxy.classList.add('filtered-list-widget-prompt-element'); | 34 promptProxy.classList.add('filtered-list-widget-prompt-element'); |
| 32 | 35 |
| 33 this._bottomElementsContainer = this.contentElement.createChild('div', 'vbox
'); | 36 this._bottomElementsContainer = this.contentElement.createChild('div', 'vbox
'); |
| 34 this._progressElement = this._bottomElementsContainer.createChild('div', 'fi
ltered-list-widget-progress'); | 37 this._progressElement = this._bottomElementsContainer.createChild('div', 'fi
ltered-list-widget-progress'); |
| 35 this._progressBarElement = this._progressElement.createChild('div', 'filtere
d-list-widget-progress-bar'); | 38 this._progressBarElement = this._progressElement.createChild('div', 'filtere
d-list-widget-progress-bar'); |
| 36 | 39 |
| 37 /** @type {!UI.ListControl<number>} */ | 40 /** @type {!UI.ListControl<number>} */ |
| 38 this._list = new UI.ListControl(this, UI.ListMode.EqualHeightItems); | 41 this._list = new UI.ListControl(this, UI.ListMode.EqualHeightItems); |
| 39 this._itemElementsContainer = this._list.element; | 42 this._itemElementsContainer = this._list.element; |
| 43 this._itemElementsContainer.addEventListener('mousemove', event => this._upd
ateHover(event)); |
| 44 this._itemElementsContainer.addEventListener('mouseout', () => this._highlig
htItem(null)); |
| 40 this._itemElementsContainer.classList.add('container'); | 45 this._itemElementsContainer.classList.add('container'); |
| 41 this._bottomElementsContainer.appendChild(this._itemElementsContainer); | 46 this._bottomElementsContainer.appendChild(this._itemElementsContainer); |
| 42 this._itemElementsContainer.addEventListener('click', this._onClick.bind(thi
s), false); | 47 this._itemElementsContainer.addEventListener('click', this._onClick.bind(thi
s), false); |
| 43 | 48 |
| 44 this._notFoundElement = this._bottomElementsContainer.createChild('div', 'no
t-found-text'); | 49 this._notFoundElement = this._bottomElementsContainer.createChild('div', 'no
t-found-text'); |
| 45 this._notFoundElement.classList.add('hidden'); | 50 this._notFoundElement.classList.add('hidden'); |
| 46 | 51 |
| 47 this.setDefaultFocusedElement(this._promptElement); | 52 this.setDefaultFocusedElement(this._promptElement); |
| 48 | 53 |
| 49 this._prefix = ''; | 54 this._prefix = ''; |
| 50 this._provider = provider; | 55 this._provider = provider; |
| 51 this._queryChangedCallback = queryChangedCallback; | 56 this._queryChangedCallback = queryChangedCallback; |
| 57 |
| 58 /** @type {?number} */ |
| 59 this._initialSelectedItem = null; |
| 52 } | 60 } |
| 53 | 61 |
| 54 /** | 62 /** |
| 55 * @param {string} query | 63 * @param {string} query |
| 56 * @return {!RegExp} | 64 * @return {!RegExp} |
| 57 */ | 65 */ |
| 58 static filterRegex(query) { | 66 static filterRegex(query) { |
| 59 const toEscape = String.regexSpecialCharacters(); | 67 const toEscape = String.regexSpecialCharacters(); |
| 60 var regexString = ''; | 68 var regexString = ''; |
| 61 for (var i = 0; i < query.length; ++i) { | 69 for (var i = 0; i < query.length; ++i) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 return false; | 118 return false; |
| 111 } | 119 } |
| 112 | 120 |
| 113 /** | 121 /** |
| 114 * @param {string} placeholder | 122 * @param {string} placeholder |
| 115 */ | 123 */ |
| 116 setPlaceholder(placeholder) { | 124 setPlaceholder(placeholder) { |
| 117 this._prompt.setPlaceholder(placeholder); | 125 this._prompt.setPlaceholder(placeholder); |
| 118 } | 126 } |
| 119 | 127 |
| 120 showAsDialog() { | 128 /** |
| 129 * @param {!AnchorBox=} anchorBox |
| 130 * @param {!UI.GlassPane.AnchorBehavior=} anchorBehavior |
| 131 */ |
| 132 showAsDialog(anchorBox, anchorBehavior) { |
| 121 this._dialog = new UI.Dialog(); | 133 this._dialog = new UI.Dialog(); |
| 134 if (anchorBox) |
| 135 this._dialog.setContentAnchorBox(anchorBox); |
| 136 else |
| 137 this._dialog.setContentPosition(null, 22); |
| 122 this._dialog.setMaxContentSize(new UI.Size(504, 340)); | 138 this._dialog.setMaxContentSize(new UI.Size(504, 340)); |
| 123 this._dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.SetExactWidthMaxHeigh
t); | 139 this._dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.SetExactWidthMaxHeigh
t); |
| 124 this._dialog.setContentPosition(null, 22); | 140 if (anchorBehavior) |
| 141 this._dialog.setAnchorBehavior(anchorBehavior); |
| 125 this.show(this._dialog.contentElement); | 142 this.show(this._dialog.contentElement); |
| 126 this._dialog.show(); | 143 this._dialog.show(); |
| 127 } | 144 } |
| 128 | 145 |
| 129 /** | 146 /** |
| 130 * @param {string} prefix | 147 * @param {string} prefix |
| 131 */ | 148 */ |
| 132 setPrefix(prefix) { | 149 setPrefix(prefix) { |
| 133 this._prefix = prefix; | 150 this._prefix = prefix; |
| 134 } | 151 } |
| 135 | 152 |
| 136 /** | 153 /** |
| 137 * @param {?QuickOpen.FilteredListWidget.Provider} provider | 154 * @param {?QuickOpen.FilteredListWidget.Provider} provider |
| 138 */ | 155 */ |
| 139 setProvider(provider) { | 156 setProvider(provider) { |
| 140 if (provider === this._provider) | 157 if (provider === this._provider) |
| 141 return; | 158 return; |
| 142 | 159 |
| 143 if (this._provider) | 160 if (this._provider) |
| 144 this._provider.detach(); | 161 this._provider.detach(); |
| 145 this._clearTimers(); | 162 this._clearTimers(); |
| 146 | 163 |
| 147 this._provider = provider; | 164 this._provider = provider; |
| 148 if (this.isShowing()) | 165 if (this.isShowing()) |
| 149 this._attachProvider(); | 166 this._attachProvider(); |
| 150 } | 167 } |
| 151 | 168 |
| 169 /** |
| 170 * @param {?string} icon |
| 171 */ |
| 172 setInputIcon(icon) { |
| 173 this._iconContainer.removeChildren(); |
| 174 if (icon) |
| 175 this._iconContainer.appendChild(UI.Icon.create(icon, 'filtered-list-input-
icon')); |
| 176 } |
| 177 |
| 152 _attachProvider() { | 178 _attachProvider() { |
| 153 this._list.replaceAllItems([]); | 179 this._list.replaceAllItems([]); |
| 154 this._list.invalidateItemHeight(); | 180 this._list.invalidateItemHeight(); |
| 155 if (this._provider) { | 181 if (this._provider) { |
| 156 this._provider.setRefreshCallback(this._itemsLoaded.bind(this, this._provi
der)); | 182 this._provider.setRefreshCallback(this._itemsLoaded.bind(this, this._provi
der)); |
| 157 this._provider.attach(); | 183 this._provider.attach(); |
| 158 } | 184 } |
| 159 this._itemsLoaded(this._provider); | 185 this._itemsLoaded(this._provider); |
| 160 } | 186 } |
| 161 | 187 |
| 162 /** | 188 /** |
| 163 * @return {string} | 189 * @return {string} |
| 164 */ | 190 */ |
| 165 _value() { | 191 _value() { |
| 166 return this._prompt.text().trim(); | 192 return this._prompt.text().trim(); |
| 167 } | 193 } |
| 168 | 194 |
| 169 _cleanValue() { | 195 _cleanValue() { |
| 170 return this._value().substring(this._prefix.length); | 196 return this._value().substring(this._prefix.length); |
| 171 } | 197 } |
| 172 | 198 |
| 173 /** | 199 /** |
| 200 * @param {!Event} event |
| 201 */ |
| 202 _updateHover(event) { |
| 203 var item = this._list.itemForNode(/** @type {?Node} */ (event.target)); |
| 204 this._highlightItem(item); |
| 205 } |
| 206 |
| 207 /** |
| 174 * @override | 208 * @override |
| 175 */ | 209 */ |
| 176 wasShown() { | 210 wasShown() { |
| 177 this._attachProvider(); | 211 this._attachProvider(); |
| 178 } | 212 } |
| 179 | 213 |
| 180 /** | 214 /** |
| 181 * @override | 215 * @override |
| 182 */ | 216 */ |
| 183 willHide() { | 217 willHide() { |
| 218 this._highlightItem(null); |
| 184 if (this._provider) | 219 if (this._provider) |
| 185 this._provider.detach(); | 220 this._provider.detach(); |
| 186 this._clearTimers(); | 221 this._clearTimers(); |
| 187 } | 222 } |
| 188 | 223 |
| 189 _clearTimers() { | 224 _clearTimers() { |
| 190 clearTimeout(this._filterTimer); | 225 clearTimeout(this._filterTimer); |
| 191 clearTimeout(this._scoringTimer); | 226 clearTimeout(this._scoringTimer); |
| 192 clearTimeout(this._loadTimeout); | 227 clearTimeout(this._loadTimeout); |
| 193 delete this._filterTimer; | 228 delete this._filterTimer; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 * @param {?number} from | 298 * @param {?number} from |
| 264 * @param {?number} to | 299 * @param {?number} to |
| 265 * @param {?Element} fromElement | 300 * @param {?Element} fromElement |
| 266 * @param {?Element} toElement | 301 * @param {?Element} toElement |
| 267 */ | 302 */ |
| 268 selectedItemChanged(from, to, fromElement, toElement) { | 303 selectedItemChanged(from, to, fromElement, toElement) { |
| 269 if (fromElement) | 304 if (fromElement) |
| 270 fromElement.classList.remove('selected'); | 305 fromElement.classList.remove('selected'); |
| 271 if (toElement) | 306 if (toElement) |
| 272 toElement.classList.add('selected'); | 307 toElement.classList.add('selected'); |
| 308 this._highlightItem(to); |
| 273 } | 309 } |
| 274 | 310 |
| 275 /** | 311 /** |
| 312 * @param {number} item |
| 313 */ |
| 314 setInitialSelection(item) { |
| 315 if (this._list.length() > 0) |
| 316 this._list.selectItem(item, true); |
| 317 else |
| 318 this._initialSelectedItem = item; |
| 319 } |
| 320 |
| 321 /** |
| 276 * @param {!Event} event | 322 * @param {!Event} event |
| 277 */ | 323 */ |
| 278 _onClick(event) { | 324 _onClick(event) { |
| 279 var item = this._list.itemForNode(/** @type {?Node} */ (event.target)); | 325 var item = this._list.itemForNode(/** @type {?Node} */ (event.target)); |
| 280 if (item === null) | 326 if (item === null) |
| 281 return; | 327 return; |
| 282 | 328 |
| 283 event.consume(true); | 329 event.consume(true); |
| 284 this._selectItem(item); | 330 this._selectItem(item); |
| 285 if (this._dialog) | 331 if (this._dialog) |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 * @param {!Array<number>} bestItems | 473 * @param {!Array<number>} bestItems |
| 428 * @param {!Array<number>} overflowItems | 474 * @param {!Array<number>} overflowItems |
| 429 * @param {!Array<number>} filteredItems | 475 * @param {!Array<number>} filteredItems |
| 430 */ | 476 */ |
| 431 _refreshList(bestItems, overflowItems, filteredItems) { | 477 _refreshList(bestItems, overflowItems, filteredItems) { |
| 432 delete this._refreshListWithCurrentResult; | 478 delete this._refreshListWithCurrentResult; |
| 433 filteredItems = [].concat(bestItems, overflowItems, filteredItems); | 479 filteredItems = [].concat(bestItems, overflowItems, filteredItems); |
| 434 this._updateNotFoundMessage(!!filteredItems.length); | 480 this._updateNotFoundMessage(!!filteredItems.length); |
| 435 var oldHeight = this._list.element.offsetHeight; | 481 var oldHeight = this._list.element.offsetHeight; |
| 436 this._list.replaceAllItems(filteredItems); | 482 this._list.replaceAllItems(filteredItems); |
| 437 if (filteredItems.length) | 483 if (filteredItems.length) { |
| 438 this._list.selectItem(filteredItems[0]); | 484 var selection = filteredItems[0]; |
| 485 if (this._initialSelectedItem !== null && filteredItems.includes(this._ini
tialSelectedItem)) |
| 486 selection = this._initialSelectedItem; |
| 487 this._initialSelectedItem = null; |
| 488 this._list.selectItem(selection, true); |
| 489 } |
| 439 if (this._list.element.offsetHeight !== oldHeight) | 490 if (this._list.element.offsetHeight !== oldHeight) |
| 440 this._list.viewportResized(); | 491 this._list.viewportResized(); |
| 441 this._itemsFilteredForTest(); | 492 this._itemsFilteredForTest(); |
| 442 } | 493 } |
| 443 | 494 |
| 444 /** | 495 /** |
| 445 * @param {boolean} hasItems | 496 * @param {boolean} hasItems |
| 446 */ | 497 */ |
| 447 _updateNotFoundMessage(hasItems) { | 498 _updateNotFoundMessage(hasItems) { |
| 448 this._list.element.classList.toggle('hidden', !hasItems); | 499 this._list.element.classList.toggle('hidden', !hasItems); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 | 551 |
| 501 /** | 552 /** |
| 502 * @param {?number} itemIndex | 553 * @param {?number} itemIndex |
| 503 */ | 554 */ |
| 504 _selectItem(itemIndex) { | 555 _selectItem(itemIndex) { |
| 505 this._promptHistory.push(this._value()); | 556 this._promptHistory.push(this._value()); |
| 506 if (this._promptHistory.length > 100) | 557 if (this._promptHistory.length > 100) |
| 507 this._promptHistory.shift(); | 558 this._promptHistory.shift(); |
| 508 this._provider.selectItem(itemIndex, this._cleanValue()); | 559 this._provider.selectItem(itemIndex, this._cleanValue()); |
| 509 } | 560 } |
| 561 |
| 562 /** |
| 563 * @param {?number} item |
| 564 */ |
| 565 _highlightItem(item) { |
| 566 if (this._provider) |
| 567 this._provider.highlightItem(item); |
| 568 } |
| 510 }; | 569 }; |
| 511 | 570 |
| 512 | 571 |
| 513 /** | 572 /** |
| 514 * @unrestricted | 573 * @unrestricted |
| 515 */ | 574 */ |
| 516 QuickOpen.FilteredListWidget.Provider = class { | 575 QuickOpen.FilteredListWidget.Provider = class { |
| 517 /** | 576 /** |
| 518 * @param {function():void} refreshCallback | 577 * @param {function():void} refreshCallback |
| 519 */ | 578 */ |
| (...skipping 22 matching lines...) Expand all Loading... |
| 542 /** | 601 /** |
| 543 * @param {number} itemIndex | 602 * @param {number} itemIndex |
| 544 * @param {string} query | 603 * @param {string} query |
| 545 * @return {number} | 604 * @return {number} |
| 546 */ | 605 */ |
| 547 itemScoreAt(itemIndex, query) { | 606 itemScoreAt(itemIndex, query) { |
| 548 return 1; | 607 return 1; |
| 549 } | 608 } |
| 550 | 609 |
| 551 /** | 610 /** |
| 611 * @param {?number} itemIndex |
| 612 */ |
| 613 highlightItem(itemIndex) { |
| 614 } |
| 615 |
| 616 /** |
| 552 * @param {number} itemIndex | 617 * @param {number} itemIndex |
| 553 * @param {string} query | 618 * @param {string} query |
| 554 * @param {!Element} titleElement | 619 * @param {!Element} titleElement |
| 555 * @param {!Element} subtitleElement | 620 * @param {!Element} subtitleElement |
| 556 */ | 621 */ |
| 557 renderItem(itemIndex, query, titleElement, subtitleElement) { | 622 renderItem(itemIndex, query, titleElement, subtitleElement) { |
| 558 } | 623 } |
| 559 | 624 |
| 560 /** | 625 /** |
| 561 * @return {boolean} | 626 * @return {boolean} |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 * @param {string} query | 658 * @param {string} query |
| 594 * @return {string} | 659 * @return {string} |
| 595 */ | 660 */ |
| 596 notFoundText(query) { | 661 notFoundText(query) { |
| 597 return Common.UIString('No results found'); | 662 return Common.UIString('No results found'); |
| 598 } | 663 } |
| 599 | 664 |
| 600 detach() { | 665 detach() { |
| 601 } | 666 } |
| 602 }; | 667 }; |
| OLD | NEW |