@hpcc-js/api 3.4.9 → 3.4.11

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.
package/src/Tooltip.ts CHANGED
@@ -1,384 +1,384 @@
1
- // Based on https://github.com/GordonSmith/d3-tip forked from https://github.com/Caged/d3-tip
2
-
3
- import { map } from "d3-collection";
4
- import { select, selection } from "d3-selection";
5
-
6
- export function tip() {
7
- let direction = d3TipDirection;
8
- let offset = d3TipOffset;
9
- let html = d3TipHTML;
10
- let rootElement = functor(document.body);
11
- let node = initNode();
12
- let svg = null;
13
- let point = null;
14
- let target = null;
15
-
16
- const tip: any = function (vis) {
17
- svg = getSVGNode(vis);
18
- if (!svg) return;
19
- point = svg.createSVGPoint();
20
- const re = rootElement();
21
- if (!re) return;
22
- if (!node) return;
23
- re.appendChild(node);
24
- };
25
-
26
- // Public - show the tooltip on the screen
27
- //
28
- // Returns a tip
29
- tip.show = function (d, idx, arr) {
30
- target = arr[idx];
31
- const args = Array.prototype.slice.call(arguments) as [];
32
- const content = html.apply(this, args);
33
- if (content === null) {
34
- return tip;
35
- }
36
- const poffset = offset.apply(this, args);
37
- const nodel = getNodeEl();
38
- let i = directions.length;
39
- let coords;
40
- const root_bbox = rootElement().getBoundingClientRect();
41
- nodel.html(content)
42
- .style("opacity", 1).style("pointer-events", "all");
43
-
44
- while (i--) nodel.classed(directions[i], false);
45
- let placement_success = false;
46
- const placement_overflow = {};
47
- let least_overflow_direction = directions[0];
48
- for (let i = 0; i < directions.length; i++) {
49
- placement_success = _placement_attempt(directions[i]);
50
- if (placement_success) break;
51
- }
52
- if (!placement_success) {
53
- nodel.classed("notick", true);
54
- const top_offset = _vertical_adjustment(placement_overflow[least_overflow_direction]);
55
- const left_offset = _horizontal_adjustment(placement_overflow[least_overflow_direction]);
56
- _placement_attempt(least_overflow_direction, top_offset, left_offset);
57
- } else {
58
- nodel.classed("notick", false);
59
- }
60
- return tip;
61
-
62
- function _horizontal_adjustment(overflow_obj) {
63
- if (overflow_obj.left > overflow_obj.right) {
64
- return overflow_obj.left > 0 ? -overflow_obj.left : 0;
65
- } else {
66
- return overflow_obj.right > 0 ? overflow_obj.right : 0;
67
- }
68
- }
69
- function _vertical_adjustment(overflow_obj) {
70
- if (overflow_obj.top > overflow_obj.bottom) {
71
- return overflow_obj.top > 0 ? -overflow_obj.top : 0;
72
- } else {
73
- return overflow_obj.bottom;
74
- }
75
- }
76
-
77
- function _placement_attempt(this: any, _dir, _top_offset?, _left_offset?) {
78
- _top_offset = _top_offset ? _top_offset : 0;
79
- _left_offset = _left_offset ? _left_offset : 0;
80
- nodel.style("white-space", "nowrap");
81
- coords = directionCallbacks.get(_dir).apply(this);
82
- nodel.classed(_dir, true)
83
- .style("top", (coords.top + poffset[0] - _top_offset) + "px")
84
- .style("left", (coords.left + poffset[1] - _left_offset) + "px");
85
- const nodel_bbox = nodel.node().getBoundingClientRect();
86
- const ret = nodel_bbox.top > root_bbox.top
87
- && nodel_bbox.left > root_bbox.left
88
- && nodel_bbox.bottom < root_bbox.bottom
89
- && nodel_bbox.right < root_bbox.right
90
- ;
91
- placement_overflow[_dir] = {
92
- top: root_bbox.top - nodel_bbox.top,
93
- right: nodel_bbox.right - root_bbox.right,
94
- bottom: nodel_bbox.bottom - root_bbox.bottom,
95
- left: root_bbox.left - nodel_bbox.left
96
- };
97
- nodel.style("white-space", "normal");
98
- placement_overflow[_dir].total_overflow = Object.keys(placement_overflow[_dir])
99
- .filter(side => placement_overflow[_dir][side] > 0)
100
- .reduce((sum, side) => {
101
- const side_overflow = placement_overflow[_dir][side];
102
- return sum + side_overflow;
103
- }, 0);
104
- if (placement_overflow[least_overflow_direction].total_overflow > placement_overflow[_dir].total_overflow) {
105
- least_overflow_direction = _dir;
106
- }
107
- if (!ret) {
108
- nodel.classed(_dir, false);
109
- }
110
- return ret;
111
- }
112
- };
113
-
114
- // Public - hide the tooltip
115
- //
116
- // Returns a tip
117
- tip.hide = function () {
118
- const nodel = getNodeEl();
119
- nodel.style("opacity", 0).style("pointer-events", "none");
120
- return tip;
121
- };
122
-
123
- // Public: Proxy attr calls to the d3 tip container.
124
- // Sets or gets attribute value.
125
- //
126
- // n - name of the attribute
127
- // v - value of the attribute
128
- //
129
- // Returns tip or attribute value
130
- tip.attr = function (n, v) {
131
- if (arguments.length < 2 && typeof n === "string") {
132
- return getNodeEl().attr(n);
133
- }
134
-
135
- const args = Array.prototype.slice.call(arguments);
136
- selection.prototype.attr.apply(getNodeEl(), args);
137
- return tip;
138
- };
139
-
140
- // Public: Proxy style calls to the d3 tip container.
141
- // Sets or gets a style value.
142
- //
143
- // n - name of the property
144
- // v - value of the property
145
- //
146
- // Returns tip or style property value
147
- tip.style = function (n, v) {
148
- if (arguments.length < 2 && typeof n === "string") {
149
- return getNodeEl().style(n);
150
- }
151
-
152
- const args = Array.prototype.slice.call(arguments);
153
- selection.prototype.style.apply(getNodeEl(), args);
154
- return tip;
155
- };
156
-
157
- // Public: Set or get the direction of the tooltip
158
- //
159
- // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
160
- // sw(southwest), ne(northeast) or se(southeast)
161
- //
162
- // Returns tip or direction
163
- tip.direction = function (v) {
164
- if (!arguments.length) return direction;
165
- direction = v == null ? v : functor(v);
166
-
167
- return tip;
168
- };
169
-
170
- // Public: Sets or gets the offset of the tip
171
- //
172
- // v - Array of [x, y] offset
173
- //
174
- // Returns offset or
175
- tip.offset = function (v) {
176
- if (!arguments.length) return offset;
177
- offset = v == null ? v : functor(v);
178
-
179
- return tip;
180
- };
181
-
182
- // Public: sets or gets the html value of the tooltip
183
- //
184
- // v - String value of the tip
185
- //
186
- // Returns html value or tip
187
- tip.html = function (v) {
188
- if (!arguments.length) return html;
189
- html = v == null ? v : functor(v);
190
-
191
- return tip;
192
- };
193
-
194
- // Public: sets or gets the root element anchor of the tooltip
195
- //
196
- // v - root element of the tooltip
197
- //
198
- // Returns root node of tip
199
- tip.rootElement = function (v) {
200
- if (!arguments.length) return rootElement;
201
- rootElement = functor(v);
202
-
203
- return tip;
204
- };
205
-
206
- // Public: destroys the tooltip and removes it from the DOM
207
- //
208
- // Returns a tip
209
- tip.destroy = function () {
210
- if (node) {
211
- getNodeEl().remove();
212
- node = null;
213
- }
214
- return tip;
215
- };
216
-
217
- function d3TipDirection() { return "n"; }
218
- function d3TipOffset() { return [0, 0]; }
219
- function d3TipHTML() { return " "; }
220
-
221
- const directionCallbacks = map({
222
- n: directionNorth,
223
- s: directionSouth,
224
- e: directionEast,
225
- w: directionWest,
226
- nw: directionNorthWest,
227
- ne: directionNorthEast,
228
- sw: directionSouthWest,
229
- se: directionSouthEast
230
- });
231
- const directions = directionCallbacks.keys();
232
-
233
- function directionNorth() {
234
- const bbox = getScreenBBox(window);
235
- return {
236
- top: bbox.n.y - node.offsetHeight,
237
- left: bbox.n.x - node.offsetWidth / 2
238
- };
239
- }
240
-
241
- function directionSouth() {
242
- const bbox = getScreenBBox(window);
243
- return {
244
- top: bbox.s.y + 8,
245
- left: bbox.s.x - node.offsetWidth / 2
246
- };
247
- }
248
-
249
- function directionEast() {
250
- const bbox = getScreenBBox(window);
251
- return {
252
- top: bbox.e.y - node.offsetHeight / 2,
253
- left: bbox.e.x + 8
254
- };
255
- }
256
-
257
- function directionWest() {
258
- const bbox = getScreenBBox(window);
259
- return {
260
- top: bbox.w.y - node.offsetHeight / 2,
261
- left: bbox.w.x - node.offsetWidth - 8
262
- };
263
- }
264
-
265
- function directionNorthWest() {
266
- const bbox = getScreenBBox(window);
267
- return {
268
- top: bbox.nw.y - node.offsetHeight,
269
- left: bbox.nw.x - node.offsetWidth
270
- };
271
- }
272
-
273
- function directionNorthEast() {
274
- const bbox = getScreenBBox(window);
275
- return {
276
- top: bbox.ne.y - node.offsetHeight,
277
- left: bbox.ne.x
278
- };
279
- }
280
-
281
- function directionSouthWest() {
282
- const bbox = getScreenBBox(window);
283
- return {
284
- top: bbox.sw.y,
285
- left: bbox.sw.x - node.offsetWidth
286
- };
287
- }
288
-
289
- function directionSouthEast() {
290
- const bbox = getScreenBBox(window);
291
- return {
292
- top: bbox.se.y,
293
- left: bbox.se.x
294
- };
295
- }
296
-
297
- function initNode() {
298
- const div = select(document.createElement("div"));
299
- div
300
- .attr("class", "d3-tip")
301
- .style("position", "absolute")
302
- .style("top", "0px")
303
- .style("opacity", 0)
304
- .style("pointer-events", "none")
305
- .style("box-sizing", "border-box");
306
-
307
- return div.node();
308
- }
309
-
310
- function getSVGNode(element) {
311
- const svgNode = element.node();
312
- if (!svgNode) return null;
313
- if (svgNode.tagName.toLowerCase() === "svg") return svgNode;
314
- return svgNode.ownerSVGElement;
315
- }
316
-
317
- function getNodeEl() {
318
- if (node == null) {
319
- node = initNode();
320
- // re-add node to DOM
321
- rootElement().appendChild(node);
322
- }
323
- return select(node);
324
- }
325
-
326
- // Private - gets the screen coordinates of a shape
327
- //
328
- // Given a shape on the screen, will return an SVGPoint for the directions
329
- // n(north), s(south), e(east), w(west), ne(northeast), se(southeast),
330
- // nw(northwest), sw(southwest).
331
- //
332
- // +-+-+
333
- // | |
334
- // + +
335
- // | |
336
- // +-+-+
337
- //
338
- // Returns an Object {n, s, e, w, nw, sw, ne, se}
339
- function getScreenBBox(targetShape) {
340
- let targetel = target || targetShape;
341
-
342
- while (targetel.getCTM == null && targetel.parentNode != null) {
343
- targetel = targetel.parentNode;
344
- }
345
-
346
- const bbox: any = {};
347
- const matrix = targetel.getCTM();
348
- const tbbox = targetel.getBBox();
349
- const width = tbbox.width;
350
- const height = tbbox.height;
351
- const x = tbbox.x;
352
- const y = tbbox.y;
353
-
354
- point.x = x;
355
- point.y = y;
356
- bbox.nw = point.matrixTransform(matrix);
357
- point.x += width;
358
- bbox.ne = point.matrixTransform(matrix);
359
- point.y += height;
360
- bbox.se = point.matrixTransform(matrix);
361
- point.x -= width;
362
- bbox.sw = point.matrixTransform(matrix);
363
- point.y -= height / 2;
364
- bbox.w = point.matrixTransform(matrix);
365
- point.x += width;
366
- bbox.e = point.matrixTransform(matrix);
367
- point.x -= width / 2;
368
- point.y -= height / 2;
369
- bbox.n = point.matrixTransform(matrix);
370
- point.y += height;
371
- bbox.s = point.matrixTransform(matrix);
372
-
373
- return bbox;
374
- }
375
-
376
- // Private - replace D3JS 3.X d3.functor() function
377
- function functor(v) {
378
- return typeof v === "function" ? v : function () {
379
- return v;
380
- };
381
- }
382
-
383
- return tip;
384
- }
1
+ // Based on https://github.com/GordonSmith/d3-tip forked from https://github.com/Caged/d3-tip
2
+
3
+ import { map } from "d3-collection";
4
+ import { select, selection } from "d3-selection";
5
+
6
+ export function tip() {
7
+ let direction = d3TipDirection;
8
+ let offset = d3TipOffset;
9
+ let html = d3TipHTML;
10
+ let rootElement = functor(document.body);
11
+ let node = initNode();
12
+ let svg = null;
13
+ let point = null;
14
+ let target = null;
15
+
16
+ const tip: any = function (vis) {
17
+ svg = getSVGNode(vis);
18
+ if (!svg) return;
19
+ point = svg.createSVGPoint();
20
+ const re = rootElement();
21
+ if (!re) return;
22
+ if (!node) return;
23
+ re.appendChild(node);
24
+ };
25
+
26
+ // Public - show the tooltip on the screen
27
+ //
28
+ // Returns a tip
29
+ tip.show = function (d, idx, arr) {
30
+ target = arr[idx];
31
+ const args = Array.prototype.slice.call(arguments) as [];
32
+ const content = html.apply(this, args);
33
+ if (content === null) {
34
+ return tip;
35
+ }
36
+ const poffset = offset.apply(this, args);
37
+ const nodel = getNodeEl();
38
+ let i = directions.length;
39
+ let coords;
40
+ const root_bbox = rootElement().getBoundingClientRect();
41
+ nodel.html(content)
42
+ .style("opacity", 1).style("pointer-events", "all");
43
+
44
+ while (i--) nodel.classed(directions[i], false);
45
+ let placement_success = false;
46
+ const placement_overflow = {};
47
+ let least_overflow_direction = directions[0];
48
+ for (let i = 0; i < directions.length; i++) {
49
+ placement_success = _placement_attempt(directions[i]);
50
+ if (placement_success) break;
51
+ }
52
+ if (!placement_success) {
53
+ nodel.classed("notick", true);
54
+ const top_offset = _vertical_adjustment(placement_overflow[least_overflow_direction]);
55
+ const left_offset = _horizontal_adjustment(placement_overflow[least_overflow_direction]);
56
+ _placement_attempt(least_overflow_direction, top_offset, left_offset);
57
+ } else {
58
+ nodel.classed("notick", false);
59
+ }
60
+ return tip;
61
+
62
+ function _horizontal_adjustment(overflow_obj) {
63
+ if (overflow_obj.left > overflow_obj.right) {
64
+ return overflow_obj.left > 0 ? -overflow_obj.left : 0;
65
+ } else {
66
+ return overflow_obj.right > 0 ? overflow_obj.right : 0;
67
+ }
68
+ }
69
+ function _vertical_adjustment(overflow_obj) {
70
+ if (overflow_obj.top > overflow_obj.bottom) {
71
+ return overflow_obj.top > 0 ? -overflow_obj.top : 0;
72
+ } else {
73
+ return overflow_obj.bottom;
74
+ }
75
+ }
76
+
77
+ function _placement_attempt(this: any, _dir, _top_offset?, _left_offset?) {
78
+ _top_offset = _top_offset ? _top_offset : 0;
79
+ _left_offset = _left_offset ? _left_offset : 0;
80
+ nodel.style("white-space", "nowrap");
81
+ coords = directionCallbacks.get(_dir).apply(this);
82
+ nodel.classed(_dir, true)
83
+ .style("top", (coords.top + poffset[0] - _top_offset) + "px")
84
+ .style("left", (coords.left + poffset[1] - _left_offset) + "px");
85
+ const nodel_bbox = nodel.node().getBoundingClientRect();
86
+ const ret = nodel_bbox.top > root_bbox.top
87
+ && nodel_bbox.left > root_bbox.left
88
+ && nodel_bbox.bottom < root_bbox.bottom
89
+ && nodel_bbox.right < root_bbox.right
90
+ ;
91
+ placement_overflow[_dir] = {
92
+ top: root_bbox.top - nodel_bbox.top,
93
+ right: nodel_bbox.right - root_bbox.right,
94
+ bottom: nodel_bbox.bottom - root_bbox.bottom,
95
+ left: root_bbox.left - nodel_bbox.left
96
+ };
97
+ nodel.style("white-space", "normal");
98
+ placement_overflow[_dir].total_overflow = Object.keys(placement_overflow[_dir])
99
+ .filter(side => placement_overflow[_dir][side] > 0)
100
+ .reduce((sum, side) => {
101
+ const side_overflow = placement_overflow[_dir][side];
102
+ return sum + side_overflow;
103
+ }, 0);
104
+ if (placement_overflow[least_overflow_direction].total_overflow > placement_overflow[_dir].total_overflow) {
105
+ least_overflow_direction = _dir;
106
+ }
107
+ if (!ret) {
108
+ nodel.classed(_dir, false);
109
+ }
110
+ return ret;
111
+ }
112
+ };
113
+
114
+ // Public - hide the tooltip
115
+ //
116
+ // Returns a tip
117
+ tip.hide = function () {
118
+ const nodel = getNodeEl();
119
+ nodel.style("opacity", 0).style("pointer-events", "none");
120
+ return tip;
121
+ };
122
+
123
+ // Public: Proxy attr calls to the d3 tip container.
124
+ // Sets or gets attribute value.
125
+ //
126
+ // n - name of the attribute
127
+ // v - value of the attribute
128
+ //
129
+ // Returns tip or attribute value
130
+ tip.attr = function (n, v) {
131
+ if (arguments.length < 2 && typeof n === "string") {
132
+ return getNodeEl().attr(n);
133
+ }
134
+
135
+ const args = Array.prototype.slice.call(arguments);
136
+ selection.prototype.attr.apply(getNodeEl(), args);
137
+ return tip;
138
+ };
139
+
140
+ // Public: Proxy style calls to the d3 tip container.
141
+ // Sets or gets a style value.
142
+ //
143
+ // n - name of the property
144
+ // v - value of the property
145
+ //
146
+ // Returns tip or style property value
147
+ tip.style = function (n, v) {
148
+ if (arguments.length < 2 && typeof n === "string") {
149
+ return getNodeEl().style(n);
150
+ }
151
+
152
+ const args = Array.prototype.slice.call(arguments);
153
+ selection.prototype.style.apply(getNodeEl(), args);
154
+ return tip;
155
+ };
156
+
157
+ // Public: Set or get the direction of the tooltip
158
+ //
159
+ // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
160
+ // sw(southwest), ne(northeast) or se(southeast)
161
+ //
162
+ // Returns tip or direction
163
+ tip.direction = function (v) {
164
+ if (!arguments.length) return direction;
165
+ direction = v == null ? v : functor(v);
166
+
167
+ return tip;
168
+ };
169
+
170
+ // Public: Sets or gets the offset of the tip
171
+ //
172
+ // v - Array of [x, y] offset
173
+ //
174
+ // Returns offset or
175
+ tip.offset = function (v) {
176
+ if (!arguments.length) return offset;
177
+ offset = v == null ? v : functor(v);
178
+
179
+ return tip;
180
+ };
181
+
182
+ // Public: sets or gets the html value of the tooltip
183
+ //
184
+ // v - String value of the tip
185
+ //
186
+ // Returns html value or tip
187
+ tip.html = function (v) {
188
+ if (!arguments.length) return html;
189
+ html = v == null ? v : functor(v);
190
+
191
+ return tip;
192
+ };
193
+
194
+ // Public: sets or gets the root element anchor of the tooltip
195
+ //
196
+ // v - root element of the tooltip
197
+ //
198
+ // Returns root node of tip
199
+ tip.rootElement = function (v) {
200
+ if (!arguments.length) return rootElement;
201
+ rootElement = functor(v);
202
+
203
+ return tip;
204
+ };
205
+
206
+ // Public: destroys the tooltip and removes it from the DOM
207
+ //
208
+ // Returns a tip
209
+ tip.destroy = function () {
210
+ if (node) {
211
+ getNodeEl().remove();
212
+ node = null;
213
+ }
214
+ return tip;
215
+ };
216
+
217
+ function d3TipDirection() { return "n"; }
218
+ function d3TipOffset() { return [0, 0]; }
219
+ function d3TipHTML() { return " "; }
220
+
221
+ const directionCallbacks = map({
222
+ n: directionNorth,
223
+ s: directionSouth,
224
+ e: directionEast,
225
+ w: directionWest,
226
+ nw: directionNorthWest,
227
+ ne: directionNorthEast,
228
+ sw: directionSouthWest,
229
+ se: directionSouthEast
230
+ });
231
+ const directions = directionCallbacks.keys();
232
+
233
+ function directionNorth() {
234
+ const bbox = getScreenBBox(window);
235
+ return {
236
+ top: bbox.n.y - node.offsetHeight,
237
+ left: bbox.n.x - node.offsetWidth / 2
238
+ };
239
+ }
240
+
241
+ function directionSouth() {
242
+ const bbox = getScreenBBox(window);
243
+ return {
244
+ top: bbox.s.y + 8,
245
+ left: bbox.s.x - node.offsetWidth / 2
246
+ };
247
+ }
248
+
249
+ function directionEast() {
250
+ const bbox = getScreenBBox(window);
251
+ return {
252
+ top: bbox.e.y - node.offsetHeight / 2,
253
+ left: bbox.e.x + 8
254
+ };
255
+ }
256
+
257
+ function directionWest() {
258
+ const bbox = getScreenBBox(window);
259
+ return {
260
+ top: bbox.w.y - node.offsetHeight / 2,
261
+ left: bbox.w.x - node.offsetWidth - 8
262
+ };
263
+ }
264
+
265
+ function directionNorthWest() {
266
+ const bbox = getScreenBBox(window);
267
+ return {
268
+ top: bbox.nw.y - node.offsetHeight,
269
+ left: bbox.nw.x - node.offsetWidth
270
+ };
271
+ }
272
+
273
+ function directionNorthEast() {
274
+ const bbox = getScreenBBox(window);
275
+ return {
276
+ top: bbox.ne.y - node.offsetHeight,
277
+ left: bbox.ne.x
278
+ };
279
+ }
280
+
281
+ function directionSouthWest() {
282
+ const bbox = getScreenBBox(window);
283
+ return {
284
+ top: bbox.sw.y,
285
+ left: bbox.sw.x - node.offsetWidth
286
+ };
287
+ }
288
+
289
+ function directionSouthEast() {
290
+ const bbox = getScreenBBox(window);
291
+ return {
292
+ top: bbox.se.y,
293
+ left: bbox.se.x
294
+ };
295
+ }
296
+
297
+ function initNode() {
298
+ const div = select(document.createElement("div"));
299
+ div
300
+ .attr("class", "d3-tip")
301
+ .style("position", "absolute")
302
+ .style("top", "0px")
303
+ .style("opacity", 0)
304
+ .style("pointer-events", "none")
305
+ .style("box-sizing", "border-box");
306
+
307
+ return div.node();
308
+ }
309
+
310
+ function getSVGNode(element) {
311
+ const svgNode = element.node();
312
+ if (!svgNode) return null;
313
+ if (svgNode.tagName.toLowerCase() === "svg") return svgNode;
314
+ return svgNode.ownerSVGElement;
315
+ }
316
+
317
+ function getNodeEl() {
318
+ if (node == null) {
319
+ node = initNode();
320
+ // re-add node to DOM
321
+ rootElement().appendChild(node);
322
+ }
323
+ return select(node);
324
+ }
325
+
326
+ // Private - gets the screen coordinates of a shape
327
+ //
328
+ // Given a shape on the screen, will return an SVGPoint for the directions
329
+ // n(north), s(south), e(east), w(west), ne(northeast), se(southeast),
330
+ // nw(northwest), sw(southwest).
331
+ //
332
+ // +-+-+
333
+ // | |
334
+ // + +
335
+ // | |
336
+ // +-+-+
337
+ //
338
+ // Returns an Object {n, s, e, w, nw, sw, ne, se}
339
+ function getScreenBBox(targetShape) {
340
+ let targetel = target || targetShape;
341
+
342
+ while (targetel.getCTM == null && targetel.parentNode != null) {
343
+ targetel = targetel.parentNode;
344
+ }
345
+
346
+ const bbox: any = {};
347
+ const matrix = targetel.getCTM();
348
+ const tbbox = targetel.getBBox();
349
+ const width = tbbox.width;
350
+ const height = tbbox.height;
351
+ const x = tbbox.x;
352
+ const y = tbbox.y;
353
+
354
+ point.x = x;
355
+ point.y = y;
356
+ bbox.nw = point.matrixTransform(matrix);
357
+ point.x += width;
358
+ bbox.ne = point.matrixTransform(matrix);
359
+ point.y += height;
360
+ bbox.se = point.matrixTransform(matrix);
361
+ point.x -= width;
362
+ bbox.sw = point.matrixTransform(matrix);
363
+ point.y -= height / 2;
364
+ bbox.w = point.matrixTransform(matrix);
365
+ point.x += width;
366
+ bbox.e = point.matrixTransform(matrix);
367
+ point.x -= width / 2;
368
+ point.y -= height / 2;
369
+ bbox.n = point.matrixTransform(matrix);
370
+ point.y += height;
371
+ bbox.s = point.matrixTransform(matrix);
372
+
373
+ return bbox;
374
+ }
375
+
376
+ // Private - replace D3JS 3.X d3.functor() function
377
+ function functor(v) {
378
+ return typeof v === "function" ? v : function () {
379
+ return v;
380
+ };
381
+ }
382
+
383
+ return tip;
384
+ }