| OLD | NEW |
| 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 * @param {number=} maxItemsHeight | 55 * @param {number=} maxItemsHeight |
| 56 * @param {boolean=} captureEnter | 56 * @param {boolean=} captureEnter |
| 57 */ | 57 */ |
| 58 constructor(suggestBoxDelegate, maxItemsHeight, captureEnter) { | 58 constructor(suggestBoxDelegate, maxItemsHeight, captureEnter) { |
| 59 this._suggestBoxDelegate = suggestBoxDelegate; | 59 this._suggestBoxDelegate = suggestBoxDelegate; |
| 60 this._maxItemsHeight = maxItemsHeight; | 60 this._maxItemsHeight = maxItemsHeight; |
| 61 this._maybeHideBound = this._maybeHide.bind(this); | 61 this._maybeHideBound = this._maybeHide.bind(this); |
| 62 this._container = createElementWithClass('div', 'suggest-box-container'); | 62 this._container = createElementWithClass('div', 'suggest-box-container'); |
| 63 this._rowHeight = 17; | 63 this._rowHeight = 17; |
| 64 /** @type {!UI.ListControl<!UI.SuggestBox.Suggestion>} */ | 64 /** @type {!UI.ListControl<!UI.SuggestBox.Suggestion>} */ |
| 65 this._list = new UI.ListControl(this, UI.ListMode.ViewportFixedItems); | 65 this._list = new UI.ListControl(this, UI.ListMode.SameHeightItems); |
| 66 this._element = this._list.element; | 66 this._element = this._list.element; |
| 67 this._element.classList.add('suggest-box'); | 67 this._element.classList.add('suggest-box'); |
| 68 this._container.appendChild(this._element); | 68 this._container.appendChild(this._element); |
| 69 this._element.addEventListener('mousedown', this._onBoxMouseDown.bind(this),
true); | 69 this._element.addEventListener('mousedown', this._onBoxMouseDown.bind(this),
true); |
| 70 this._detailsPopup = this._container.createChild('div', 'suggest-box details
-popup monospace'); | 70 this._detailsPopup = this._container.createChild('div', 'suggest-box details
-popup monospace'); |
| 71 this._detailsPopup.classList.add('hidden'); | 71 this._detailsPopup.classList.add('hidden'); |
| 72 this._asyncDetailsCallback = null; | 72 this._asyncDetailsCallback = null; |
| 73 /** @type {!Map<!UI.SuggestBox.Suggestion, !Promise<{detail: string, descrip
tion: string}>>} */ | 73 /** @type {!Map<!UI.SuggestBox.Suggestion, !Promise<{detail: string, descrip
tion: string}>>} */ |
| 74 this._asyncDetailsPromises = new Map(); | 74 this._asyncDetailsPromises = new Map(); |
| 75 this._userInteracted = false; | 75 this._userInteracted = false; |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 if (index > 0) | 252 if (index > 0) |
| 253 titleElement.createChild('span').textContent = displayText.substring(0, in
dex); | 253 titleElement.createChild('span').textContent = displayText.substring(0, in
dex); |
| 254 if (index > -1) | 254 if (index > -1) |
| 255 titleElement.createChild('span', 'query').textContent = displayText.substr
ing(index, index + query.length); | 255 titleElement.createChild('span', 'query').textContent = displayText.substr
ing(index, index + query.length); |
| 256 titleElement.createChild('span').textContent = displayText.substring(index >
-1 ? index + query.length : 0); | 256 titleElement.createChild('span').textContent = displayText.substring(index >
-1 ? index + query.length : 0); |
| 257 titleElement.createChild('span', 'spacer'); | 257 titleElement.createChild('span', 'spacer'); |
| 258 if (item.subtitle) { | 258 if (item.subtitle) { |
| 259 var subtitleElement = element.createChild('span', 'suggestion-subtitle'); | 259 var subtitleElement = element.createChild('span', 'suggestion-subtitle'); |
| 260 subtitleElement.textContent = item.subtitle.trimEnd(15); | 260 subtitleElement.textContent = item.subtitle.trimEnd(15); |
| 261 } | 261 } |
| 262 element.addEventListener('mousedown', this._onItemMouseDown.bind(this), fals
e); | |
| 263 return element; | 262 return element; |
| 264 } | 263 } |
| 265 | 264 |
| 266 /** | 265 /** |
| 267 * @override | 266 * @override |
| 268 * @param {!UI.SuggestBox.Suggestion} item | 267 * @param {!UI.SuggestBox.Suggestion} item |
| 269 * @return {number} | 268 * @return {number} |
| 270 */ | 269 */ |
| 271 heightForItem(item) { | 270 heightForItem(item) { |
| 272 return this._rowHeight; | 271 return this._rowHeight; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 297 return; | 296 return; |
| 298 this._detailsPopup.classList.add('hidden'); | 297 this._detailsPopup.classList.add('hidden'); |
| 299 this._asyncDetails(to).then(details => { | 298 this._asyncDetails(to).then(details => { |
| 300 if (this._list.selectedItem() === to) | 299 if (this._list.selectedItem() === to) |
| 301 this._showDetailsPopup(details); | 300 this._showDetailsPopup(details); |
| 302 }); | 301 }); |
| 303 this._applySuggestion(true); | 302 this._applySuggestion(true); |
| 304 } | 303 } |
| 305 | 304 |
| 306 /** | 305 /** |
| 306 * @override |
| 307 * @param {!UI.SuggestBox.Suggestion} item |
| 308 * @param {!Element} element |
| 307 * @param {!Event} event | 309 * @param {!Event} event |
| 308 */ | 310 */ |
| 309 _onItemMouseDown(event) { | 311 itemElementClicked(item, element, event) { |
| 310 if (!this._list.onClick(event)) | 312 this._list.selectItem(item); |
| 311 return; | |
| 312 this._userInteracted = true; | 313 this._userInteracted = true; |
| 314 event.consume(true); |
| 313 this.acceptSuggestion(); | 315 this.acceptSuggestion(); |
| 314 event.consume(true); | |
| 315 } | 316 } |
| 316 | 317 |
| 317 /** | 318 /** |
| 318 * @param {!UI.SuggestBox.Suggestion} item | 319 * @param {!UI.SuggestBox.Suggestion} item |
| 319 * @return {!Promise<?{detail: string, description: string}>} | 320 * @return {!Promise<?{detail: string, description: string}>} |
| 320 */ | 321 */ |
| 321 _asyncDetails(item) { | 322 _asyncDetails(item) { |
| 322 if (!this._asyncDetailsCallback) | 323 if (!this._asyncDetailsCallback) |
| 323 return Promise.resolve(/** @type {?{description: string, detail: string}}
*/ (null)); | 324 return Promise.resolve(/** @type {?{description: string, detail: string}}
*/ (null)); |
| 324 if (!this._asyncDetailsPromises.has(item)) | 325 if (!this._asyncDetailsPromises.has(item)) |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 this._asyncDetailsPromises.clear(); | 379 this._asyncDetailsPromises.clear(); |
| 379 if (asyncDetails) | 380 if (asyncDetails) |
| 380 this._asyncDetailsCallback = item => asyncDetails(completions.indexOf(it
em)); | 381 this._asyncDetailsCallback = item => asyncDetails(completions.indexOf(it
em)); |
| 381 else | 382 else |
| 382 this._asyncDetailsCallback = null; | 383 this._asyncDetailsCallback = null; |
| 383 this._userEnteredText = userEnteredText; | 384 this._userEnteredText = userEnteredText; |
| 384 | 385 |
| 385 this._show(); | 386 this._show(); |
| 386 this._updateBoxPosition(anchorBox, completions.length); | 387 this._updateBoxPosition(anchorBox, completions.length); |
| 387 this._updateWidth(completions); | 388 this._updateWidth(completions); |
| 388 this._list.fixedHeightChanged(); | 389 this._list.invalidateSameHeight(); |
| 389 this._list.replaceAllItems(completions); | 390 this._list.replaceAllItems(completions); |
| 390 | 391 |
| 391 var highestPriorityItem = -1; | |
| 392 if (selectHighestPriority) { | 392 if (selectHighestPriority) { |
| 393 var highestPriority = -Infinity; | 393 var highestPriorityItem = completions[0]; |
| 394 var highestPriority = completions[0].priority || 0; |
| 394 for (var i = 0; i < completions.length; i++) { | 395 for (var i = 0; i < completions.length; i++) { |
| 395 var priority = completions[i].priority || 0; | 396 var priority = completions[i].priority || 0; |
| 396 if (highestPriority < priority) { | 397 if (highestPriority < priority) { |
| 397 highestPriority = priority; | 398 highestPriority = priority; |
| 398 highestPriorityItem = i; | 399 highestPriorityItem = completions[i]; |
| 399 } | 400 } |
| 400 } | 401 } |
| 402 this._list.selectItem(highestPriorityItem, true); |
| 401 } | 403 } |
| 402 this._list.selectItemAtIndex(highestPriorityItem, true); | |
| 403 } else { | 404 } else { |
| 404 if (completions.length === 1) { | 405 if (completions.length === 1) { |
| 405 this._onlyCompletion = completions[0].title; | 406 this._onlyCompletion = completions[0].title; |
| 406 this._applySuggestion(true); | 407 this._applySuggestion(true); |
| 407 } | 408 } |
| 408 this.hide(); | 409 this.hide(); |
| 409 } | 410 } |
| 410 } | 411 } |
| 411 | 412 |
| 412 /** | 413 /** |
| 413 * @param {!KeyboardEvent} event | 414 * @param {!KeyboardEvent} event |
| 414 * @return {boolean} | 415 * @return {boolean} |
| 415 */ | 416 */ |
| 416 keyPressed(event) { | 417 keyPressed(event) { |
| 417 if (this._list.onKeyDown(event)) { | 418 var selected = false; |
| 419 switch (event.key) { |
| 420 case 'Enter': |
| 421 return this.enterKeyPressed(); |
| 422 case 'ArrowUp': |
| 423 selected = this._list.selectPreviousItem(true, false); |
| 424 break; |
| 425 case 'ArrowDown': |
| 426 selected = this._list.selectNextItem(true, false); |
| 427 break; |
| 428 case 'PageUp': |
| 429 selected = this._list.selectItemPreviousPage(false); |
| 430 break; |
| 431 case 'PageDown': |
| 432 selected = this._list.selectItemNextPage(false); |
| 433 break; |
| 434 default: |
| 435 return false; |
| 436 } |
| 437 if (selected) { |
| 418 this._userInteracted = true; | 438 this._userInteracted = true; |
| 419 return true; | 439 return true; |
| 420 } | 440 } |
| 421 if (event.key === 'Enter') | |
| 422 return this.enterKeyPressed(); | |
| 423 return false; | 441 return false; |
| 424 } | 442 } |
| 425 | 443 |
| 426 /** | 444 /** |
| 427 * @return {boolean} | 445 * @return {boolean} |
| 428 */ | 446 */ |
| 429 enterKeyPressed() { | 447 enterKeyPressed() { |
| 430 if (!this._userInteracted && this._captureEnter) | 448 if (!this._userInteracted && this._captureEnter) |
| 431 return false; | 449 return false; |
| 432 | 450 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 this.element.style.left = containerBox.x + 'px'; | 523 this.element.style.left = containerBox.x + 'px'; |
| 506 this.element.style.top = containerBox.y + 'px'; | 524 this.element.style.top = containerBox.y + 'px'; |
| 507 this.element.style.height = containerBox.height + 'px'; | 525 this.element.style.height = containerBox.height + 'px'; |
| 508 this.element.style.width = containerBox.width + 'px'; | 526 this.element.style.width = containerBox.width + 'px'; |
| 509 } | 527 } |
| 510 | 528 |
| 511 dispose() { | 529 dispose() { |
| 512 this.element.remove(); | 530 this.element.remove(); |
| 513 } | 531 } |
| 514 }; | 532 }; |
| OLD | NEW |