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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js

Issue 2592433003: [DevTools] Replace ViewportControl with ListControl. (Closed)
Patch Set: different api Created 3 years, 12 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) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 28 matching lines...) Expand all
39 */ 39 */
40 applySuggestion(suggestion, isIntermediateSuggestion) {}, 40 applySuggestion(suggestion, isIntermediateSuggestion) {},
41 41
42 /** 42 /**
43 * acceptSuggestion will be always called after call to applySuggestion with i sIntermediateSuggestion being equal to false. 43 * acceptSuggestion will be always called after call to applySuggestion with i sIntermediateSuggestion being equal to false.
44 */ 44 */
45 acceptSuggestion() {}, 45 acceptSuggestion() {},
46 }; 46 };
47 47
48 /** 48 /**
49 * @implements {UI.ViewportControl.Provider}
50 * @unrestricted 49 * @unrestricted
51 */ 50 */
52 UI.SuggestBox = class { 51 UI.SuggestBox = class {
53 /** 52 /**
54 * @param {!UI.SuggestBoxDelegate} suggestBoxDelegate 53 * @param {!UI.SuggestBoxDelegate} suggestBoxDelegate
55 * @param {number=} maxItemsHeight 54 * @param {number=} maxItemsHeight
56 * @param {boolean=} captureEnter 55 * @param {boolean=} captureEnter
57 */ 56 */
58 constructor(suggestBoxDelegate, maxItemsHeight, captureEnter) { 57 constructor(suggestBoxDelegate, maxItemsHeight, captureEnter) {
59 this._suggestBoxDelegate = suggestBoxDelegate; 58 this._suggestBoxDelegate = suggestBoxDelegate;
60 this._length = 0;
61 this._selectedIndex = -1; 59 this._selectedIndex = -1;
62 this._selectedElement = null; 60 this._selectedElement = null;
63 this._maxItemsHeight = maxItemsHeight; 61 this._maxItemsHeight = maxItemsHeight;
64 this._maybeHideBound = this._maybeHide.bind(this); 62 this._maybeHideBound = this._maybeHide.bind(this);
65 this._container = createElementWithClass('div', 'suggest-box-container'); 63 this._container = createElementWithClass('div', 'suggest-box-container');
66 this._viewport = new UI.ViewportControl(this); 64 /** @type {!UI.ViewportControl<!UI.SuggestBox.Suggestion>} */
65 this._viewport = new UI.ViewportControl(this._createItemElement.bind(this));
67 this._element = this._viewport.element; 66 this._element = this._viewport.element;
68 this._element.classList.add('suggest-box'); 67 this._element.classList.add('suggest-box');
69 this._container.appendChild(this._element); 68 this._container.appendChild(this._element);
70 this._element.addEventListener('mousedown', this._onBoxMouseDown.bind(this), true); 69 this._element.addEventListener('mousedown', this._onBoxMouseDown.bind(this), true);
71 this._detailsPopup = this._container.createChild('div', 'suggest-box details -popup monospace'); 70 this._detailsPopup = this._container.createChild('div', 'suggest-box details -popup monospace');
72 this._detailsPopup.classList.add('hidden'); 71 this._detailsPopup.classList.add('hidden');
73 this._asyncDetailsCallback = null; 72 this._asyncDetailsCallback = null;
74 /** @type {!Map<number, !Promise<{detail: string, description: string}>>} */ 73 /** @type {!Map<number, !Promise<{detail: string, description: string}>>} */
75 this._asyncDetailsPromises = new Map(); 74 this._asyncDetailsPromises = new Map();
76 this._userInteracted = false; 75 this._userInteracted = false;
77 this._captureEnter = captureEnter; 76 this._captureEnter = captureEnter;
78 /** @type {!Array<!Element>} */
79 this._elementList = [];
80 this._rowHeight = 17;
81 this._viewportWidth = '100vw'; 77 this._viewportWidth = '100vw';
82 this._hasVerticalScroll = false; 78 this._hasVerticalScroll = false;
83 this._userEnteredText = ''; 79 this._userEnteredText = '';
84 /** @type {!UI.SuggestBox.Suggestions} */
85 this._items = [];
86 } 80 }
87 81
88 /** 82 /**
89 * @return {boolean} 83 * @return {boolean}
90 */ 84 */
91 visible() { 85 visible() {
92 return !!this._container.parentElement; 86 return !!this._container.parentElement;
93 } 87 }
94 88
95 /** 89 /**
96 * @param {!AnchorBox} anchorBox 90 * @param {!AnchorBox} anchorBox
97 */ 91 */
98 setPosition(anchorBox) { 92 setPosition(anchorBox) {
99 this._updateBoxPosition(anchorBox); 93 this._updateBoxPosition(anchorBox, this._viewport.length());
100 } 94 }
101 95
102 /** 96 /**
103 * @param {!AnchorBox} anchorBox 97 * @param {!AnchorBox} anchorBox
98 * @param {number} length
104 */ 99 */
105 _updateBoxPosition(anchorBox) { 100 _updateBoxPosition(anchorBox, length) {
106 console.assert(this._overlay); 101 console.assert(this._overlay);
107 if (this._lastAnchorBox && this._lastAnchorBox.equals(anchorBox) && this._la stItemCount === this.itemCount()) 102 if (this._lastAnchorBox && this._lastAnchorBox.equals(anchorBox) && this._la stItemCount === length)
108 return; 103 return;
109 this._lastItemCount = this.itemCount(); 104 this._lastItemCount = length;
110 this._lastAnchorBox = anchorBox; 105 this._lastAnchorBox = anchorBox;
111 106
112 // Position relative to main DevTools element. 107 // Position relative to main DevTools element.
113 var container = UI.Dialog.modalHostView().element; 108 var container = UI.Dialog.modalHostView().element;
114 anchorBox = anchorBox.relativeToElement(container); 109 anchorBox = anchorBox.relativeToElement(container);
115 var totalHeight = container.offsetHeight; 110 var totalHeight = container.offsetHeight;
116 var aboveHeight = anchorBox.y; 111 var aboveHeight = anchorBox.y;
117 var underHeight = totalHeight - anchorBox.y - anchorBox.height; 112 var underHeight = totalHeight - anchorBox.y - anchorBox.height;
118 113
119 this._overlay.setLeftOffset(anchorBox.x); 114 this._overlay.setLeftOffset(anchorBox.x);
120 115
121 var under = underHeight >= aboveHeight; 116 var under = underHeight >= aboveHeight;
122 if (under) 117 if (under)
123 this._overlay.setVerticalOffset(anchorBox.y + anchorBox.height, true); 118 this._overlay.setVerticalOffset(anchorBox.y + anchorBox.height, true);
124 else 119 else
125 this._overlay.setVerticalOffset(totalHeight - anchorBox.y, false); 120 this._overlay.setVerticalOffset(totalHeight - anchorBox.y, false);
126 121
127 var spacer = 6; 122 var spacer = 6;
128 var maxHeight = Math.min( 123 var maxHeight = Math.min(
129 Math.max(underHeight, aboveHeight) - spacer, 124 Math.max(underHeight, aboveHeight) - spacer,
130 this._maxItemsHeight ? this._maxItemsHeight * this._rowHeight : Infinity ); 125 this._maxItemsHeight ? this._maxItemsHeight * this._rowHeight : Infinity );
131 var height = this._rowHeight * this._items.length; 126 var height = this._rowHeight * length;
132 this._hasVerticalScroll = height > maxHeight; 127 this._hasVerticalScroll = height > maxHeight;
133 this._element.style.height = Math.min(maxHeight, height) + 'px'; 128 this._element.style.height = Math.min(maxHeight, height) + 'px';
134 } 129 }
135 130
136 _updateWidth() { 131 _updateWidth() {
137 if (this._hasVerticalScroll) { 132 if (this._hasVerticalScroll) {
138 this._element.style.width = '100vw'; 133 this._element.style.width = '100vw';
139 return; 134 return;
140 } 135 }
136 if (!this._viewport.length())
137 return;
141 // If there are no scrollbars, set the width to the width of the largest row . 138 // If there are no scrollbars, set the width to the width of the largest row .
139 var maxItem = this._viewport.itemAtIndex(0);
142 var maxIndex = 0; 140 var maxIndex = 0;
143 for (var i = 0; i < this._items.length; i++) { 141 for (var i = 1; i < this._viewport.length(); i++) {
144 if (this._items[i].title.length > this._items[maxIndex].title.length) 142 var item = this._viewport.itemAtIndex(i);
143 if (item.title.length > maxItem.title.length) {
144 maxItem = item;
145 maxIndex = i; 145 maxIndex = i;
146 }
146 } 147 }
147 var element = /** @type {!Element} */ (this.itemElement(maxIndex)); 148 this._element.style.width =
148 this._element.style.width = UI.measurePreferredSize(element, this._element). width + 'px'; 149 UI.measurePreferredSize(this._viewport.elementAtIndex(maxIndex), this._e lement).width + 'px';
149 } 150 }
150 151
151 /** 152 /**
152 * @param {!Event} event 153 * @param {!Event} event
153 */ 154 */
154 _onBoxMouseDown(event) { 155 _onBoxMouseDown(event) {
155 if (this._hideTimeoutId) { 156 if (this._hideTimeoutId) {
156 window.clearTimeout(this._hideTimeoutId); 157 window.clearTimeout(this._hideTimeoutId);
157 delete this._hideTimeoutId; 158 delete this._hideTimeoutId;
158 } 159 }
159 event.preventDefault(); 160 event.preventDefault();
160 } 161 }
161 162
162 _maybeHide() { 163 _maybeHide() {
163 if (!this._hideTimeoutId) 164 if (!this._hideTimeoutId)
164 this._hideTimeoutId = window.setTimeout(this.hide.bind(this), 0); 165 this._hideTimeoutId = window.setTimeout(this.hide.bind(this), 0);
165 } 166 }
166 167
167 /** 168 /**
168 * // FIXME: make SuggestBox work for multiple documents. 169 * // FIXME: make SuggestBox work for multiple documents.
169 * @suppressGlobalPropertiesCheck 170 * @suppressGlobalPropertiesCheck
170 */ 171 */
171 _show() { 172 _show() {
172 if (this.visible()) 173 if (this.visible())
173 return; 174 return;
174 this._bodyElement = document.body; 175 this._bodyElement = document.body;
175 this._bodyElement.addEventListener('mousedown', this._maybeHideBound, true); 176 this._bodyElement.addEventListener('mousedown', this._maybeHideBound, true);
176 this._overlay = new UI.SuggestBox.Overlay(); 177 this._overlay = new UI.SuggestBox.Overlay();
177 this._overlay.setContentElement(this._container); 178 this._overlay.setContentElement(this._container);
178 var measuringElement = this._createItemElement('1', '12'); 179 this._rowHeight =
179 this._viewport.element.appendChild(measuringElement); 180 UI.measurePreferredSize(this._createItemElement({title: '1', subtitle: ' 12'}), this._element).height;
180 this._rowHeight = measuringElement.getBoundingClientRect().height;
181 measuringElement.remove();
182 } 181 }
183 182
184 hide() { 183 hide() {
185 if (!this.visible()) 184 if (!this.visible())
186 return; 185 return;
187 186
188 this._userInteracted = false; 187 this._userInteracted = false;
189 this._bodyElement.removeEventListener('mousedown', this._maybeHideBound, tru e); 188 this._bodyElement.removeEventListener('mousedown', this._maybeHideBound, tru e);
190 delete this._bodyElement; 189 delete this._bodyElement;
191 this._container.remove(); 190 this._container.remove();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 233
235 return true; 234 return true;
236 } 235 }
237 236
238 /** 237 /**
239 * @param {number} shift 238 * @param {number} shift
240 * @param {boolean=} isCircular 239 * @param {boolean=} isCircular
241 * @return {boolean} is changed 240 * @return {boolean} is changed
242 */ 241 */
243 _selectClosest(shift, isCircular) { 242 _selectClosest(shift, isCircular) {
244 if (!this._length) 243 var length = this._viewport.length();
244 if (!length)
245 return false; 245 return false;
246 246
247 this._userInteracted = true; 247 this._userInteracted = true;
248 248
249 if (this._selectedIndex === -1 && shift < 0) 249 if (this._selectedIndex === -1 && shift < 0)
250 shift += 1; 250 shift += 1;
251 251
252 var index = this._selectedIndex + shift; 252 var index = this._selectedIndex + shift;
253 253
254 if (isCircular) 254 if (isCircular)
255 index = (this._length + index) % this._length; 255 index = (length + index) % length;
256 else 256 else
257 index = Number.constrain(index, 0, this._length - 1); 257 index = Number.constrain(index, 0, length - 1);
258 258
259 this._selectItem(index); 259 this._selectItem(index);
260 return true; 260 return true;
261 } 261 }
262 262
263 /** 263 /**
264 * @param {!Event} event 264 * @param {!Event} event
265 */ 265 */
266 _onItemMouseDown(event) { 266 _onItemMouseDown(event) {
267 this._selectedElement = event.currentTarget; 267 this._selectedElement = event.currentTarget;
268 this.acceptSuggestion(); 268 this.acceptSuggestion();
269 event.consume(true); 269 event.consume(true);
270 } 270 }
271 271
272 /** 272 /**
273 * @param {string} query 273 * @param {!UI.SuggestBox.Suggestion} item
274 * @param {string} title
275 * @param {string=} subtitle
276 * @param {string=} iconType
277 * @param {boolean=} isSecondary
278 * @return {!Element} 274 * @return {!Element}
279 */ 275 */
280 _createItemElement(query, title, subtitle, iconType, isSecondary) { 276 _createItemElement(item) {
277 var query = this._userEnteredText;
281 var element = createElementWithClass('div', 'suggest-box-content-item source -code'); 278 var element = createElementWithClass('div', 'suggest-box-content-item source -code');
282 if (iconType) { 279 if (item.iconType) {
283 var icon = UI.Icon.create(iconType, 'suggestion-icon'); 280 var icon = UI.Icon.create(item.iconType, 'suggestion-icon');
284 element.appendChild(icon); 281 element.appendChild(icon);
285 } 282 }
286 if (isSecondary) 283 if (item.isSecondary)
287 element.classList.add('secondary'); 284 element.classList.add('secondary');
288 element.tabIndex = -1; 285 element.tabIndex = -1;
289 var displayText = title.trimEnd(50 + query.length); 286 var displayText = item.title.trimEnd(50 + query.length);
290 287
291 var titleElement = element.createChild('span', 'suggestion-title'); 288 var titleElement = element.createChild('span', 'suggestion-title');
292 var index = displayText.toLowerCase().indexOf(query.toLowerCase()); 289 var index = displayText.toLowerCase().indexOf(query.toLowerCase());
293 if (index > 0) 290 if (index > 0)
294 titleElement.createChild('span').textContent = displayText.substring(0, in dex); 291 titleElement.createChild('span').textContent = displayText.substring(0, in dex);
295 if (index > -1) 292 if (index > -1)
296 titleElement.createChild('span', 'query').textContent = displayText.substr ing(index, index + query.length); 293 titleElement.createChild('span', 'query').textContent = displayText.substr ing(index, index + query.length);
297 titleElement.createChild('span').textContent = displayText.substring(index > -1 ? index + query.length : 0); 294 titleElement.createChild('span').textContent = displayText.substring(index > -1 ? index + query.length : 0);
298 titleElement.createChild('span', 'spacer'); 295 titleElement.createChild('span', 'spacer');
299 if (subtitle) { 296 if (item.subtitle) {
300 var subtitleElement = element.createChild('span', 'suggestion-subtitle'); 297 var subtitleElement = element.createChild('span', 'suggestion-subtitle');
301 subtitleElement.textContent = subtitle.trimEnd(15); 298 subtitleElement.textContent = item.subtitle.trimEnd(15);
302 } 299 }
303 element.__fullValue = title; 300 element.__fullValue = item.title;
304 element.addEventListener('mousedown', this._onItemMouseDown.bind(this), fals e); 301 element.addEventListener('mousedown', this._onItemMouseDown.bind(this), fals e);
305 return element; 302 return element;
306 } 303 }
307 304
308 /** 305 /**
309 * @param {!UI.SuggestBox.Suggestions} items
310 * @param {string} userEnteredText
311 * @param {function(number): !Promise<{detail:string, description:string}>=} a syncDetails
312 */
313 _updateItems(items, userEnteredText, asyncDetails) {
314 this._length = items.length;
315 this._asyncDetailsPromises.clear();
316 this._asyncDetailsCallback = asyncDetails;
317 this._elementList = [];
318 delete this._selectedElement;
319
320 this._userEnteredText = userEnteredText;
321 this._items = items;
322 }
323
324 /**
325 * @param {number} index 306 * @param {number} index
326 * @return {!Promise<?{detail: string, description: string}>} 307 * @return {!Promise<?{detail: string, description: string}>}
327 */ 308 */
328 _asyncDetails(index) { 309 _asyncDetails(index) {
329 if (!this._asyncDetailsCallback) 310 if (!this._asyncDetailsCallback)
330 return Promise.resolve(/** @type {?{description: string, detail: string}} */ (null)); 311 return Promise.resolve(/** @type {?{description: string, detail: string}} */ (null));
331 if (!this._asyncDetailsPromises.has(index)) 312 if (!this._asyncDetailsPromises.has(index))
332 this._asyncDetailsPromises.set(index, this._asyncDetailsCallback(index)); 313 this._asyncDetailsPromises.set(index, this._asyncDetailsCallback(index));
333 return /** @type {!Promise<?{detail: string, description: string}>} */ (this ._asyncDetailsPromises.get(index)); 314 return /** @type {!Promise<?{detail: string, description: string}>} */ (this ._asyncDetailsPromises.get(index));
334 } 315 }
(...skipping 16 matching lines...) Expand all
351 _selectItem(index) { 332 _selectItem(index) {
352 if (this._selectedElement) { 333 if (this._selectedElement) {
353 this._selectedElement.classList.remove('selected'); 334 this._selectedElement.classList.remove('selected');
354 this._selectedElement.classList.remove('force-white-icons'); 335 this._selectedElement.classList.remove('force-white-icons');
355 } 336 }
356 337
357 this._selectedIndex = index; 338 this._selectedIndex = index;
358 if (index < 0) 339 if (index < 0)
359 return; 340 return;
360 341
361 this._selectedElement = this.itemElement(index); 342 this._selectedElement = this._viewport.elementAtIndex(index);
362 this._selectedElement.classList.add('selected'); 343 this._selectedElement.classList.add('selected');
363 this._selectedElement.classList.add('force-white-icons'); 344 this._selectedElement.classList.add('force-white-icons');
364 this._detailsPopup.classList.add('hidden'); 345 this._detailsPopup.classList.add('hidden');
365 var elem = this._selectedElement; 346 var elem = this._selectedElement;
366 this._asyncDetails(index).then(showDetails.bind(this), function() {}); 347 this._asyncDetails(index).then(showDetails.bind(this), function() {});
367 348
368 this._viewport.scrollItemIntoView(index); 349 this._viewport.scrollItemAtIndexIntoView(index);
369 this._applySuggestion(true); 350 this._applySuggestion(true);
370 351
371 /** 352 /**
372 * @param {?{detail: string, description: string}} details 353 * @param {?{detail: string, description: string}} details
373 * @this {UI.SuggestBox} 354 * @this {UI.SuggestBox}
374 */ 355 */
375 function showDetails(details) { 356 function showDetails(details) {
376 if (elem === this._selectedElement) 357 if (elem === this._selectedElement)
377 this._showDetailsPopup(details); 358 this._showDetailsPopup(details);
378 } 359 }
(...skipping 12 matching lines...) Expand all
391 if (completions.length > 1) 372 if (completions.length > 1)
392 return true; 373 return true;
393 374
394 if (!completions[0].title.startsWith(userEnteredText)) 375 if (!completions[0].title.startsWith(userEnteredText))
395 return true; 376 return true;
396 377
397 // Do not show a single suggestion if it is the same as user-entered query, even if allowed to show single-item suggest boxes. 378 // Do not show a single suggestion if it is the same as user-entered query, even if allowed to show single-item suggest boxes.
398 return canShowForSingleItem && completions[0].title !== userEnteredText; 379 return canShowForSingleItem && completions[0].title !== userEnteredText;
399 } 380 }
400 381
401 _ensureRowCountPerViewport() {
402 if (this._rowCountPerViewport)
403 return;
404 if (!this._items.length)
405 return;
406
407 this._rowCountPerViewport = Math.floor(this._element.getBoundingClientRect() .height / this._rowHeight);
408 }
409
410 /** 382 /**
411 * @param {!AnchorBox} anchorBox 383 * @param {!AnchorBox} anchorBox
412 * @param {!UI.SuggestBox.Suggestions} completions 384 * @param {!UI.SuggestBox.Suggestions} completions
413 * @param {boolean} selectHighestPriority 385 * @param {boolean} selectHighestPriority
414 * @param {boolean} canShowForSingleItem 386 * @param {boolean} canShowForSingleItem
415 * @param {string} userEnteredText 387 * @param {string} userEnteredText
416 * @param {function(number): !Promise<{detail:string, description:string}>=} a syncDetails 388 * @param {function(number): !Promise<{detail:string, description:string}>=} a syncDetails
417 */ 389 */
418 updateSuggestions( 390 updateSuggestions(
419 anchorBox, 391 anchorBox,
420 completions, 392 completions,
421 selectHighestPriority, 393 selectHighestPriority,
422 canShowForSingleItem, 394 canShowForSingleItem,
423 userEnteredText, 395 userEnteredText,
424 asyncDetails) { 396 asyncDetails) {
425 delete this._onlyCompletion; 397 delete this._onlyCompletion;
426 if (this._canShowBox(completions, canShowForSingleItem, userEnteredText)) { 398 if (this._canShowBox(completions, canShowForSingleItem, userEnteredText)) {
427 this._updateItems(completions, userEnteredText, asyncDetails); 399 this._asyncDetailsPromises.clear();
400 this._asyncDetailsCallback = asyncDetails;
401 delete this._selectedElement;
402 this._userEnteredText = userEnteredText;
428 this._show(); 403 this._show();
429 this._updateBoxPosition(anchorBox); 404 this._updateBoxPosition(anchorBox, completions.length);
405 this._viewport.setFixedHeight(this._rowHeight);
406 this._viewport.replaceAllItems(completions);
430 this._updateWidth(); 407 this._updateWidth();
431 this._viewport.refresh();
432 var highestPriorityItem = -1; 408 var highestPriorityItem = -1;
433 if (selectHighestPriority) { 409 if (selectHighestPriority) {
434 var highestPriority = -Infinity; 410 var highestPriority = -Infinity;
435 for (var i = 0; i < completions.length; i++) { 411 for (var i = 0; i < completions.length; i++) {
436 var priority = completions[i].priority || 0; 412 var priority = completions[i].priority || 0;
437 if (highestPriority < priority) { 413 if (highestPriority < priority) {
438 highestPriority = priority; 414 highestPriority = priority;
439 highestPriorityItem = i; 415 highestPriorityItem = i;
440 } 416 }
441 } 417 }
442 } 418 }
443 this._selectItem(highestPriorityItem); 419 this._selectItem(highestPriorityItem);
444 delete this._rowCountPerViewport;
445 } else { 420 } else {
446 if (completions.length === 1) { 421 if (completions.length === 1) {
447 this._onlyCompletion = completions[0].title; 422 this._onlyCompletion = completions[0].title;
448 this._applySuggestion(true); 423 this._applySuggestion(true);
449 } 424 }
450 this.hide(); 425 this.hide();
451 } 426 }
452 } 427 }
453 428
454 /** 429 /**
(...skipping 27 matching lines...) Expand all
482 * @return {boolean} 457 * @return {boolean}
483 */ 458 */
484 downKeyPressed() { 459 downKeyPressed() {
485 return this._selectClosest(1, true); 460 return this._selectClosest(1, true);
486 } 461 }
487 462
488 /** 463 /**
489 * @return {boolean} 464 * @return {boolean}
490 */ 465 */
491 pageUpKeyPressed() { 466 pageUpKeyPressed() {
492 this._ensureRowCountPerViewport(); 467 var rowCount = Math.floor(this._viewport.element.offsetHeight / this._rowHei ght);
493 return this._selectClosest(-this._rowCountPerViewport, false); 468 return this._selectClosest(-rowCount, false);
494 } 469 }
495 470
496 /** 471 /**
497 * @return {boolean} 472 * @return {boolean}
498 */ 473 */
499 pageDownKeyPressed() { 474 pageDownKeyPressed() {
500 this._ensureRowCountPerViewport(); 475 var rowCount = Math.floor(this._viewport.element.offsetHeight / this._rowHei ght);
501 return this._selectClosest(this._rowCountPerViewport, false); 476 return this._selectClosest(rowCount, false);
502 } 477 }
503 478
504 /** 479 /**
505 * @return {boolean} 480 * @return {boolean}
506 */ 481 */
507 enterKeyPressed() { 482 enterKeyPressed() {
508 if (!this._userInteracted && this._captureEnter) 483 if (!this._userInteracted && this._captureEnter)
509 return false; 484 return false;
510 485
511 var hasSelectedItem = !!this._selectedElement || this._onlyCompletion; 486 var hasSelectedItem = !!this._selectedElement || this._onlyCompletion;
512 this.acceptSuggestion(); 487 this.acceptSuggestion();
513 488
514 // Report the event as non-handled if there is no selected item, 489 // Report the event as non-handled if there is no selected item,
515 // to commit the input or handle it otherwise. 490 // to commit the input or handle it otherwise.
516 return hasSelectedItem; 491 return hasSelectedItem;
517 } 492 }
518
519 /**
520 * @override
521 * @param {number} index
522 * @return {number}
523 */
524 fastItemHeight(index) {
525 return this._rowHeight;
526 }
527
528 /**
529 * @override
530 * @return {number}
531 */
532 itemCount() {
533 return this._items.length;
534 }
535
536 /**
537 * @override
538 * @param {number} index
539 * @return {?Element}
540 */
541 itemElement(index) {
542 if (!this._elementList[index]) {
543 this._elementList[index] = this._createItemElement(
544 this._userEnteredText, this._items[index].title, this._items[index].su btitle, this._items[index].iconType,
545 this._items[index].isSecondary);
546 }
547 return this._elementList[index];
548 }
549 }; 493 };
550 494
551 /** 495 /**
552 * @typedef {!Array.<{title: string, subtitle: (string|undefined), iconType: (st ring|undefined), priority: (number|undefined), isSecondary: (boolean|undefined)} >} 496 * @typedef {!{title: string, subtitle: (string|undefined), iconType: (string|un defined), priority: (number|undefined), isSecondary: (boolean|undefined)}}
497 */
498 UI.SuggestBox.Suggestion;
499
500 /**
501 * @typedef {!Array<!UI.SuggestBox.Suggestion>}
553 */ 502 */
554 UI.SuggestBox.Suggestions; 503 UI.SuggestBox.Suggestions;
555 504
556 /** 505 /**
557 * @unrestricted 506 * @unrestricted
558 */ 507 */
559 UI.SuggestBox.Overlay = class { 508 UI.SuggestBox.Overlay = class {
560 /** 509 /**
561 * // FIXME: make SuggestBox work for multiple documents. 510 * // FIXME: make SuggestBox work for multiple documents.
562 * @suppressGlobalPropertiesCheck 511 * @suppressGlobalPropertiesCheck
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 this.element.style.left = containerBox.x + 'px'; 558 this.element.style.left = containerBox.x + 'px';
610 this.element.style.top = containerBox.y + 'px'; 559 this.element.style.top = containerBox.y + 'px';
611 this.element.style.height = containerBox.height + 'px'; 560 this.element.style.height = containerBox.height + 'px';
612 this.element.style.width = containerBox.width + 'px'; 561 this.element.style.width = containerBox.width + 'px';
613 } 562 }
614 563
615 dispose() { 564 dispose() {
616 this.element.remove(); 565 this.element.remove();
617 } 566 }
618 }; 567 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698