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

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

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month 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) 2009 Google Inc. All rights reserved. 2 * Copyright (C) 2009 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
11 * copyright notice, this list of conditions and the following disclaimer 11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the 12 * in the documentation and/or other materials provided with the
13 * distribution. 13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its 14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from 15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission. 16 * this software without specific prior written permission.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30
31 /** 30 /**
32 * @constructor 31 * @unrestricted
33 * @extends {WebInspector.Widget}
34 * @param {!WebInspector.PopoverHelper=} popoverHelper
35 */ 32 */
36 WebInspector.Popover = function(popoverHelper) 33 WebInspector.Popover = class extends WebInspector.Widget {
37 { 34 /**
38 WebInspector.Widget.call(this); 35 * @param {!WebInspector.PopoverHelper=} popoverHelper
36 */
37 constructor(popoverHelper) {
38 super();
39 this.markAsRoot(); 39 this.markAsRoot();
40 this.element.className = WebInspector.Popover._classNamePrefix; // Override 40 this.element.className = WebInspector.Popover._classNamePrefix; // Override
41 this._containerElement = createElementWithClass("div", "fill popover-contain er"); 41 this._containerElement = createElementWithClass('div', 'fill popover-contain er');
42 42
43 this._popupArrowElement = this.element.createChild("div", "arrow"); 43 this._popupArrowElement = this.element.createChild('div', 'arrow');
44 this._contentDiv = this.element.createChild("div", "content"); 44 this._contentDiv = this.element.createChild('div', 'content');
45 45
46 this._popoverHelper = popoverHelper; 46 this._popoverHelper = popoverHelper;
47 this._hideBound = this.hide.bind(this); 47 this._hideBound = this.hide.bind(this);
48 }
49
50 /**
51 * @param {!Element} element
52 * @param {!Element|!AnchorBox} anchor
53 * @param {?number=} preferredWidth
54 * @param {?number=} preferredHeight
55 * @param {?WebInspector.Popover.Orientation=} arrowDirection
56 */
57 showForAnchor(element, anchor, preferredWidth, preferredHeight, arrowDirection ) {
58 this._innerShow(null, element, anchor, preferredWidth, preferredHeight, arro wDirection);
59 }
60
61 /**
62 * @param {!WebInspector.Widget} view
63 * @param {!Element|!AnchorBox} anchor
64 * @param {?number=} preferredWidth
65 * @param {?number=} preferredHeight
66 */
67 showView(view, anchor, preferredWidth, preferredHeight) {
68 this._innerShow(view, view.element, anchor, preferredWidth, preferredHeight) ;
69 }
70
71 /**
72 * @param {?WebInspector.Widget} view
73 * @param {!Element} contentElement
74 * @param {!Element|!AnchorBox} anchor
75 * @param {?number=} preferredWidth
76 * @param {?number=} preferredHeight
77 * @param {?WebInspector.Popover.Orientation=} arrowDirection
78 */
79 _innerShow(view, contentElement, anchor, preferredWidth, preferredHeight, arro wDirection) {
80 if (this._disposed)
81 return;
82 this._contentElement = contentElement;
83
84 // This should not happen, but we hide previous popup to be on the safe side .
85 if (WebInspector.Popover._popover)
86 WebInspector.Popover._popover.hide();
87 WebInspector.Popover._popover = this;
88
89 var document = anchor instanceof Element ? anchor.ownerDocument : contentEle ment.ownerDocument;
90 var window = document.defaultView;
91
92 // Temporarily attach in order to measure preferred dimensions.
93 var preferredSize = view ? view.measurePreferredSize() : WebInspector.measur ePreferredSize(this._contentElement);
94 this._preferredWidth = preferredWidth || preferredSize.width;
95 this._preferredHeight = preferredHeight || preferredSize.height;
96
97 window.addEventListener('resize', this._hideBound, false);
98 document.body.appendChild(this._containerElement);
99 super.show(this._containerElement);
100
101 if (view)
102 view.show(this._contentDiv);
103 else
104 this._contentDiv.appendChild(this._contentElement);
105
106 this.positionElement(anchor, this._preferredWidth, this._preferredHeight, ar rowDirection);
107
108 if (this._popoverHelper) {
109 this._contentDiv.addEventListener(
110 'mousemove', this._popoverHelper._killHidePopoverTimer.bind(this._popo verHelper), true);
111 this.element.addEventListener('mouseout', this._popoverHelper._popoverMous eOut.bind(this._popoverHelper), true);
112 }
113 }
114
115 hide() {
116 this._containerElement.ownerDocument.defaultView.removeEventListener('resize ', this._hideBound, false);
117 this.detach();
118 this._containerElement.remove();
119 delete WebInspector.Popover._popover;
120 }
121
122 get disposed() {
123 return this._disposed;
124 }
125
126 dispose() {
127 if (this.isShowing())
128 this.hide();
129 this._disposed = true;
130 }
131
132 /**
133 * @param {boolean} canShrink
134 */
135 setCanShrink(canShrink) {
136 this._hasFixedHeight = !canShrink;
137 this._contentDiv.classList.toggle('fixed-height', this._hasFixedHeight);
138 }
139
140 /**
141 * @param {boolean} noPadding
142 */
143 setNoPadding(noPadding) {
144 this._hasNoPadding = noPadding;
145 this._contentDiv.classList.toggle('no-padding', this._hasNoPadding);
146 }
147
148 /**
149 * @param {!Element|!AnchorBox} anchorElement
150 * @param {number=} preferredWidth
151 * @param {number=} preferredHeight
152 * @param {?WebInspector.Popover.Orientation=} arrowDirection
153 */
154 positionElement(anchorElement, preferredWidth, preferredHeight, arrowDirection ) {
155 const borderWidth = this._hasNoPadding ? 0 : 8;
156 const scrollerWidth = this._hasFixedHeight ? 0 : 14;
157 const arrowHeight = this._hasNoPadding ? 8 : 15;
158 const arrowOffset = 10;
159 const borderRadius = 4;
160 const arrowRadius = 6;
161 preferredWidth = preferredWidth || this._preferredWidth;
162 preferredHeight = preferredHeight || this._preferredHeight;
163
164 // Skinny tooltips are not pretty, their arrow location is not nice.
165 preferredWidth = Math.max(preferredWidth, 50);
166 // Position relative to main DevTools element.
167 const container = WebInspector.Dialog.modalHostView().element;
168 const totalWidth = container.offsetWidth;
169 const totalHeight = container.offsetHeight;
170
171 var anchorBox = anchorElement instanceof AnchorBox ? anchorElement : anchorE lement.boxInWindow(window);
172 anchorBox = anchorBox.relativeToElement(container);
173 var newElementPosition = {x: 0, y: 0, width: preferredWidth + scrollerWidth, height: preferredHeight};
174
175 var verticalAlignment;
176 var roomAbove = anchorBox.y;
177 var roomBelow = totalHeight - anchorBox.y - anchorBox.height;
178 this._popupArrowElement.hidden = false;
179
180 if ((roomAbove > roomBelow) || (arrowDirection === WebInspector.Popover.Orie ntation.Bottom)) {
181 // Positioning above the anchor.
182 if ((anchorBox.y > newElementPosition.height + arrowHeight + borderRadius) ||
183 (arrowDirection === WebInspector.Popover.Orientation.Bottom))
184 newElementPosition.y = anchorBox.y - newElementPosition.height - arrowHe ight;
185 else {
186 this._popupArrowElement.hidden = true;
187 newElementPosition.y = borderRadius;
188 newElementPosition.height = anchorBox.y - borderRadius * 2 - arrowHeight ;
189 if (this._hasFixedHeight && newElementPosition.height < preferredHeight) {
190 newElementPosition.y = borderRadius;
191 newElementPosition.height = preferredHeight;
192 }
193 }
194 verticalAlignment = WebInspector.Popover.Orientation.Bottom;
195 } else {
196 // Positioning below the anchor.
197 newElementPosition.y = anchorBox.y + anchorBox.height + arrowHeight;
198 if ((newElementPosition.y + newElementPosition.height + borderRadius >= to talHeight) &&
199 (arrowDirection !== WebInspector.Popover.Orientation.Top)) {
200 this._popupArrowElement.hidden = true;
201 newElementPosition.height = totalHeight - borderRadius - newElementPosit ion.y;
202 if (this._hasFixedHeight && newElementPosition.height < preferredHeight) {
203 newElementPosition.y = totalHeight - preferredHeight - borderRadius;
204 newElementPosition.height = preferredHeight;
205 }
206 }
207 // Align arrow.
208 verticalAlignment = WebInspector.Popover.Orientation.Top;
209 }
210
211 var horizontalAlignment;
212 this._popupArrowElement.removeAttribute('style');
213 if (anchorBox.x + newElementPosition.width < totalWidth) {
214 newElementPosition.x = Math.max(borderRadius, anchorBox.x - borderRadius - arrowOffset);
215 horizontalAlignment = 'left';
216 this._popupArrowElement.style.left = arrowOffset + 'px';
217 } else if (newElementPosition.width + borderRadius * 2 < totalWidth) {
218 newElementPosition.x = totalWidth - newElementPosition.width - borderRadiu s - 2 * borderWidth;
219 horizontalAlignment = 'right';
220 // Position arrow accurately.
221 var arrowRightPosition = Math.max(0, totalWidth - anchorBox.x - anchorBox. width - borderRadius - arrowOffset);
222 arrowRightPosition += anchorBox.width / 2;
223 arrowRightPosition = Math.min(arrowRightPosition, newElementPosition.width - borderRadius - arrowOffset);
224 this._popupArrowElement.style.right = arrowRightPosition + 'px';
225 } else {
226 newElementPosition.x = borderRadius;
227 newElementPosition.width = totalWidth - borderRadius * 2;
228 newElementPosition.height += scrollerWidth;
229 horizontalAlignment = 'left';
230 if (verticalAlignment === WebInspector.Popover.Orientation.Bottom)
231 newElementPosition.y -= scrollerWidth;
232 // Position arrow accurately.
233 this._popupArrowElement.style.left =
234 Math.max(0, anchorBox.x - newElementPosition.x - borderRadius - arrowR adius + anchorBox.width / 2) + 'px';
235 }
236
237 this.element.className =
238 WebInspector.Popover._classNamePrefix + ' ' + verticalAlignment + '-' + horizontalAlignment + '-arrow';
239 this.element.positionAt(newElementPosition.x, newElementPosition.y - borderW idth, container);
240 this.element.style.width = newElementPosition.width + borderWidth * 2 + 'px' ;
241 this.element.style.height = newElementPosition.height + borderWidth * 2 + 'p x';
242 }
48 }; 243 };
49 244
50 WebInspector.Popover._classNamePrefix = "popover"; 245 WebInspector.Popover._classNamePrefix = 'popover';
51 246
52 WebInspector.Popover.prototype = { 247 /**
248 * @unrestricted
249 */
250 WebInspector.PopoverHelper = class {
251 /**
252 * @param {!Element} panelElement
253 * @param {boolean=} disableOnClick
254 */
255 constructor(panelElement, disableOnClick) {
256 this._disableOnClick = !!disableOnClick;
257 panelElement.addEventListener('mousedown', this._mouseDown.bind(this), false );
258 panelElement.addEventListener('mousemove', this._mouseMove.bind(this), false );
259 panelElement.addEventListener('mouseout', this._mouseOut.bind(this), false);
260 this.setTimeout(1000, 500);
261 }
262
263 /**
264 * @param {function(!Element, !Event):(!Element|!AnchorBox|undefined)} getAnch or
265 * @param {function(!Element, !WebInspector.Popover):undefined} showPopover
266 * @param {function()=} onHide
267 */
268 initializeCallbacks(getAnchor, showPopover, onHide) {
269 this._getAnchor = getAnchor;
270 this._showPopover = showPopover;
271 this._onHide = onHide;
272 }
273
274 /**
275 * @param {number} timeout
276 * @param {number=} hideTimeout
277 */
278 setTimeout(timeout, hideTimeout) {
279 this._timeout = timeout;
280 if (typeof hideTimeout === 'number')
281 this._hideTimeout = hideTimeout;
282 else
283 this._hideTimeout = timeout / 2;
284 }
285
286 /**
287 * @param {!MouseEvent} event
288 * @return {boolean}
289 */
290 _eventInHoverElement(event) {
291 if (!this._hoverElement)
292 return false;
293 var box = this._hoverElement instanceof AnchorBox ? this._hoverElement : thi s._hoverElement.boxInWindow();
294 return (
295 box.x <= event.clientX && event.clientX <= box.x + box.width && box.y <= event.clientY &&
296 event.clientY <= box.y + box.height);
297 }
298
299 _mouseDown(event) {
300 if (this._disableOnClick || !this._eventInHoverElement(event))
301 this.hidePopover();
302 else {
303 this._killHidePopoverTimer();
304 this._handleMouseAction(event, true);
305 }
306 }
307
308 _mouseMove(event) {
309 // Pretend that nothing has happened.
310 if (this._eventInHoverElement(event))
311 return;
312
313 this._startHidePopoverTimer();
314 this._handleMouseAction(event, false);
315 }
316
317 _popoverMouseOut(event) {
318 if (!this.isPopoverVisible())
319 return;
320 if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(this._pop over._contentDiv))
321 this._startHidePopoverTimer();
322 }
323
324 _mouseOut(event) {
325 if (!this.isPopoverVisible())
326 return;
327 if (!this._eventInHoverElement(event))
328 this._startHidePopoverTimer();
329 }
330
331 _startHidePopoverTimer() {
332 // User has 500ms (this._hideTimeout) to reach the popup.
333 if (!this._popover || this._hidePopoverTimer)
334 return;
335
53 /** 336 /**
54 * @param {!Element} element 337 * @this {WebInspector.PopoverHelper}
55 * @param {!Element|!AnchorBox} anchor
56 * @param {?number=} preferredWidth
57 * @param {?number=} preferredHeight
58 * @param {?WebInspector.Popover.Orientation=} arrowDirection
59 */ 338 */
60 showForAnchor: function(element, anchor, preferredWidth, preferredHeight, ar rowDirection) 339 function doHide() {
61 { 340 this._hidePopover();
62 this._innerShow(null, element, anchor, preferredWidth, preferredHeight, arrowDirection); 341 delete this._hidePopoverTimer;
63 }, 342 }
64 343 this._hidePopoverTimer = setTimeout(doHide.bind(this), this._hideTimeout);
65 /** 344 }
66 * @param {!WebInspector.Widget} view 345
67 * @param {!Element|!AnchorBox} anchor 346 _handleMouseAction(event, isMouseDown) {
68 * @param {?number=} preferredWidth 347 this._resetHoverTimer();
69 * @param {?number=} preferredHeight 348 if (event.which && this._disableOnClick)
70 */ 349 return;
71 showView: function(view, anchor, preferredWidth, preferredHeight) 350 this._hoverElement = this._getAnchor(event.target, event);
72 { 351 if (!this._hoverElement)
73 this._innerShow(view, view.element, anchor, preferredWidth, preferredHei ght); 352 return;
74 }, 353 const toolTipDelay = isMouseDown ? 0 : (this._popup ? this._timeout * 0.6 : this._timeout);
75 354 this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement ), toolTipDelay);
76 /** 355 }
77 * @param {?WebInspector.Widget} view 356
78 * @param {!Element} contentElement 357 _resetHoverTimer() {
79 * @param {!Element|!AnchorBox} anchor 358 if (this._hoverTimer) {
80 * @param {?number=} preferredWidth 359 clearTimeout(this._hoverTimer);
81 * @param {?number=} preferredHeight 360 delete this._hoverTimer;
82 * @param {?WebInspector.Popover.Orientation=} arrowDirection 361 }
83 */ 362 }
84 _innerShow: function(view, contentElement, anchor, preferredWidth, preferred Height, arrowDirection) 363
85 { 364 /**
86 if (this._disposed) 365 * @return {boolean}
87 return; 366 */
88 this._contentElement = contentElement; 367 isPopoverVisible() {
89 368 return !!this._popover;
90 // This should not happen, but we hide previous popup to be on the safe side. 369 }
91 if (WebInspector.Popover._popover) 370
92 WebInspector.Popover._popover.hide(); 371 hidePopover() {
93 WebInspector.Popover._popover = this; 372 this._resetHoverTimer();
94 373 this._hidePopover();
95 var document = anchor instanceof Element ? anchor.ownerDocument : conten tElement.ownerDocument; 374 }
96 var window = document.defaultView; 375
97 376 _hidePopover() {
98 // Temporarily attach in order to measure preferred dimensions. 377 if (!this._popover)
99 var preferredSize = view ? view.measurePreferredSize() : WebInspector.me asurePreferredSize(this._contentElement); 378 return;
100 this._preferredWidth = preferredWidth || preferredSize.width; 379
101 this._preferredHeight = preferredHeight || preferredSize.height; 380 if (this._onHide)
102 381 this._onHide();
103 window.addEventListener("resize", this._hideBound, false); 382
104 document.body.appendChild(this._containerElement); 383 this._popover.dispose();
105 WebInspector.Widget.prototype.show.call(this, this._containerElement); 384 delete this._popover;
106 385 this._hoverElement = null;
107 if (view) 386 }
108 view.show(this._contentDiv); 387
109 else 388 _mouseHover(element) {
110 this._contentDiv.appendChild(this._contentElement); 389 delete this._hoverTimer;
111 390 this._hoverElement = element;
112 this.positionElement(anchor, this._preferredWidth, this._preferredHeight , arrowDirection); 391 this._hidePopover();
113 392 this._popover = new WebInspector.Popover(this);
114 if (this._popoverHelper) { 393 this._showPopover(element, this._popover);
115 this._contentDiv.addEventListener("mousemove", this._popoverHelper._ killHidePopoverTimer.bind(this._popoverHelper), true); 394 }
116 this.element.addEventListener("mouseout", this._popoverHelper._popov erMouseOut.bind(this._popoverHelper), true); 395
117 } 396 _killHidePopoverTimer() {
118 }, 397 if (this._hidePopoverTimer) {
119 398 clearTimeout(this._hidePopoverTimer);
120 hide: function() 399 delete this._hidePopoverTimer;
121 { 400
122 this._containerElement.ownerDocument.defaultView.removeEventListener("re size", this._hideBound, false); 401 // We know that we reached the popup, but we might have moved over other e lements.
123 this.detach(); 402 // Discard pending command.
124 this._containerElement.remove(); 403 this._resetHoverTimer();
125 delete WebInspector.Popover._popover; 404 }
126 }, 405 }
127
128 get disposed()
129 {
130 return this._disposed;
131 },
132
133 dispose: function()
134 {
135 if (this.isShowing())
136 this.hide();
137 this._disposed = true;
138 },
139
140 /**
141 * @param {boolean} canShrink
142 */
143 setCanShrink: function(canShrink)
144 {
145 this._hasFixedHeight = !canShrink;
146 this._contentDiv.classList.toggle("fixed-height", this._hasFixedHeight);
147 },
148
149 /**
150 * @param {boolean} noPadding
151 */
152 setNoPadding: function(noPadding)
153 {
154 this._hasNoPadding = noPadding;
155 this._contentDiv.classList.toggle("no-padding", this._hasNoPadding);
156 },
157
158 /**
159 * @param {!Element|!AnchorBox} anchorElement
160 * @param {number=} preferredWidth
161 * @param {number=} preferredHeight
162 * @param {?WebInspector.Popover.Orientation=} arrowDirection
163 */
164 positionElement: function(anchorElement, preferredWidth, preferredHeight, ar rowDirection)
165 {
166 const borderWidth = this._hasNoPadding ? 0 : 8;
167 const scrollerWidth = this._hasFixedHeight ? 0 : 14;
168 const arrowHeight = this._hasNoPadding ? 8 : 15;
169 const arrowOffset = 10;
170 const borderRadius = 4;
171 const arrowRadius = 6;
172 preferredWidth = preferredWidth || this._preferredWidth;
173 preferredHeight = preferredHeight || this._preferredHeight;
174
175 // Skinny tooltips are not pretty, their arrow location is not nice.
176 preferredWidth = Math.max(preferredWidth, 50);
177 // Position relative to main DevTools element.
178 const container = WebInspector.Dialog.modalHostView().element;
179 const totalWidth = container.offsetWidth;
180 const totalHeight = container.offsetHeight;
181
182 var anchorBox = anchorElement instanceof AnchorBox ? anchorElement : anc horElement.boxInWindow(window);
183 anchorBox = anchorBox.relativeToElement(container);
184 var newElementPosition = { x: 0, y: 0, width: preferredWidth + scrollerW idth, height: preferredHeight };
185
186 var verticalAlignment;
187 var roomAbove = anchorBox.y;
188 var roomBelow = totalHeight - anchorBox.y - anchorBox.height;
189 this._popupArrowElement.hidden = false;
190
191 if ((roomAbove > roomBelow) || (arrowDirection === WebInspector.Popover. Orientation.Bottom)) {
192 // Positioning above the anchor.
193 if ((anchorBox.y > newElementPosition.height + arrowHeight + borderR adius) || (arrowDirection === WebInspector.Popover.Orientation.Bottom))
194 newElementPosition.y = anchorBox.y - newElementPosition.height - arrowHeight;
195 else {
196 this._popupArrowElement.hidden = true;
197 newElementPosition.y = borderRadius;
198 newElementPosition.height = anchorBox.y - borderRadius * 2 - arr owHeight;
199 if (this._hasFixedHeight && newElementPosition.height < preferre dHeight) {
200 newElementPosition.y = borderRadius;
201 newElementPosition.height = preferredHeight;
202 }
203 }
204 verticalAlignment = WebInspector.Popover.Orientation.Bottom;
205 } else {
206 // Positioning below the anchor.
207 newElementPosition.y = anchorBox.y + anchorBox.height + arrowHeight;
208 if ((newElementPosition.y + newElementPosition.height + borderRadius >= totalHeight) && (arrowDirection !== WebInspector.Popover.Orientation.Top)) {
209 this._popupArrowElement.hidden = true;
210 newElementPosition.height = totalHeight - borderRadius - newElem entPosition.y;
211 if (this._hasFixedHeight && newElementPosition.height < preferre dHeight) {
212 newElementPosition.y = totalHeight - preferredHeight - borde rRadius;
213 newElementPosition.height = preferredHeight;
214 }
215 }
216 // Align arrow.
217 verticalAlignment = WebInspector.Popover.Orientation.Top;
218 }
219
220 var horizontalAlignment;
221 this._popupArrowElement.removeAttribute("style");
222 if (anchorBox.x + newElementPosition.width < totalWidth) {
223 newElementPosition.x = Math.max(borderRadius, anchorBox.x - borderRa dius - arrowOffset);
224 horizontalAlignment = "left";
225 this._popupArrowElement.style.left = arrowOffset + "px";
226 } else if (newElementPosition.width + borderRadius * 2 < totalWidth) {
227 newElementPosition.x = totalWidth - newElementPosition.width - borde rRadius - 2 * borderWidth;
228 horizontalAlignment = "right";
229 // Position arrow accurately.
230 var arrowRightPosition = Math.max(0, totalWidth - anchorBox.x - anch orBox.width - borderRadius - arrowOffset);
231 arrowRightPosition += anchorBox.width / 2;
232 arrowRightPosition = Math.min(arrowRightPosition, newElementPosition .width - borderRadius - arrowOffset);
233 this._popupArrowElement.style.right = arrowRightPosition + "px";
234 } else {
235 newElementPosition.x = borderRadius;
236 newElementPosition.width = totalWidth - borderRadius * 2;
237 newElementPosition.height += scrollerWidth;
238 horizontalAlignment = "left";
239 if (verticalAlignment === WebInspector.Popover.Orientation.Bottom)
240 newElementPosition.y -= scrollerWidth;
241 // Position arrow accurately.
242 this._popupArrowElement.style.left = Math.max(0, anchorBox.x - newEl ementPosition.x - borderRadius - arrowRadius + anchorBox.width / 2) + "px";
243 }
244
245 this.element.className = WebInspector.Popover._classNamePrefix + " " + v erticalAlignment + "-" + horizontalAlignment + "-arrow";
246 this.element.positionAt(newElementPosition.x, newElementPosition.y - bor derWidth, container);
247 this.element.style.width = newElementPosition.width + borderWidth * 2 + "px";
248 this.element.style.height = newElementPosition.height + borderWidth * 2 + "px";
249 },
250
251 __proto__: WebInspector.Widget.prototype
252 };
253
254 /**
255 * @constructor
256 * @param {!Element} panelElement
257 * @param {boolean=} disableOnClick
258 */
259 WebInspector.PopoverHelper = function(panelElement, disableOnClick)
260 {
261 this._disableOnClick = !!disableOnClick;
262 panelElement.addEventListener("mousedown", this._mouseDown.bind(this), false );
263 panelElement.addEventListener("mousemove", this._mouseMove.bind(this), false );
264 panelElement.addEventListener("mouseout", this._mouseOut.bind(this), false);
265 this.setTimeout(1000, 500);
266 };
267
268 WebInspector.PopoverHelper.prototype = {
269 /**
270 * @param {function(!Element, !Event):(!Element|!AnchorBox|undefined)} getAn chor
271 * @param {function(!Element, !WebInspector.Popover):undefined} showPopover
272 * @param {function()=} onHide
273 */
274 initializeCallbacks:function(getAnchor, showPopover, onHide)
275 {
276 this._getAnchor = getAnchor;
277 this._showPopover = showPopover;
278 this._onHide = onHide;
279 },
280
281 /**
282 * @param {number} timeout
283 * @param {number=} hideTimeout
284 */
285 setTimeout: function(timeout, hideTimeout)
286 {
287 this._timeout = timeout;
288 if (typeof hideTimeout === "number")
289 this._hideTimeout = hideTimeout;
290 else
291 this._hideTimeout = timeout / 2;
292 },
293
294 /**
295 * @param {!MouseEvent} event
296 * @return {boolean}
297 */
298 _eventInHoverElement: function(event)
299 {
300 if (!this._hoverElement)
301 return false;
302 var box = this._hoverElement instanceof AnchorBox ? this._hoverElement : this._hoverElement.boxInWindow();
303 return (box.x <= event.clientX && event.clientX <= box.x + box.width &&
304 box.y <= event.clientY && event.clientY <= box.y + box.height);
305 },
306
307 _mouseDown: function(event)
308 {
309 if (this._disableOnClick || !this._eventInHoverElement(event))
310 this.hidePopover();
311 else {
312 this._killHidePopoverTimer();
313 this._handleMouseAction(event, true);
314 }
315 },
316
317 _mouseMove: function(event)
318 {
319 // Pretend that nothing has happened.
320 if (this._eventInHoverElement(event))
321 return;
322
323 this._startHidePopoverTimer();
324 this._handleMouseAction(event, false);
325 },
326
327 _popoverMouseOut: function(event)
328 {
329 if (!this.isPopoverVisible())
330 return;
331 if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(this. _popover._contentDiv))
332 this._startHidePopoverTimer();
333 },
334
335 _mouseOut: function(event)
336 {
337 if (!this.isPopoverVisible())
338 return;
339 if (!this._eventInHoverElement(event))
340 this._startHidePopoverTimer();
341 },
342
343 _startHidePopoverTimer: function()
344 {
345 // User has 500ms (this._hideTimeout) to reach the popup.
346 if (!this._popover || this._hidePopoverTimer)
347 return;
348
349 /**
350 * @this {WebInspector.PopoverHelper}
351 */
352 function doHide()
353 {
354 this._hidePopover();
355 delete this._hidePopoverTimer;
356 }
357 this._hidePopoverTimer = setTimeout(doHide.bind(this), this._hideTimeout );
358 },
359
360 _handleMouseAction: function(event, isMouseDown)
361 {
362 this._resetHoverTimer();
363 if (event.which && this._disableOnClick)
364 return;
365 this._hoverElement = this._getAnchor(event.target, event);
366 if (!this._hoverElement)
367 return;
368 const toolTipDelay = isMouseDown ? 0 : (this._popup ? this._timeout * 0. 6 : this._timeout);
369 this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverEle ment), toolTipDelay);
370 },
371
372 _resetHoverTimer: function()
373 {
374 if (this._hoverTimer) {
375 clearTimeout(this._hoverTimer);
376 delete this._hoverTimer;
377 }
378 },
379
380 /**
381 * @return {boolean}
382 */
383 isPopoverVisible: function()
384 {
385 return !!this._popover;
386 },
387
388 hidePopover: function()
389 {
390 this._resetHoverTimer();
391 this._hidePopover();
392 },
393
394 _hidePopover: function()
395 {
396 if (!this._popover)
397 return;
398
399 if (this._onHide)
400 this._onHide();
401
402 this._popover.dispose();
403 delete this._popover;
404 this._hoverElement = null;
405 },
406
407 _mouseHover: function(element)
408 {
409 delete this._hoverTimer;
410 this._hoverElement = element;
411 this._hidePopover();
412 this._popover = new WebInspector.Popover(this);
413 this._showPopover(element, this._popover);
414 },
415
416 _killHidePopoverTimer: function()
417 {
418 if (this._hidePopoverTimer) {
419 clearTimeout(this._hidePopoverTimer);
420 delete this._hidePopoverTimer;
421
422 // We know that we reached the popup, but we might have moved over o ther elements.
423 // Discard pending command.
424 this._resetHoverTimer();
425 }
426 }
427 }; 406 };
428 407
429 /** @enum {string} */ 408 /** @enum {string} */
430 WebInspector.Popover.Orientation = { 409 WebInspector.Popover.Orientation = {
431 Top: "top", 410 Top: 'top',
432 Bottom: "bottom" 411 Bottom: 'bottom'
433 }; 412 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698