Chromium Code Reviews| 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 * acceptSuggestion will be always called after call to applySuggestion with isIntermediateSuggestion being equal to false. | 46 * acceptSuggestion will be always called after call to applySuggestion with isIntermediateSuggestion being equal to false. |
| 47 */ | 47 */ |
| 48 acceptSuggestion: function() { }, | 48 acceptSuggestion: function() { }, |
| 49 } | 49 } |
| 50 | 50 |
| 51 /** | 51 /** |
| 52 * @constructor | 52 * @constructor |
| 53 * @param {!WebInspector.SuggestBoxDelegate} suggestBoxDelegate | 53 * @param {!WebInspector.SuggestBoxDelegate} suggestBoxDelegate |
| 54 * @param {number=} maxItemsHeight | 54 * @param {number=} maxItemsHeight |
| 55 */ | 55 */ |
| 56 WebInspector.SuggestBox = function(suggestBoxDelegate, maxItemsHeight) | 56 WebInspector.SuggestBox = function(suggestBoxDelegate, maxItemsHeight) |
|
pfeldman
2015/08/13 21:15:47
This is worth a separate patch.
wes
2015/08/14 01:25:50
Adding the details popover flow? Alright, I'll not
| |
| 57 { | 57 { |
| 58 this._suggestBoxDelegate = suggestBoxDelegate; | 58 this._suggestBoxDelegate = suggestBoxDelegate; |
| 59 this._length = 0; | 59 this._length = 0; |
| 60 this._selectedIndex = -1; | 60 this._selectedIndex = -1; |
| 61 this._selectedElement = null; | 61 this._selectedElement = null; |
| 62 this._maxItemsHeight = maxItemsHeight; | 62 this._maxItemsHeight = maxItemsHeight; |
| 63 this._maybeHideBound = this._maybeHide.bind(this); | 63 this._maybeHideBound = this._maybeHide.bind(this); |
| 64 this._element = createElementWithClass("div", "suggest-box"); | 64 this._container = createElementWithClass("div", "suggest-box-container"); |
| 65 this._element = this._container.createChild("div", "suggest-box"); | |
| 65 this._element.addEventListener("mousedown", this._onBoxMouseDown.bind(this), true); | 66 this._element.addEventListener("mousedown", this._onBoxMouseDown.bind(this), true); |
| 67 this._detailsPopup = this._container.createChild("div", "details-popup monos pace"); | |
| 68 this._detailsPopup.style.visibility = 'hidden'; | |
| 66 } | 69 } |
| 67 | 70 |
| 68 WebInspector.SuggestBox.prototype = { | 71 WebInspector.SuggestBox.prototype = { |
| 69 /** | 72 /** |
| 70 * @return {boolean} | 73 * @return {boolean} |
| 71 */ | 74 */ |
| 72 visible: function() | 75 visible: function() |
| 73 { | 76 { |
| 74 return !!this._element.parentElement; | 77 return !!this._container.parentElement; |
| 75 }, | 78 }, |
| 76 | 79 |
| 77 /** | 80 /** |
| 78 * @param {!AnchorBox} anchorBox | 81 * @param {!AnchorBox} anchorBox |
| 79 */ | 82 */ |
| 80 setPosition: function(anchorBox) | 83 setPosition: function(anchorBox) |
| 81 { | 84 { |
| 82 this._updateBoxPosition(anchorBox); | 85 this._updateBoxPosition(anchorBox); |
| 83 }, | 86 }, |
| 84 | 87 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 * // FIXME: make SuggestBox work for multiple documents. | 138 * // FIXME: make SuggestBox work for multiple documents. |
| 136 * @suppressGlobalPropertiesCheck | 139 * @suppressGlobalPropertiesCheck |
| 137 */ | 140 */ |
| 138 _show: function() | 141 _show: function() |
| 139 { | 142 { |
| 140 if (this.visible()) | 143 if (this.visible()) |
| 141 return; | 144 return; |
| 142 this._bodyElement = document.body; | 145 this._bodyElement = document.body; |
| 143 this._bodyElement.addEventListener("mousedown", this._maybeHideBound, tr ue); | 146 this._bodyElement.addEventListener("mousedown", this._maybeHideBound, tr ue); |
| 144 this._overlay = new WebInspector.SuggestBox.Overlay(); | 147 this._overlay = new WebInspector.SuggestBox.Overlay(); |
| 145 this._overlay.setContentElement(this._element); | 148 this._overlay.setContentElement(this._container); |
| 146 }, | 149 }, |
| 147 | 150 |
| 148 hide: function() | 151 hide: function() |
| 149 { | 152 { |
| 150 if (!this.visible()) | 153 if (!this.visible()) |
| 151 return; | 154 return; |
| 152 | 155 |
| 153 this._bodyElement.removeEventListener("mousedown", this._maybeHideBound, true); | 156 this._bodyElement.removeEventListener("mousedown", this._maybeHideBound, true); |
| 154 delete this._bodyElement; | 157 delete this._bodyElement; |
| 155 this._element.remove(); | 158 this._container.remove(); |
| 156 this._overlay.dispose(); | 159 this._overlay.dispose(); |
| 157 delete this._overlay; | 160 delete this._overlay; |
| 158 delete this._selectedElement; | 161 delete this._selectedElement; |
| 159 this._selectedIndex = -1; | 162 this._selectedIndex = -1; |
| 160 delete this._lastAnchorBox; | 163 delete this._lastAnchorBox; |
| 161 }, | 164 }, |
| 162 | 165 |
| 163 removeFromElement: function() | 166 removeFromElement: function() |
| 164 { | 167 { |
| 165 this.hide(); | 168 this.hide(); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 227 _onItemMouseDown: function(event) | 230 _onItemMouseDown: function(event) |
| 228 { | 231 { |
| 229 this._selectedElement = event.currentTarget; | 232 this._selectedElement = event.currentTarget; |
| 230 this.acceptSuggestion(); | 233 this.acceptSuggestion(); |
| 231 event.consume(true); | 234 event.consume(true); |
| 232 }, | 235 }, |
| 233 | 236 |
| 234 /** | 237 /** |
| 235 * @param {string} prefix | 238 * @param {string} prefix |
| 236 * @param {string} text | 239 * @param {string} text |
| 240 * @param {?Function<!Promise<{detail:string, description:string}>>} asyncDe tail | |
| 237 */ | 241 */ |
| 238 _createItemElement: function(prefix, text) | 242 _createItemElement: function(prefix, text, asyncDetail) |
| 239 { | 243 { |
| 240 var element = createElementWithClass("div", "suggest-box-content-item so urce-code"); | 244 var element = createElementWithClass("div", "suggest-box-content-item so urce-code"); |
| 241 element.tabIndex = -1; | 245 element.tabIndex = -1; |
| 242 if (prefix && prefix.length && !text.indexOf(prefix)) { | 246 if (prefix && prefix.length && !text.indexOf(prefix)) { |
| 243 element.createChild("span", "prefix").textContent = prefix; | 247 element.createChild("span", "prefix").textContent = prefix; |
| 244 element.createChild("span", "suffix").textContent = text.substring(p refix.length); | 248 element.createChild("span", "suffix").textContent = text.substring(p refix.length); |
| 245 } else { | 249 } else { |
| 246 element.createChild("span", "suffix").textContent = text; | 250 element.createChild("span", "suffix").textContent = text; |
| 247 } | 251 } |
| 248 element.createChild("span", "spacer"); | 252 element.createChild("span", "spacer"); |
| 253 var prom; | |
| 254 element.details = function() { | |
| 255 if (!prom) { | |
| 256 if (!asyncDetail) { | |
| 257 prom = Promise.reject().then(function(){},function(){}); | |
| 258 } else { | |
| 259 prom = asyncDetail(); | |
| 260 } | |
| 261 } | |
| 262 return prom; | |
| 263 }; | |
| 249 element.addEventListener("mousedown", this._onItemMouseDown.bind(this), false); | 264 element.addEventListener("mousedown", this._onItemMouseDown.bind(this), false); |
| 250 return element; | 265 return element; |
| 251 }, | 266 }, |
| 252 | 267 |
| 253 /** | 268 /** |
| 254 * @param {!Array.<string>} items | 269 * @param {!Array.<string>} items |
| 255 * @param {string} userEnteredText | 270 * @param {string} userEnteredText |
| 271 * @param {!Array<!Function<!Promise<{detail:string, description:string}>>>} asyncDetails | |
| 256 */ | 272 */ |
| 257 _updateItems: function(items, userEnteredText) | 273 _updateItems: function(items, userEnteredText, asyncDetails) |
| 258 { | 274 { |
| 259 this._length = items.length; | 275 this._length = items.length; |
| 260 this._element.removeChildren(); | 276 this._element.removeChildren(); |
| 261 delete this._selectedElement; | 277 delete this._selectedElement; |
| 262 | 278 |
| 263 for (var i = 0; i < items.length; ++i) { | 279 for (var i = 0; i < items.length; ++i) { |
| 264 var item = items[i]; | 280 var item = items[i]; |
| 265 var currentItemElement = this._createItemElement(userEnteredText, it em); | 281 if (!item) continue; |
| 282 var currentItemElement = this._createItemElement(userEnteredText, it em, asyncDetails[i]); | |
| 266 this._element.appendChild(currentItemElement); | 283 this._element.appendChild(currentItemElement); |
| 267 } | 284 } |
| 268 }, | 285 }, |
| 269 | 286 |
| 287 _hideDetailsPopup: function() | |
| 288 { | |
| 289 this._detailsPopup.style.visibility = 'hidden'; | |
| 290 }, | |
| 291 | |
| 292 /** | |
| 293 * @param {{detail: string, description: string}=} details | |
| 294 */ | |
| 295 _showDetailsPopup: function(details) | |
| 296 { | |
| 297 while (this._detailsPopup.firstChild) { | |
| 298 this._detailsPopup.removeChild(this._detailsPopup.firstChild); | |
| 299 } | |
| 300 if (!details) { | |
| 301 return; | |
| 302 } | |
| 303 this._detailsPopup.createChild('section', 'detail').createTextChild(deta ils.detail); | |
| 304 this._detailsPopup.createChild('section', 'description').createTextChild (details.description); | |
| 305 this._detailsPopup.style.visibility = ''; | |
| 306 //WebInspector.runCSSAnimationOnce(this._detailsPopup, 'details-fade-in' ); //TODO: Causes assertion failures | |
| 307 }, | |
| 308 | |
| 270 /** | 309 /** |
| 271 * @param {number} index | 310 * @param {number} index |
| 272 * @param {boolean} scrollIntoView | 311 * @param {boolean} scrollIntoView |
| 273 */ | 312 */ |
| 274 _selectItem: function(index, scrollIntoView) | 313 _selectItem: function(index, scrollIntoView) |
| 275 { | 314 { |
| 276 if (this._selectedElement) | 315 if (this._selectedElement) |
| 277 this._selectedElement.classList.remove("selected"); | 316 this._selectedElement.classList.remove("selected"); |
| 278 | 317 |
| 279 this._selectedIndex = index; | 318 this._selectedIndex = index; |
| 280 if (index < 0) | 319 if (index < 0) |
| 281 return; | 320 return; |
| 282 | 321 |
| 283 this._selectedElement = this._element.children[index]; | 322 this._selectedElement = this._element.children[index]; |
| 284 this._selectedElement.classList.add("selected"); | 323 this._selectedElement.classList.add("selected"); |
| 324 this._hideDetailsPopup(); | |
| 325 var elem = this._selectedElement; | |
| 326 this._selectedElement.details().then((function(details){ | |
| 327 if (elem === this._selectedElement) { | |
| 328 this._showDetailsPopup(details); | |
| 329 } | |
| 330 }).bind(this), function(){}); | |
| 285 | 331 |
| 286 if (scrollIntoView) | 332 if (scrollIntoView) |
| 287 this._selectedElement.scrollIntoViewIfNeeded(false); | 333 this._selectedElement.scrollIntoViewIfNeeded(false); |
| 288 }, | 334 }, |
| 289 | 335 |
| 290 /** | 336 /** |
| 291 * @param {!Array.<string>} completions | 337 * @param {!Array.<string>} completions |
| 292 * @param {boolean} canShowForSingleItem | 338 * @param {boolean} canShowForSingleItem |
| 293 * @param {string} userEnteredText | 339 * @param {string} userEnteredText |
| 294 */ | 340 */ |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 313 | 359 |
| 314 this._rowCountPerViewport = Math.floor(this._element.offsetHeight / this ._element.firstChild.offsetHeight); | 360 this._rowCountPerViewport = Math.floor(this._element.offsetHeight / this ._element.firstChild.offsetHeight); |
| 315 }, | 361 }, |
| 316 | 362 |
| 317 /** | 363 /** |
| 318 * @param {!AnchorBox} anchorBox | 364 * @param {!AnchorBox} anchorBox |
| 319 * @param {!Array.<string>} completions | 365 * @param {!Array.<string>} completions |
| 320 * @param {number} selectedIndex | 366 * @param {number} selectedIndex |
| 321 * @param {boolean} canShowForSingleItem | 367 * @param {boolean} canShowForSingleItem |
| 322 * @param {string} userEnteredText | 368 * @param {string} userEnteredText |
| 369 * @param {?Array<!Function<!Promise<{detail:string, description:string}>>>= } asyncDetails | |
| 323 */ | 370 */ |
| 324 updateSuggestions: function(anchorBox, completions, selectedIndex, canShowFo rSingleItem, userEnteredText) | 371 updateSuggestions: function(anchorBox, completions, selectedIndex, canShowFo rSingleItem, userEnteredText, asyncDetails) |
| 325 { | 372 { |
| 326 if (this._canShowBox(completions, canShowForSingleItem, userEnteredText) ) { | 373 if (this._canShowBox(completions, canShowForSingleItem, userEnteredText) ) { |
| 327 this._updateItems(completions, userEnteredText); | 374 this._updateItems(completions, userEnteredText, asyncDetails || []); |
| 328 this._show(); | 375 this._show(); |
| 329 this._updateBoxPosition(anchorBox); | 376 this._updateBoxPosition(anchorBox); |
| 330 this._selectItem(selectedIndex, selectedIndex > 0); | 377 this._selectItem(selectedIndex, selectedIndex > 0); |
| 331 delete this._rowCountPerViewport; | 378 delete this._rowCountPerViewport; |
| 332 } else | 379 } else |
| 333 this.hide(); | 380 this.hide(); |
| 334 }, | 381 }, |
| 335 | 382 |
| 336 /** | 383 /** |
| 337 * @param {!KeyboardEvent} event | 384 * @param {!KeyboardEvent} event |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 this.element.style.top = containerBox.y + "px"; | 510 this.element.style.top = containerBox.y + "px"; |
| 464 this.element.style.height = containerBox.height + "px"; | 511 this.element.style.height = containerBox.height + "px"; |
| 465 this.element.style.width = containerBox.width + "px"; | 512 this.element.style.width = containerBox.width + "px"; |
| 466 }, | 513 }, |
| 467 | 514 |
| 468 dispose: function() | 515 dispose: function() |
| 469 { | 516 { |
| 470 this.element.remove(); | 517 this.element.remove(); |
| 471 } | 518 } |
| 472 } | 519 } |
| OLD | NEW |