@hpcc-js/html 3.3.13 → 3.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,384 +1,384 @@
1
- import { HTMLWidget, select as d3Select } from "@hpcc-js/common";
2
- import { scopedLogger, ScopedLogging } from "@hpcc-js/util";
3
-
4
- type Direction = "n" | "s" | "e" | "w" | "ne" | "nw" | "se" | "sw";
5
- type Position = { x: number, y: number };
6
- type DirectionalBBox = { [key in Direction]: Position; };
7
-
8
- type Rectangle = { top: number, left: number, width: number, height: number };
9
- export class HTMLTooltip extends HTMLWidget {
10
-
11
- public _triggerElement;
12
- public _contentNode;
13
- protected _prevContentNode;
14
-
15
- protected _tooltipElement;
16
- protected _arrowElement;
17
- protected _tooltipHTMLCallback = (data?) => "<b>_tooltipHTMLCallback is undefined</b>";
18
- protected _logger: ScopedLogging = scopedLogger("html/HTMLTooltip");
19
- constructor() {
20
- super();
21
- this.visible(false);
22
- }
23
-
24
- tooltipHTML(_: (data?) => string): this {
25
- this._tooltipHTMLCallback = _;
26
- return this;
27
- }
28
-
29
- tooltipContent(_): this {
30
- if (!arguments.length) return this._contentNode;
31
- this._contentNode = _;
32
- return this;
33
- }
34
-
35
- triggerElement(_): this {
36
- this._triggerElement = _;
37
- return this;
38
- }
39
-
40
- enter(domNode, element) {
41
- super.enter(domNode, element);
42
- const body = d3Select("body");
43
- this._tooltipElement = body.append("div")
44
- .attr("class", "tooltip-div")
45
- .style("z-index", "2147483638")
46
- .style("position", "fixed")
47
- ;
48
- this._arrowElement = body.append("div")
49
- .attr("class", "arrow-div")
50
- .style("z-index", "2147483638")
51
- .style("position", "fixed")
52
- ;
53
- }
54
-
55
- update(domNode, element) {
56
- super.update(domNode, element);
57
-
58
- if (this._contentNode !== this._prevContentNode) {
59
- const node = this._tooltipElement.node();
60
- [...node.querySelectorAll("*")]
61
- .map(n => n.__data__)
62
- .filter(n => n)
63
- .forEach(w => {
64
- if (typeof w.target === "function") {
65
- w.target(null);
66
- }
67
- if (typeof w.exit === "function") {
68
- w.exit();
69
- }
70
- });
71
- node.innerHTML = "";
72
- node.appendChild(this._contentNode);
73
- this._prevContentNode = this._contentNode;
74
- }
75
-
76
- if (this._contentNode) {
77
- this.onShowContent(this._contentNode);
78
- } else {
79
- this._tooltipElement
80
- .html(() => {
81
- return this._tooltipHTMLCallback(this.data());
82
- });
83
- }
84
- if (this.fitContent()) {
85
- this._tooltipElement
86
- .style("width", "auto")
87
- .style("height", "auto")
88
- .style("padding", "0px")
89
- .style("box-sizing", "content-box")
90
- ;
91
- const rect = this._tooltipElement.node().getBoundingClientRect();
92
- this.tooltipWidth_default(rect.width);
93
- this.tooltipHeight_default(rect.height);
94
- }
95
- this._closing = false;
96
- this._tooltipElement
97
- .style("background-color", this.tooltipColor())
98
- .style("color", this.fontColor())
99
- .style("width", this.tooltipWidth() + "px")
100
- .style("height", this.tooltipHeight() + "px")
101
- .style("opacity", 1)
102
- .style("padding", this.padding() + "px")
103
- .style("pointer-events", this.enablePointerEvents() ? "all" : "none")
104
- .style("box-sizing", "content-box")
105
- ;
106
- this._arrowElement
107
- .style("opacity", 1)
108
- .style("pointer-events", "none")
109
- ;
110
- this.updateTooltipPosition();
111
- }
112
-
113
- onShowContent(node) {
114
-
115
- }
116
-
117
- protected updateTooltipPosition(): Position {
118
- const bbox = this.calcReferenceBBox();
119
- const direction = this.calcTooltipDirection(bbox);
120
- const box = bbox[direction];
121
- this._tooltipElement
122
- .style("top", box.y + "px")
123
- .style("left", box.x + "px")
124
- ;
125
- this.setArrowPosition(box, direction);
126
- return box;
127
- }
128
-
129
- protected calcTooltipDirection(bbox: DirectionalBBox): Direction {
130
- const directions: Direction[] = Object.keys(bbox) as Direction[];
131
-
132
- const defaultDirection = this.direction();
133
- directions.sort((a, b) => a === defaultDirection ? -1 : 1);
134
- const windowRect = {
135
- top: 0,
136
- left: 0,
137
- width: window.innerWidth,
138
- height: window.innerHeight
139
- };
140
- for (let i = 0; i < directions.length; i++) {
141
- const tooltipRect = {
142
- top: bbox[directions[i]].y,
143
- left: bbox[directions[i]].x,
144
- width: this.tooltipWidth(),
145
- height: this.tooltipHeight()
146
- };
147
- if (this.rectFits(tooltipRect, windowRect)) {
148
- return directions[i];
149
- }
150
- }
151
- this._logger.warning(`Tooltip doesn't fit in the window for any of the directions. Defaulting to '${defaultDirection}'`);
152
- this._logger.debug(windowRect);
153
- this._logger.debug({
154
- top: bbox[defaultDirection].y,
155
- left: bbox[defaultDirection].x,
156
- width: this.tooltipWidth(),
157
- height: this.tooltipHeight()
158
- });
159
- return defaultDirection;
160
- }
161
-
162
- protected rectFits(innerRect: Rectangle, outerRect: Rectangle): boolean {
163
- return (
164
- innerRect.top >= outerRect.top &&
165
- innerRect.left >= outerRect.left &&
166
- innerRect.width + innerRect.left <= outerRect.width + outerRect.left &&
167
- innerRect.height + innerRect.top <= outerRect.height + outerRect.top
168
- );
169
- }
170
-
171
- protected setArrowPosition(point: Position, direction: Direction) {
172
- let top;
173
- let left;
174
- let visibleBorderStyle = "border-top-color";
175
- this._arrowElement
176
- .style("border", `${this.arrowHeight()}px solid ${this.tooltipColor()}`)
177
- .style("border-top-color", "transparent")
178
- .style("border-right-color", "transparent")
179
- .style("border-bottom-color", "transparent")
180
- .style("border-left-color", "transparent")
181
- ;
182
- switch (direction) {
183
- case "n":
184
- top = point.y + this.tooltipHeight() + (this.padding() * 2);
185
- left = point.x + (this.tooltipWidth() / 2) - (this.arrowWidth() / 2) + this.padding();
186
- visibleBorderStyle = "border-top-color";
187
- this._arrowElement
188
- .style("border-top-width", `${this.arrowHeight()}px`)
189
- .style("border-bottom-width", "0px")
190
- .style("border-left-width", `${this.arrowWidth() / 2}px`)
191
- .style("border-right-width", `${this.arrowWidth() / 2}px`)
192
- ;
193
- break;
194
- case "s":
195
- top = point.y - this.arrowHeight();
196
- left = point.x + this.padding() + (this.tooltipWidth() / 2) - (this.arrowWidth() / 2);
197
- visibleBorderStyle = "border-bottom-color";
198
- this._arrowElement
199
- .style("border-top-width", "0px")
200
- .style("border-bottom-width", `${this.arrowHeight()}px`)
201
- .style("border-left-width", `${this.arrowWidth() / 2}px`)
202
- .style("border-right-width", `${this.arrowWidth() / 2}px`)
203
- ;
204
- break;
205
- case "e":
206
- top = point.y + (this.tooltipHeight() / 2) + this.padding() - (this.arrowWidth() / 2);
207
- left = point.x - this.arrowHeight();
208
- visibleBorderStyle = "border-right-color";
209
- this._arrowElement
210
- .style("border-top-width", `${this.arrowWidth() / 2}px`)
211
- .style("border-bottom-width", `${this.arrowWidth() / 2}px`)
212
- .style("border-left-width", "0px")
213
- .style("border-right-width", `${this.arrowHeight()}px`)
214
- ;
215
- break;
216
- case "w":
217
- top = point.y + (this.tooltipHeight() / 2) - (this.arrowWidth() / 2) + this.padding();
218
- left = point.x + this.tooltipWidth() + (this.padding() * 2);
219
- visibleBorderStyle = "border-left-color";
220
- this._arrowElement
221
- .style("border-top-width", `${this.arrowWidth() / 2}px`)
222
- .style("border-bottom-width", `${this.arrowWidth() / 2}px`)
223
- .style("border-left-width", `${this.arrowHeight()}px`)
224
- .style("border-right-width", "0px")
225
- ;
226
- break;
227
- }
228
- if (typeof top !== "undefined" && typeof left !== "undefined") {
229
- this._arrowElement
230
- .style("top", top + "px")
231
- .style("left", left + "px")
232
- .style(visibleBorderStyle, this.tooltipColor())
233
- .style("opacity", 1)
234
- ;
235
- } else {
236
- this._arrowElement
237
- .style("opacity", 0)
238
- ;
239
- }
240
- return point;
241
- }
242
-
243
- protected getReferenceNode() {
244
- if (!this._triggerElement) {
245
- return this.element().node().parentNode.parentNode;
246
- }
247
- return this._triggerElement.node();
248
- }
249
- public _cursorLoc;
250
- protected calcReferenceBBox() {
251
- const node = this.getReferenceNode();
252
- let { top, left, width, height } = node.getBoundingClientRect();
253
- const wholeW = this.tooltipWidth();
254
- const wholeH = this.tooltipHeight();
255
- const halfW = wholeW / 2;
256
- const halfH = wholeH / 2;
257
- const arrowH = this.arrowHeight();
258
- const p = this.padding();
259
- const p2 = p * 2;
260
-
261
- if (this.followCursor() && this._cursorLoc) {
262
-
263
- left = this._cursorLoc[0];
264
- top = this._cursorLoc[1];
265
- width = 1;
266
- height = 1;
267
- }
268
- const bbox = {
269
- n: {
270
- x: left + (width / 2) - halfW - p,
271
- y: top - wholeH - arrowH - p2
272
- },
273
- e: {
274
- x: left + width + arrowH,
275
- y: top + (height / 2) - halfH - p
276
- },
277
- s: {
278
- x: left + (width / 2) - halfW - p,
279
- y: top + height + arrowH
280
- },
281
- w: {
282
- x: left - wholeW - arrowH - p2,
283
- y: top + (height / 2) - halfH - p
284
- },
285
- nw: {
286
- x: left - wholeW - p2,
287
- y: top - wholeH - p2
288
- },
289
- ne: {
290
- x: left + width,
291
- y: top - wholeH - p2
292
- },
293
- se: {
294
- x: left + width,
295
- y: top + height
296
- },
297
- sw: {
298
- x: left - wholeW - p2,
299
- y: top + height
300
- }
301
- };
302
- return bbox;
303
- }
304
-
305
- private _closing = false;
306
- mouseout() {
307
- this._closing = true;
308
- this._tooltipElement.on("mouseover", () => {
309
- this._closing = false;
310
- });
311
- this._tooltipElement.on("mouseout", () => {
312
- this.mouseout();
313
- });
314
- setTimeout(() => {
315
- if (this._closing) {
316
- this.visible(false);
317
- }
318
- }, this.closeDelay());
319
- }
320
-
321
- visible(): boolean;
322
- visible(_: boolean): this;
323
- visible(_?: boolean): boolean | this {
324
- if (!arguments.length) return super.visible();
325
- if (this._arrowElement) {
326
- this._arrowElement.style("visibility", _ ? "visible" : "hidden");
327
- this._tooltipElement.style("visibility", _ ? "visible" : "hidden");
328
- }
329
- super.visible(_);
330
- return this;
331
- }
332
-
333
- exit(domNode, element) {
334
- if (this._arrowElement) {
335
- this._arrowElement.remove();
336
- this._tooltipElement.remove();
337
- }
338
- super.exit(domNode, element);
339
- }
340
- }
341
- HTMLTooltip.prototype._class += " html_HTMLTooltip";
342
-
343
- export interface HTMLTooltip {
344
- padding(): number;
345
- padding(_: number): this;
346
- direction(): Direction;
347
- direction(_: Direction): this;
348
- arrowHeight(): number;
349
- arrowHeight(_: number): this;
350
- arrowWidth(): number;
351
- arrowWidth(_: number): this;
352
- fontColor(): string;
353
- fontColor(_: string): this;
354
- tooltipColor(): string;
355
- tooltipColor(_: string): this;
356
- tooltipWidth(): number;
357
- tooltipWidth(_: number): this;
358
- tooltipWidth_default(_: number);
359
- tooltipHeight(): number;
360
- tooltipHeight(_: number): this;
361
- tooltipHeight_default(_: number);
362
- followCursor(): boolean;
363
- followCursor(_: boolean): this;
364
- enablePointerEvents(): boolean;
365
- enablePointerEvents(_: boolean): this;
366
- closeDelay(): number;
367
- closeDelay(_: number): this;
368
- fitContent(): boolean;
369
- fitContent(_: boolean): this;
370
-
371
- }
372
-
373
- HTMLTooltip.prototype.publish("fitContent", false, "boolean", "If true, tooltip will grow to fit its html content");
374
- HTMLTooltip.prototype.publish("followCursor", false, "boolean", "If true, tooltip will display relative to cursor location");
375
- HTMLTooltip.prototype.publish("closeDelay", 400, "number", "Number of milliseconds to wait before closing tooltip (cancelled on tooltip mouseover event)");
376
- HTMLTooltip.prototype.publish("direction", "n", "set", "Direction in which to display the tooltip", ["n", "s", "e", "w", "ne", "nw", "se", "sw"]);
377
- HTMLTooltip.prototype.publish("padding", 8, "number", "Padding (pixels)");
378
- HTMLTooltip.prototype.publish("arrowWidth", 16, "number", "Width (or height depending on direction) of the tooltip arrow (pixels)");
379
- HTMLTooltip.prototype.publish("arrowHeight", 8, "number", "Height (or width depending on direction) of the tooltip arrow (pixels)");
380
- HTMLTooltip.prototype.publish("fontColor", "#FFF", "html-color", "The default font color for text in the tooltip");
381
- HTMLTooltip.prototype.publish("tooltipColor", "#000000EE", "html-color", "Background color of the tooltip");
382
- HTMLTooltip.prototype.publish("tooltipWidth", 200, "number", "Width of the tooltip (not including arrow) (pixels)");
383
- HTMLTooltip.prototype.publish("tooltipHeight", 200, "number", "Height of the tooltip (not including arrow) (pixels)");
384
- HTMLTooltip.prototype.publish("enablePointerEvents", false, "boolean", "If true, the 'pointer-events: all' style will be used");
1
+ import { HTMLWidget, select as d3Select } from "@hpcc-js/common";
2
+ import { scopedLogger, ScopedLogging } from "@hpcc-js/util";
3
+
4
+ type Direction = "n" | "s" | "e" | "w" | "ne" | "nw" | "se" | "sw";
5
+ type Position = { x: number, y: number };
6
+ type DirectionalBBox = { [key in Direction]: Position; };
7
+
8
+ type Rectangle = { top: number, left: number, width: number, height: number };
9
+ export class HTMLTooltip extends HTMLWidget {
10
+
11
+ public _triggerElement;
12
+ public _contentNode;
13
+ protected _prevContentNode;
14
+
15
+ protected _tooltipElement;
16
+ protected _arrowElement;
17
+ protected _tooltipHTMLCallback = (data?) => "<b>_tooltipHTMLCallback is undefined</b>";
18
+ protected _logger: ScopedLogging = scopedLogger("html/HTMLTooltip");
19
+ constructor() {
20
+ super();
21
+ this.visible(false);
22
+ }
23
+
24
+ tooltipHTML(_: (data?) => string): this {
25
+ this._tooltipHTMLCallback = _;
26
+ return this;
27
+ }
28
+
29
+ tooltipContent(_): this {
30
+ if (!arguments.length) return this._contentNode;
31
+ this._contentNode = _;
32
+ return this;
33
+ }
34
+
35
+ triggerElement(_): this {
36
+ this._triggerElement = _;
37
+ return this;
38
+ }
39
+
40
+ enter(domNode, element) {
41
+ super.enter(domNode, element);
42
+ const body = d3Select("body");
43
+ this._tooltipElement = body.append("div")
44
+ .attr("class", "tooltip-div")
45
+ .style("z-index", "2147483638")
46
+ .style("position", "fixed")
47
+ ;
48
+ this._arrowElement = body.append("div")
49
+ .attr("class", "arrow-div")
50
+ .style("z-index", "2147483638")
51
+ .style("position", "fixed")
52
+ ;
53
+ }
54
+
55
+ update(domNode, element) {
56
+ super.update(domNode, element);
57
+
58
+ if (this._contentNode !== this._prevContentNode) {
59
+ const node = this._tooltipElement.node();
60
+ [...node.querySelectorAll("*")]
61
+ .map(n => n.__data__)
62
+ .filter(n => n)
63
+ .forEach(w => {
64
+ if (typeof w.target === "function") {
65
+ w.target(null);
66
+ }
67
+ if (typeof w.exit === "function") {
68
+ w.exit();
69
+ }
70
+ });
71
+ node.innerHTML = "";
72
+ node.appendChild(this._contentNode);
73
+ this._prevContentNode = this._contentNode;
74
+ }
75
+
76
+ if (this._contentNode) {
77
+ this.onShowContent(this._contentNode);
78
+ } else {
79
+ this._tooltipElement
80
+ .html(() => {
81
+ return this._tooltipHTMLCallback(this.data());
82
+ });
83
+ }
84
+ if (this.fitContent()) {
85
+ this._tooltipElement
86
+ .style("width", "auto")
87
+ .style("height", "auto")
88
+ .style("padding", "0px")
89
+ .style("box-sizing", "content-box")
90
+ ;
91
+ const rect = this._tooltipElement.node().getBoundingClientRect();
92
+ this.tooltipWidth_default(rect.width);
93
+ this.tooltipHeight_default(rect.height);
94
+ }
95
+ this._closing = false;
96
+ this._tooltipElement
97
+ .style("background-color", this.tooltipColor())
98
+ .style("color", this.fontColor())
99
+ .style("width", this.tooltipWidth() + "px")
100
+ .style("height", this.tooltipHeight() + "px")
101
+ .style("opacity", 1)
102
+ .style("padding", this.padding() + "px")
103
+ .style("pointer-events", this.enablePointerEvents() ? "all" : "none")
104
+ .style("box-sizing", "content-box")
105
+ ;
106
+ this._arrowElement
107
+ .style("opacity", 1)
108
+ .style("pointer-events", "none")
109
+ ;
110
+ this.updateTooltipPosition();
111
+ }
112
+
113
+ onShowContent(node) {
114
+
115
+ }
116
+
117
+ protected updateTooltipPosition(): Position {
118
+ const bbox = this.calcReferenceBBox();
119
+ const direction = this.calcTooltipDirection(bbox);
120
+ const box = bbox[direction];
121
+ this._tooltipElement
122
+ .style("top", box.y + "px")
123
+ .style("left", box.x + "px")
124
+ ;
125
+ this.setArrowPosition(box, direction);
126
+ return box;
127
+ }
128
+
129
+ protected calcTooltipDirection(bbox: DirectionalBBox): Direction {
130
+ const directions: Direction[] = Object.keys(bbox) as Direction[];
131
+
132
+ const defaultDirection = this.direction();
133
+ directions.sort((a, b) => a === defaultDirection ? -1 : 1);
134
+ const windowRect = {
135
+ top: 0,
136
+ left: 0,
137
+ width: window.innerWidth,
138
+ height: window.innerHeight
139
+ };
140
+ for (let i = 0; i < directions.length; i++) {
141
+ const tooltipRect = {
142
+ top: bbox[directions[i]].y,
143
+ left: bbox[directions[i]].x,
144
+ width: this.tooltipWidth(),
145
+ height: this.tooltipHeight()
146
+ };
147
+ if (this.rectFits(tooltipRect, windowRect)) {
148
+ return directions[i];
149
+ }
150
+ }
151
+ this._logger.warning(`Tooltip doesn't fit in the window for any of the directions. Defaulting to '${defaultDirection}'`);
152
+ this._logger.debug(windowRect);
153
+ this._logger.debug({
154
+ top: bbox[defaultDirection].y,
155
+ left: bbox[defaultDirection].x,
156
+ width: this.tooltipWidth(),
157
+ height: this.tooltipHeight()
158
+ });
159
+ return defaultDirection;
160
+ }
161
+
162
+ protected rectFits(innerRect: Rectangle, outerRect: Rectangle): boolean {
163
+ return (
164
+ innerRect.top >= outerRect.top &&
165
+ innerRect.left >= outerRect.left &&
166
+ innerRect.width + innerRect.left <= outerRect.width + outerRect.left &&
167
+ innerRect.height + innerRect.top <= outerRect.height + outerRect.top
168
+ );
169
+ }
170
+
171
+ protected setArrowPosition(point: Position, direction: Direction) {
172
+ let top;
173
+ let left;
174
+ let visibleBorderStyle = "border-top-color";
175
+ this._arrowElement
176
+ .style("border", `${this.arrowHeight()}px solid ${this.tooltipColor()}`)
177
+ .style("border-top-color", "transparent")
178
+ .style("border-right-color", "transparent")
179
+ .style("border-bottom-color", "transparent")
180
+ .style("border-left-color", "transparent")
181
+ ;
182
+ switch (direction) {
183
+ case "n":
184
+ top = point.y + this.tooltipHeight() + (this.padding() * 2);
185
+ left = point.x + (this.tooltipWidth() / 2) - (this.arrowWidth() / 2) + this.padding();
186
+ visibleBorderStyle = "border-top-color";
187
+ this._arrowElement
188
+ .style("border-top-width", `${this.arrowHeight()}px`)
189
+ .style("border-bottom-width", "0px")
190
+ .style("border-left-width", `${this.arrowWidth() / 2}px`)
191
+ .style("border-right-width", `${this.arrowWidth() / 2}px`)
192
+ ;
193
+ break;
194
+ case "s":
195
+ top = point.y - this.arrowHeight();
196
+ left = point.x + this.padding() + (this.tooltipWidth() / 2) - (this.arrowWidth() / 2);
197
+ visibleBorderStyle = "border-bottom-color";
198
+ this._arrowElement
199
+ .style("border-top-width", "0px")
200
+ .style("border-bottom-width", `${this.arrowHeight()}px`)
201
+ .style("border-left-width", `${this.arrowWidth() / 2}px`)
202
+ .style("border-right-width", `${this.arrowWidth() / 2}px`)
203
+ ;
204
+ break;
205
+ case "e":
206
+ top = point.y + (this.tooltipHeight() / 2) + this.padding() - (this.arrowWidth() / 2);
207
+ left = point.x - this.arrowHeight();
208
+ visibleBorderStyle = "border-right-color";
209
+ this._arrowElement
210
+ .style("border-top-width", `${this.arrowWidth() / 2}px`)
211
+ .style("border-bottom-width", `${this.arrowWidth() / 2}px`)
212
+ .style("border-left-width", "0px")
213
+ .style("border-right-width", `${this.arrowHeight()}px`)
214
+ ;
215
+ break;
216
+ case "w":
217
+ top = point.y + (this.tooltipHeight() / 2) - (this.arrowWidth() / 2) + this.padding();
218
+ left = point.x + this.tooltipWidth() + (this.padding() * 2);
219
+ visibleBorderStyle = "border-left-color";
220
+ this._arrowElement
221
+ .style("border-top-width", `${this.arrowWidth() / 2}px`)
222
+ .style("border-bottom-width", `${this.arrowWidth() / 2}px`)
223
+ .style("border-left-width", `${this.arrowHeight()}px`)
224
+ .style("border-right-width", "0px")
225
+ ;
226
+ break;
227
+ }
228
+ if (typeof top !== "undefined" && typeof left !== "undefined") {
229
+ this._arrowElement
230
+ .style("top", top + "px")
231
+ .style("left", left + "px")
232
+ .style(visibleBorderStyle, this.tooltipColor())
233
+ .style("opacity", 1)
234
+ ;
235
+ } else {
236
+ this._arrowElement
237
+ .style("opacity", 0)
238
+ ;
239
+ }
240
+ return point;
241
+ }
242
+
243
+ protected getReferenceNode() {
244
+ if (!this._triggerElement) {
245
+ return this.element().node().parentNode.parentNode;
246
+ }
247
+ return this._triggerElement.node();
248
+ }
249
+ public _cursorLoc;
250
+ protected calcReferenceBBox() {
251
+ const node = this.getReferenceNode();
252
+ let { top, left, width, height } = node.getBoundingClientRect();
253
+ const wholeW = this.tooltipWidth();
254
+ const wholeH = this.tooltipHeight();
255
+ const halfW = wholeW / 2;
256
+ const halfH = wholeH / 2;
257
+ const arrowH = this.arrowHeight();
258
+ const p = this.padding();
259
+ const p2 = p * 2;
260
+
261
+ if (this.followCursor() && this._cursorLoc) {
262
+
263
+ left = this._cursorLoc[0];
264
+ top = this._cursorLoc[1];
265
+ width = 1;
266
+ height = 1;
267
+ }
268
+ const bbox = {
269
+ n: {
270
+ x: left + (width / 2) - halfW - p,
271
+ y: top - wholeH - arrowH - p2
272
+ },
273
+ e: {
274
+ x: left + width + arrowH,
275
+ y: top + (height / 2) - halfH - p
276
+ },
277
+ s: {
278
+ x: left + (width / 2) - halfW - p,
279
+ y: top + height + arrowH
280
+ },
281
+ w: {
282
+ x: left - wholeW - arrowH - p2,
283
+ y: top + (height / 2) - halfH - p
284
+ },
285
+ nw: {
286
+ x: left - wholeW - p2,
287
+ y: top - wholeH - p2
288
+ },
289
+ ne: {
290
+ x: left + width,
291
+ y: top - wholeH - p2
292
+ },
293
+ se: {
294
+ x: left + width,
295
+ y: top + height
296
+ },
297
+ sw: {
298
+ x: left - wholeW - p2,
299
+ y: top + height
300
+ }
301
+ };
302
+ return bbox;
303
+ }
304
+
305
+ private _closing = false;
306
+ mouseout() {
307
+ this._closing = true;
308
+ this._tooltipElement.on("mouseover", () => {
309
+ this._closing = false;
310
+ });
311
+ this._tooltipElement.on("mouseout", () => {
312
+ this.mouseout();
313
+ });
314
+ setTimeout(() => {
315
+ if (this._closing) {
316
+ this.visible(false);
317
+ }
318
+ }, this.closeDelay());
319
+ }
320
+
321
+ visible(): boolean;
322
+ visible(_: boolean): this;
323
+ visible(_?: boolean): boolean | this {
324
+ if (!arguments.length) return super.visible();
325
+ if (this._arrowElement) {
326
+ this._arrowElement.style("visibility", _ ? "visible" : "hidden");
327
+ this._tooltipElement.style("visibility", _ ? "visible" : "hidden");
328
+ }
329
+ super.visible(_);
330
+ return this;
331
+ }
332
+
333
+ exit(domNode, element) {
334
+ if (this._arrowElement) {
335
+ this._arrowElement.remove();
336
+ this._tooltipElement.remove();
337
+ }
338
+ super.exit(domNode, element);
339
+ }
340
+ }
341
+ HTMLTooltip.prototype._class += " html_HTMLTooltip";
342
+
343
+ export interface HTMLTooltip {
344
+ padding(): number;
345
+ padding(_: number): this;
346
+ direction(): Direction;
347
+ direction(_: Direction): this;
348
+ arrowHeight(): number;
349
+ arrowHeight(_: number): this;
350
+ arrowWidth(): number;
351
+ arrowWidth(_: number): this;
352
+ fontColor(): string;
353
+ fontColor(_: string): this;
354
+ tooltipColor(): string;
355
+ tooltipColor(_: string): this;
356
+ tooltipWidth(): number;
357
+ tooltipWidth(_: number): this;
358
+ tooltipWidth_default(_: number);
359
+ tooltipHeight(): number;
360
+ tooltipHeight(_: number): this;
361
+ tooltipHeight_default(_: number);
362
+ followCursor(): boolean;
363
+ followCursor(_: boolean): this;
364
+ enablePointerEvents(): boolean;
365
+ enablePointerEvents(_: boolean): this;
366
+ closeDelay(): number;
367
+ closeDelay(_: number): this;
368
+ fitContent(): boolean;
369
+ fitContent(_: boolean): this;
370
+
371
+ }
372
+
373
+ HTMLTooltip.prototype.publish("fitContent", false, "boolean", "If true, tooltip will grow to fit its html content");
374
+ HTMLTooltip.prototype.publish("followCursor", false, "boolean", "If true, tooltip will display relative to cursor location");
375
+ HTMLTooltip.prototype.publish("closeDelay", 400, "number", "Number of milliseconds to wait before closing tooltip (cancelled on tooltip mouseover event)");
376
+ HTMLTooltip.prototype.publish("direction", "n", "set", "Direction in which to display the tooltip", ["n", "s", "e", "w", "ne", "nw", "se", "sw"]);
377
+ HTMLTooltip.prototype.publish("padding", 8, "number", "Padding (pixels)");
378
+ HTMLTooltip.prototype.publish("arrowWidth", 16, "number", "Width (or height depending on direction) of the tooltip arrow (pixels)");
379
+ HTMLTooltip.prototype.publish("arrowHeight", 8, "number", "Height (or width depending on direction) of the tooltip arrow (pixels)");
380
+ HTMLTooltip.prototype.publish("fontColor", "#FFF", "html-color", "The default font color for text in the tooltip");
381
+ HTMLTooltip.prototype.publish("tooltipColor", "#000000EE", "html-color", "Background color of the tooltip");
382
+ HTMLTooltip.prototype.publish("tooltipWidth", 200, "number", "Width of the tooltip (not including arrow) (pixels)");
383
+ HTMLTooltip.prototype.publish("tooltipHeight", 200, "number", "Height of the tooltip (not including arrow) (pixels)");
384
+ HTMLTooltip.prototype.publish("enablePointerEvents", false, "boolean", "If true, the 'pointer-events: all' style will be used");