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 |