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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/quick_open/FilteredListWidget.js

Issue 2773583002: [DevTools] Introduce a sidebar with a drop-down
Patch Set: [DevTools] Introduce a sidebar with a drop-down Created 3 years, 7 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 /* 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
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
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
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
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
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
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 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698