OLD | NEW |
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 |
(...skipping 10 matching lines...) Expand all Loading... |
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 | 30 |
31 UI.Popover = class extends UI.GlassPane { | |
32 /** | |
33 * @param {!UI.PopoverHelper=} popoverHelper | |
34 */ | |
35 constructor(popoverHelper) { | |
36 super(); | |
37 this.registerRequiredCSS('ui/popover.css'); | |
38 this.setBlockPointerEvents(false); | |
39 this.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent); | |
40 this.setShowArrow(true); | |
41 this._popoverHelper = popoverHelper; | |
42 } | |
43 | |
44 /** | |
45 * @param {!Element} element | |
46 * @param {!Element|!AnchorBox} anchor | |
47 */ | |
48 showForAnchor(element, anchor) { | |
49 this._innerShow(null, element, anchor); | |
50 } | |
51 | |
52 /** | |
53 * @param {!UI.Widget} view | |
54 * @param {!Element|!AnchorBox} anchor | |
55 */ | |
56 showView(view, anchor) { | |
57 this._innerShow(view, view.element, anchor); | |
58 } | |
59 | |
60 /** | |
61 * @param {?UI.Widget} widget | |
62 * @param {!Element} contentElement | |
63 * @param {!Element|!AnchorBox} anchor | |
64 */ | |
65 _innerShow(widget, contentElement, anchor) { | |
66 // This should not happen, but we hide previous popup to be on the safe side
. | |
67 if (UI.Popover._popover) | |
68 UI.Popover._popover.hide(); | |
69 UI.Popover._popover = this; | |
70 | |
71 var document = | |
72 /** @type {!Document} */ (anchor instanceof Element ? anchor.ownerDocume
nt : contentElement.ownerDocument); | |
73 var anchorBox = anchor instanceof AnchorBox ? anchor : anchor.boxInWindow(); | |
74 this.setContentAnchorBox(anchorBox); | |
75 | |
76 if (widget) | |
77 widget.show(this.contentElement); | |
78 else | |
79 this.contentElement.appendChild(contentElement); | |
80 | |
81 super.show(document); | |
82 | |
83 if (this._popoverHelper) { | |
84 this.contentElement.addEventListener( | |
85 'mousemove', this._popoverHelper._killHidePopoverTimer.bind(this._popo
verHelper), true); | |
86 this.contentElement.addEventListener( | |
87 'mouseout', this._popoverHelper._popoverMouseOut.bind(this._popoverHel
per), true); | |
88 } | |
89 } | |
90 | |
91 /** | |
92 * @override | |
93 */ | |
94 hide() { | |
95 super.hide(); | |
96 delete UI.Popover._popover; | |
97 } | |
98 | |
99 /** | |
100 * @param {boolean} noPadding | |
101 */ | |
102 setNoPadding(noPadding) { | |
103 // TODO(dgozman): remove this. Clients should add padding themselves. | |
104 this.contentElement.classList.toggle('no-padding', noPadding); | |
105 } | |
106 }; | |
107 | |
108 /** | 31 /** |
109 * @unrestricted | 32 * @unrestricted |
110 */ | 33 */ |
111 UI.PopoverHelper = class { | 34 UI.PopoverHelper = class { |
112 /** | 35 /** |
113 * @param {!Element} panelElement | 36 * @param {!Element} panelElement |
114 * @param {boolean=} disableOnClick | 37 * @param {boolean=} disableOnClick |
115 */ | 38 */ |
116 constructor(panelElement, disableOnClick) { | 39 constructor(panelElement, disableOnClick) { |
117 this._disableOnClick = !!disableOnClick; | 40 this._disableOnClick = !!disableOnClick; |
| 41 this._hasPadding = false; |
118 panelElement.addEventListener('mousedown', this._mouseDown.bind(this), false
); | 42 panelElement.addEventListener('mousedown', this._mouseDown.bind(this), false
); |
119 panelElement.addEventListener('mousemove', this._mouseMove.bind(this), false
); | 43 panelElement.addEventListener('mousemove', this._mouseMove.bind(this), false
); |
120 panelElement.addEventListener('mouseout', this._mouseOut.bind(this), false); | 44 panelElement.addEventListener('mouseout', this._mouseOut.bind(this), false); |
121 this.setTimeout(1000, 500); | 45 this.setTimeout(1000, 500); |
122 } | 46 } |
123 | 47 |
124 /** | 48 /** |
125 * @param {function(!Element, !Event):(!Element|!AnchorBox|undefined)} getAnch
or | 49 * @param {function(!Element, !Event):(!Element|!AnchorBox|undefined)} getAnch
or |
126 * @param {function(!Element, !UI.Popover):undefined} showPopover | 50 * @param {function(!Element, !UI.GlassPane):!Promise<boolean>} showPopover |
127 * @param {function()=} onHide | 51 * @param {function()=} onHide |
128 */ | 52 */ |
129 initializeCallbacks(getAnchor, showPopover, onHide) { | 53 initializeCallbacks(getAnchor, showPopover, onHide) { |
130 this._getAnchor = getAnchor; | 54 this._getAnchor = getAnchor; |
131 this._showPopover = showPopover; | 55 this._showPopover = showPopover; |
132 this._onHide = onHide; | 56 this._onHide = onHide; |
133 } | 57 } |
134 | 58 |
135 /** | 59 /** |
136 * @param {number} timeout | 60 * @param {number} timeout |
137 * @param {number=} hideTimeout | 61 * @param {number=} hideTimeout |
138 */ | 62 */ |
139 setTimeout(timeout, hideTimeout) { | 63 setTimeout(timeout, hideTimeout) { |
140 this._timeout = timeout; | 64 this._timeout = timeout; |
141 if (typeof hideTimeout === 'number') | 65 if (typeof hideTimeout === 'number') |
142 this._hideTimeout = hideTimeout; | 66 this._hideTimeout = hideTimeout; |
143 else | 67 else |
144 this._hideTimeout = timeout / 2; | 68 this._hideTimeout = timeout / 2; |
145 } | 69 } |
146 | 70 |
147 /** | 71 /** |
| 72 * @param {boolean} hasPadding |
| 73 */ |
| 74 setHasPadding(hasPadding) { |
| 75 this._hasPadding = hasPadding; |
| 76 } |
| 77 |
| 78 /** |
148 * @param {!MouseEvent} event | 79 * @param {!MouseEvent} event |
149 * @return {boolean} | 80 * @return {boolean} |
150 */ | 81 */ |
151 _eventInHoverElement(event) { | 82 _eventInHoverElement(event) { |
152 if (!this._hoverElement) | 83 if (!this._hoverElement) |
153 return false; | 84 return false; |
154 var box = this._hoverElement instanceof AnchorBox ? this._hoverElement : thi
s._hoverElement.boxInWindow(); | 85 var box = this._hoverElement instanceof AnchorBox ? this._hoverElement : thi
s._hoverElement.boxInWindow(); |
155 return ( | 86 return ( |
156 box.x <= event.clientX && event.clientX <= box.x + box.width && box.y <=
event.clientY && | 87 box.x <= event.clientX && event.clientX <= box.x + box.width && box.y <=
event.clientY && |
157 event.clientY <= box.y + box.height); | 88 event.clientY <= box.y + box.height); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 } | 136 } |
206 | 137 |
207 _handleMouseAction(event, isMouseDown) { | 138 _handleMouseAction(event, isMouseDown) { |
208 this._resetHoverTimer(); | 139 this._resetHoverTimer(); |
209 if (event.which && this._disableOnClick) | 140 if (event.which && this._disableOnClick) |
210 return; | 141 return; |
211 this._hoverElement = this._getAnchor(event.target, event); | 142 this._hoverElement = this._getAnchor(event.target, event); |
212 if (!this._hoverElement) | 143 if (!this._hoverElement) |
213 return; | 144 return; |
214 const toolTipDelay = isMouseDown ? 0 : (this._popup ? this._timeout * 0.6 :
this._timeout); | 145 const toolTipDelay = isMouseDown ? 0 : (this._popup ? this._timeout * 0.6 :
this._timeout); |
215 this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement
), toolTipDelay); | 146 this._hoverTimer = |
| 147 setTimeout(this._mouseHover.bind(this, this._hoverElement, event.target.
ownerDocument), toolTipDelay); |
216 } | 148 } |
217 | 149 |
218 _resetHoverTimer() { | 150 _resetHoverTimer() { |
219 if (this._hoverTimer) { | 151 if (this._hoverTimer) { |
220 clearTimeout(this._hoverTimer); | 152 clearTimeout(this._hoverTimer); |
221 delete this._hoverTimer; | 153 delete this._hoverTimer; |
222 } | 154 } |
223 } | 155 } |
224 | 156 |
225 /** | 157 /** |
226 * @return {boolean} | 158 * @return {boolean} |
227 */ | 159 */ |
228 isPopoverVisible() { | 160 isPopoverVisible() { |
229 return !!this._popover; | 161 return !!this._popover; |
230 } | 162 } |
231 | 163 |
232 hidePopover() { | 164 hidePopover() { |
233 this._resetHoverTimer(); | 165 this._resetHoverTimer(); |
234 this._hidePopover(); | 166 this._hidePopover(); |
235 } | 167 } |
236 | 168 |
237 _hidePopover() { | 169 _hidePopover() { |
238 if (!this._popover) | 170 if (!this._popover) |
239 return; | 171 return; |
240 | 172 |
| 173 delete UI.PopoverHelper._popover; |
241 if (this._onHide) | 174 if (this._onHide) |
242 this._onHide(); | 175 this._onHide(); |
243 | 176 |
244 if (this._popover.isShowing()) | 177 if (this._popover.isShowing()) |
245 this._popover.hide(); | 178 this._popover.hide(); |
246 delete this._popover; | 179 delete this._popover; |
247 this._hoverElement = null; | 180 this._hoverElement = null; |
248 } | 181 } |
249 | 182 |
250 _mouseHover(element) { | 183 _mouseHover(element, document) { |
251 delete this._hoverTimer; | 184 delete this._hoverTimer; |
252 this._hoverElement = element; | 185 this._hoverElement = element; |
253 this._hidePopover(); | 186 this._hidePopover(); |
254 this._popover = new UI.Popover(this); | 187 |
255 this._showPopover(element, this._popover); | 188 this._popover = new UI.GlassPane(); |
| 189 this._popover.registerRequiredCSS('ui/popover.css'); |
| 190 this._popover.setBlockPointerEvents(false); |
| 191 this._popover.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent); |
| 192 this._popover.setShowArrow(true); |
| 193 this._popover.contentElement.classList.toggle('has-padding', this._hasPaddin
g); |
| 194 this._popover.contentElement.addEventListener('mousemove', this._killHidePop
overTimer.bind(this), true); |
| 195 this._popover.contentElement.addEventListener('mouseout', this._popoverMouse
Out.bind(this), true); |
| 196 this._popover.setContentAnchorBox( |
| 197 this._hoverElement instanceof AnchorBox ? this._hoverElement : this._hov
erElement.boxInWindow()); |
| 198 |
| 199 // This should not happen, but we hide previous popover to be on the safe si
de. |
| 200 if (UI.PopoverHelper._popover) { |
| 201 console.error('One popover is already visible'); |
| 202 UI.PopoverHelper._popover.hide(); |
| 203 } |
| 204 UI.PopoverHelper._popover = this._popover; |
| 205 var popover = this._popover; |
| 206 this._showPopover(element, this._popover).then(success => { |
| 207 if (success && this._popover === popover && this._hoverElement === element
) |
| 208 popover.show(document); |
| 209 }); |
256 } | 210 } |
257 | 211 |
258 _killHidePopoverTimer() { | 212 _killHidePopoverTimer() { |
259 if (this._hidePopoverTimer) { | 213 if (this._hidePopoverTimer) { |
260 clearTimeout(this._hidePopoverTimer); | 214 clearTimeout(this._hidePopoverTimer); |
261 delete this._hidePopoverTimer; | 215 delete this._hidePopoverTimer; |
262 | 216 |
263 // We know that we reached the popup, but we might have moved over other e
lements. | 217 // We know that we reached the popup, but we might have moved over other e
lements. |
264 // Discard pending command. | 218 // Discard pending command. |
265 this._resetHoverTimer(); | 219 this._resetHoverTimer(); |
266 } | 220 } |
267 } | 221 } |
268 }; | 222 }; |
OLD | NEW |