OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @constructor | 6 * @constructor |
7 * @param {!Document} doc | 7 * @param {!Document} doc |
8 */ | 8 */ |
9 WebInspector.Tooltip = function(doc) | 9 WebInspector.Tooltip = function(doc) |
10 { | 10 { |
11 this.element = doc.body.createChild("div"); | 11 this.element = doc.body.createChild("div"); |
12 this._shadowRoot = WebInspector.createShadowRootWithCoreStyles(this.element)
; | 12 this._shadowRoot = WebInspector.createShadowRootWithCoreStyles(this.element)
; |
13 this._shadowRoot.appendChild(WebInspector.Widget.createStyleElement("ui/tool
tip.css")); | 13 this._shadowRoot.appendChild(WebInspector.Widget.createStyleElement("ui/tool
tip.css")); |
14 | 14 |
15 this._tooltipElement = this._shadowRoot.createChild("div", "tooltip"); | 15 this._tooltipElement = this._shadowRoot.createChild("div", "tooltip"); |
16 doc.addEventListener("mousemove", this._mouseMove.bind(this), true); | 16 doc.addEventListener("mousemove", this._mouseMove.bind(this), true); |
17 doc.addEventListener("mousedown", this._hide.bind(this, true), true); | 17 doc.addEventListener("mousedown", this._hide.bind(this, true), true); |
| 18 doc.addEventListener("mouseout", this._hide.bind(this, true), true); |
| 19 doc.addEventListener("keydown", this._hide.bind(this, true), true); |
18 } | 20 } |
19 | 21 |
20 WebInspector.Tooltip.Timing = { | 22 WebInspector.Tooltip.Timing = { |
21 // Max time between tooltips showing that no opening delay is required. | 23 // Max time between tooltips showing that no opening delay is required. |
22 "InstantThreshold": 300, | 24 "InstantThreshold": 300, |
23 // Wait time before opening a tooltip. | 25 // Wait time before opening a tooltip. |
24 "OpeningDelay": 600 | 26 "OpeningDelay": 600 |
25 } | 27 } |
26 | 28 |
27 WebInspector.Tooltip.AlignmentOverride = { | |
28 Right: "Right" | |
29 } | |
30 | |
31 WebInspector.Tooltip.prototype = { | 29 WebInspector.Tooltip.prototype = { |
32 /** | 30 /** |
33 * @param {!Event} event | 31 * @param {!Event} event |
34 */ | 32 */ |
35 _mouseMove: function(event) | 33 _mouseMove: function(event) |
36 { | 34 { |
37 var path = event.deepPath ? event.deepPath : event.path; | 35 var path = event.deepPath ? event.deepPath : event.path; |
38 if (!path || event.buttons !== 0) | 36 if (!path || event.buttons !== 0) |
39 return; | 37 return; |
40 | 38 |
41 if (this._anchorElement && path.indexOf(this._anchorElement) === -1) | 39 if (this._anchorElement && path.indexOf(this._anchorElement) === -1) |
42 this._hide(); | 40 this._hide(); |
43 | 41 |
44 for (var element of path) { | 42 for (var element of path) { |
45 if (element === this._anchorElement) { | 43 if (element === this._anchorElement) { |
46 return; | 44 return; |
47 } else if (element[WebInspector.Tooltip._symbol]) { | 45 } else if (element[WebInspector.Tooltip._symbol]) { |
48 this._show(element); | 46 this._show(element, event); |
49 return; | 47 return; |
50 } | 48 } |
51 } | 49 } |
52 }, | 50 }, |
53 | 51 |
54 /** | 52 /** |
55 * @param {!Element} anchorElement | 53 * @param {!Element} anchorElement |
| 54 * @param {!Event} event |
56 */ | 55 */ |
57 _show: function(anchorElement) | 56 _show: function(anchorElement, event) |
58 { | 57 { |
59 var tooltip = anchorElement[WebInspector.Tooltip._symbol]; | 58 var tooltip = anchorElement[WebInspector.Tooltip._symbol]; |
60 this._anchorElement = anchorElement; | 59 this._anchorElement = anchorElement; |
61 this._tooltipElement.removeChildren(); | 60 this._tooltipElement.removeChildren(); |
| 61 |
| 62 // Check if native tooltips should be used. |
| 63 for (var element of WebInspector.Tooltip._nativeOverrideContainer) { |
| 64 if (this._anchorElement.isSelfOrDescendant(element)) { |
| 65 Object.defineProperty(this._anchorElement, "title", WebInspector
.Tooltip._nativeTitle); |
| 66 this._anchorElement.title = tooltip.content; |
| 67 return; |
| 68 } |
| 69 } |
| 70 |
62 if (typeof tooltip.content === "string") | 71 if (typeof tooltip.content === "string") |
63 this._tooltipElement.textContent = tooltip.content; | 72 this._tooltipElement.textContent = tooltip.content; |
64 else | 73 else |
65 this._tooltipElement.appendChild(tooltip.content); | 74 this._tooltipElement.appendChild(tooltip.content); |
66 | 75 |
67 if (tooltip.actionId) { | 76 if (tooltip.actionId) { |
68 var shortcuts = WebInspector.shortcutRegistry.shortcutDescriptorsFor
Action(tooltip.actionId); | 77 var shortcuts = WebInspector.shortcutRegistry.shortcutDescriptorsFor
Action(tooltip.actionId); |
69 for (var shortcut of shortcuts) { | 78 for (var shortcut of shortcuts) { |
70 var shortcutElement = this._tooltipElement.createChild("div", "t
ooltip-shortcut"); | 79 var shortcutElement = this._tooltipElement.createChild("div", "t
ooltip-shortcut"); |
71 shortcutElement.textContent = shortcut.name; | 80 shortcutElement.textContent = shortcut.name; |
(...skipping 15 matching lines...) Expand all Loading... |
87 if (!anchorElement.isDescendant(container)) | 96 if (!anchorElement.isDescendant(container)) |
88 container = this.element.parentElement; | 97 container = this.element.parentElement; |
89 | 98 |
90 // Posititon tooltip based on the anchor element. | 99 // Posititon tooltip based on the anchor element. |
91 var containerOffset = container.offsetRelativeToWindow(this.element.wind
ow()); | 100 var containerOffset = container.offsetRelativeToWindow(this.element.wind
ow()); |
92 var containerOffsetWidth = container.offsetWidth; | 101 var containerOffsetWidth = container.offsetWidth; |
93 var containerOffsetHeight = container.offsetHeight; | 102 var containerOffsetHeight = container.offsetHeight; |
94 var anchorBox = this._anchorElement.boxInWindow(this.element.window()); | 103 var anchorBox = this._anchorElement.boxInWindow(this.element.window()); |
95 const anchorOffset = 2; | 104 const anchorOffset = 2; |
96 const pageMargin = 2; | 105 const pageMargin = 2; |
| 106 var cursorOffset = 10; |
97 this._tooltipElement.style.maxWidth = (containerOffsetWidth - pageMargin
* 2) + "px"; | 107 this._tooltipElement.style.maxWidth = (containerOffsetWidth - pageMargin
* 2) + "px"; |
98 var tooltipWidth = this._tooltipElement.offsetWidth; | 108 var tooltipWidth = this._tooltipElement.offsetWidth; |
99 var tooltipHeight = this._tooltipElement.offsetHeight; | 109 var tooltipHeight = this._tooltipElement.offsetHeight; |
100 var tooltipX = anchorBox.x; | 110 var anchorTooltipAtElement = this._anchorElement.nodeName === "BUTTON" |
| this._anchorElement.nodeName === "LABEL"; |
| 111 var tooltipX = anchorTooltipAtElement ? anchorBox.x : event.x + cursorOf
fset; |
101 tooltipX = Number.constrain(tooltipX, | 112 tooltipX = Number.constrain(tooltipX, |
102 containerOffset.x + pageMargin, | 113 containerOffset.x + pageMargin, |
103 containerOffset.x + containerOffsetWidth - tooltipWidth - pageMargin
); | 114 containerOffset.x + containerOffsetWidth - tooltipWidth - pageMargin
); |
104 var onBottom = anchorBox.y + anchorOffset + anchorBox.height + tooltipHe
ight < containerOffset.y + containerOffsetHeight; | 115 var tooltipY; |
105 var tooltipY = onBottom ? anchorBox.y + anchorBox.height + anchorOffset
: anchorBox.y - tooltipHeight - anchorOffset; | 116 if (!anchorTooltipAtElement) { |
| 117 tooltipY = event.y + cursorOffset; |
| 118 } else { |
| 119 var onBottom = anchorBox.y + anchorOffset + anchorBox.height + toolt
ipHeight < containerOffset.y + containerOffsetHeight; |
| 120 tooltipY = onBottom ? anchorBox.y + anchorBox.height + anchorOffset
: anchorBox.y - tooltipHeight - anchorOffset; |
| 121 } |
106 this._tooltipElement.positionAt(tooltipX, tooltipY); | 122 this._tooltipElement.positionAt(tooltipX, tooltipY); |
107 }, | 123 }, |
108 | 124 |
109 /** | 125 /** |
110 * @param {boolean=} removeInstant | 126 * @param {boolean=} removeInstant |
111 */ | 127 */ |
112 _hide: function(removeInstant) | 128 _hide: function(removeInstant) |
113 { | 129 { |
114 delete this._anchorElement; | 130 delete this._anchorElement; |
115 this._tooltipElement.classList.remove("shown"); | 131 this._tooltipElement.classList.remove("shown"); |
(...skipping 11 matching lines...) Expand all Loading... |
127 */ | 143 */ |
128 WebInspector.Tooltip.installHandler = function(doc) | 144 WebInspector.Tooltip.installHandler = function(doc) |
129 { | 145 { |
130 new WebInspector.Tooltip(doc); | 146 new WebInspector.Tooltip(doc); |
131 } | 147 } |
132 | 148 |
133 /** | 149 /** |
134 * @param {!Element} element | 150 * @param {!Element} element |
135 * @param {!Element|string} tooltipContent | 151 * @param {!Element|string} tooltipContent |
136 * @param {string=} actionId | 152 * @param {string=} actionId |
| 153 * @param {!Object=} options |
137 */ | 154 */ |
138 WebInspector.Tooltip.install = function(element, tooltipContent, actionId) | 155 WebInspector.Tooltip.install = function(element, tooltipContent, actionId, optio
ns) |
139 { | 156 { |
140 if (typeof tooltipContent === "string" && tooltipContent === "") { | 157 if (typeof tooltipContent === "string" && tooltipContent === "") { |
141 delete element[WebInspector.Tooltip._symbol]; | 158 delete element[WebInspector.Tooltip._symbol]; |
142 return; | 159 return; |
143 } | 160 } |
144 element[WebInspector.Tooltip._symbol] = { content: tooltipContent, actionId
: actionId }; | 161 element[WebInspector.Tooltip._symbol] = { content: tooltipContent, actionId:
actionId, options: options || {} }; |
145 } | 162 } |
146 | 163 |
| 164 /** |
| 165 * @param {!Element} element |
| 166 */ |
| 167 WebInspector.Tooltip.addNativeOverrideContainer = function(element) |
| 168 { |
| 169 WebInspector.Tooltip._nativeOverrideContainer.push(element); |
| 170 } |
| 171 |
| 172 /** @type {!Array.<!Element>} */ |
| 173 WebInspector.Tooltip._nativeOverrideContainer = []; |
| 174 WebInspector.Tooltip._nativeTitle = /** @type {!ObjectPropertyDescriptor} */(Obj
ect.getOwnPropertyDescriptor(HTMLElement.prototype, "title")); |
| 175 |
147 Object.defineProperty(HTMLElement.prototype, "title", { | 176 Object.defineProperty(HTMLElement.prototype, "title", { |
148 /** | 177 /** |
149 * @return {!Element|string} | 178 * @return {!Element|string} |
150 * @this {!Element} | 179 * @this {!Element} |
151 */ | 180 */ |
152 get: function() | 181 get: function() |
153 { | 182 { |
154 var tooltip = this[WebInspector.Tooltip._symbol]; | 183 var tooltip = this[WebInspector.Tooltip._symbol]; |
155 return tooltip ? tooltip.content : ""; | 184 return tooltip ? tooltip.content : ""; |
156 }, | 185 }, |
157 | 186 |
158 /** | 187 /** |
159 * @param {!Element|string} x | 188 * @param {!Element|string} x |
160 * @this {!Element} | 189 * @this {!Element} |
161 */ | 190 */ |
162 set: function(x) | 191 set: function(x) |
163 { | 192 { |
164 WebInspector.Tooltip.install(this, x); | 193 WebInspector.Tooltip.install(this, x); |
165 } | 194 } |
166 }); | 195 }); |
OLD | NEW |