| 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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); | 65 this._list = new UI.ListControl(this); |
| 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'); | |
| 71 this._detailsPopup.classList.add('hidden'); | |
| 72 this._asyncDetailsCallback = null; | |
| 73 /** @type {!Map<!UI.SuggestBox.Suggestion, !Promise<{detail: string, descrip
tion: string}>>} */ | |
| 74 this._asyncDetailsPromises = new Map(); | |
| 75 this._userInteracted = false; | 70 this._userInteracted = false; |
| 76 this._captureEnter = captureEnter; | 71 this._captureEnter = captureEnter; |
| 77 this._viewportWidth = '100vw'; | 72 this._viewportWidth = '100vw'; |
| 78 this._hasVerticalScroll = false; | 73 this._hasVerticalScroll = false; |
| 79 this._userEnteredText = ''; | 74 this._userEnteredText = ''; |
| 80 } | 75 } |
| 81 | 76 |
| 82 /** | 77 /** |
| 83 * @return {boolean} | 78 * @return {boolean} |
| 84 */ | 79 */ |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 * @param {?Element} fromElement | 283 * @param {?Element} fromElement |
| 289 * @param {?Element} toElement | 284 * @param {?Element} toElement |
| 290 */ | 285 */ |
| 291 selectedItemChanged(from, to, fromElement, toElement) { | 286 selectedItemChanged(from, to, fromElement, toElement) { |
| 292 if (fromElement) | 287 if (fromElement) |
| 293 fromElement.classList.remove('selected', 'force-white-icons'); | 288 fromElement.classList.remove('selected', 'force-white-icons'); |
| 294 if (toElement) | 289 if (toElement) |
| 295 toElement.classList.add('selected', 'force-white-icons'); | 290 toElement.classList.add('selected', 'force-white-icons'); |
| 296 if (!to) | 291 if (!to) |
| 297 return; | 292 return; |
| 298 this._detailsPopup.classList.add('hidden'); | |
| 299 this._asyncDetails(to).then(details => { | |
| 300 if (this._list.selectedItem() === to) | |
| 301 this._showDetailsPopup(details); | |
| 302 }); | |
| 303 this._applySuggestion(true); | 293 this._applySuggestion(true); |
| 304 } | 294 } |
| 305 | 295 |
| 306 /** | 296 /** |
| 307 * @param {!Event} event | 297 * @param {!Event} event |
| 308 */ | 298 */ |
| 309 _onItemMouseDown(event) { | 299 _onItemMouseDown(event) { |
| 310 if (!this._list.onClick(event)) | 300 if (!this._list.onClick(event)) |
| 311 return; | 301 return; |
| 312 this._userInteracted = true; | 302 this._userInteracted = true; |
| 313 this.acceptSuggestion(); | 303 this.acceptSuggestion(); |
| 314 event.consume(true); | 304 event.consume(true); |
| 315 } | 305 } |
| 316 | 306 |
| 317 /** | 307 /** |
| 318 * @param {!UI.SuggestBox.Suggestion} item | |
| 319 * @return {!Promise<?{detail: string, description: string}>} | |
| 320 */ | |
| 321 _asyncDetails(item) { | |
| 322 if (!this._asyncDetailsCallback) | |
| 323 return Promise.resolve(/** @type {?{description: string, detail: string}}
*/ (null)); | |
| 324 if (!this._asyncDetailsPromises.has(item)) | |
| 325 this._asyncDetailsPromises.set(item, this._asyncDetailsCallback(item)); | |
| 326 return /** @type {!Promise<?{detail: string, description: string}>} */ (this
._asyncDetailsPromises.get(item)); | |
| 327 } | |
| 328 | |
| 329 /** | |
| 330 * @param {?{detail: string, description: string}} details | |
| 331 */ | |
| 332 _showDetailsPopup(details) { | |
| 333 this._detailsPopup.removeChildren(); | |
| 334 if (!details) | |
| 335 return; | |
| 336 this._detailsPopup.createChild('section', 'detail').createTextChild(details.
detail); | |
| 337 this._detailsPopup.createChild('section', 'description').createTextChild(det
ails.description); | |
| 338 this._detailsPopup.classList.remove('hidden'); | |
| 339 } | |
| 340 | |
| 341 /** | |
| 342 * @param {!UI.SuggestBox.Suggestions} completions | 308 * @param {!UI.SuggestBox.Suggestions} completions |
| 343 * @param {boolean} canShowForSingleItem | 309 * @param {boolean} canShowForSingleItem |
| 344 * @param {string} userEnteredText | 310 * @param {string} userEnteredText |
| 345 * @return {boolean} | 311 * @return {boolean} |
| 346 */ | 312 */ |
| 347 _canShowBox(completions, canShowForSingleItem, userEnteredText) { | 313 _canShowBox(completions, canShowForSingleItem, userEnteredText) { |
| 348 if (!completions || !completions.length) | 314 if (!completions || !completions.length) |
| 349 return false; | 315 return false; |
| 350 | 316 |
| 351 if (completions.length > 1) | 317 if (completions.length > 1) |
| 352 return true; | 318 return true; |
| 353 | 319 |
| 354 if (!completions[0].title.startsWith(userEnteredText)) | 320 if (!completions[0].title.startsWith(userEnteredText)) |
| 355 return true; | 321 return true; |
| 356 | 322 |
| 357 // Do not show a single suggestion if it is the same as user-entered query,
even if allowed to show single-item suggest boxes. | 323 // Do not show a single suggestion if it is the same as user-entered query,
even if allowed to show single-item suggest boxes. |
| 358 return canShowForSingleItem && completions[0].title !== userEnteredText; | 324 return canShowForSingleItem && completions[0].title !== userEnteredText; |
| 359 } | 325 } |
| 360 | 326 |
| 361 /** | 327 /** |
| 362 * @param {!AnchorBox} anchorBox | 328 * @param {!AnchorBox} anchorBox |
| 363 * @param {!UI.SuggestBox.Suggestions} completions | 329 * @param {!UI.SuggestBox.Suggestions} completions |
| 364 * @param {boolean} selectHighestPriority | 330 * @param {boolean} selectHighestPriority |
| 365 * @param {boolean} canShowForSingleItem | 331 * @param {boolean} canShowForSingleItem |
| 366 * @param {string} userEnteredText | 332 * @param {string} userEnteredText |
| 367 * @param {function(number): !Promise<{detail:string, description:string}>=} a
syncDetails | |
| 368 */ | 333 */ |
| 369 updateSuggestions( | 334 updateSuggestions(anchorBox, completions, selectHighestPriority, canShowForSin
gleItem, userEnteredText) { |
| 370 anchorBox, | |
| 371 completions, | |
| 372 selectHighestPriority, | |
| 373 canShowForSingleItem, | |
| 374 userEnteredText, | |
| 375 asyncDetails) { | |
| 376 delete this._onlyCompletion; | 335 delete this._onlyCompletion; |
| 377 if (this._canShowBox(completions, canShowForSingleItem, userEnteredText)) { | 336 if (this._canShowBox(completions, canShowForSingleItem, userEnteredText)) { |
| 378 this._asyncDetailsPromises.clear(); | |
| 379 if (asyncDetails) | |
| 380 this._asyncDetailsCallback = item => asyncDetails(completions.indexOf(it
em)); | |
| 381 else | |
| 382 this._asyncDetailsCallback = null; | |
| 383 this._userEnteredText = userEnteredText; | 337 this._userEnteredText = userEnteredText; |
| 384 | 338 |
| 385 this._show(); | 339 this._show(); |
| 386 this._updateBoxPosition(anchorBox, completions.length); | 340 this._updateBoxPosition(anchorBox, completions.length); |
| 387 this._updateWidth(completions); | 341 this._updateWidth(completions); |
| 388 | 342 |
| 389 this._list.setHeightMode(UI.ListHeightMode.Fixed); | 343 this._list.setHeightMode(UI.ListHeightMode.Fixed); |
| 390 this._list.replaceAllItems(completions); | 344 this._list.replaceAllItems(completions); |
| 391 | 345 |
| 392 var highestPriorityItem = -1; | 346 var highestPriorityItem = -1; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 this.element.style.left = containerBox.x + 'px'; | 460 this.element.style.left = containerBox.x + 'px'; |
| 507 this.element.style.top = containerBox.y + 'px'; | 461 this.element.style.top = containerBox.y + 'px'; |
| 508 this.element.style.height = containerBox.height + 'px'; | 462 this.element.style.height = containerBox.height + 'px'; |
| 509 this.element.style.width = containerBox.width + 'px'; | 463 this.element.style.width = containerBox.width + 'px'; |
| 510 } | 464 } |
| 511 | 465 |
| 512 dispose() { | 466 dispose() { |
| 513 this.element.remove(); | 467 this.element.remove(); |
| 514 } | 468 } |
| 515 }; | 469 }; |
| OLD | NEW |