@slickgrid-universal/custom-tooltip-plugin 4.6.0 → 4.7.0
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/dist/cjs/slickCustomTooltip.js +78 -32
- package/dist/cjs/slickCustomTooltip.js.map +1 -1
- package/dist/esm/slickCustomTooltip.js +78 -32
- package/dist/esm/slickCustomTooltip.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/slickCustomTooltip.d.ts +11 -3
- package/dist/types/slickCustomTooltip.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/slickCustomTooltip.ts +84 -35
|
@@ -29,13 +29,20 @@ export declare class SlickCustomTooltip {
|
|
|
29
29
|
name: 'CustomTooltip';
|
|
30
30
|
protected _addonOptions?: CustomTooltipOption;
|
|
31
31
|
protected _cellAddonOptions?: CustomTooltipOption;
|
|
32
|
-
protected _cellNodeElm?:
|
|
32
|
+
protected _cellNodeElm?: HTMLElement;
|
|
33
33
|
protected _cellType: CellType;
|
|
34
34
|
protected _cancellablePromise?: CancellablePromiseWrapper;
|
|
35
35
|
protected _observable$?: Subscription;
|
|
36
36
|
protected _rxjs?: RxJsFacade | null;
|
|
37
37
|
protected _sharedService?: SharedService | null;
|
|
38
|
+
protected _tooltipBodyElm?: HTMLDivElement;
|
|
38
39
|
protected _tooltipElm?: HTMLDivElement;
|
|
40
|
+
protected _mousePosition: {
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
};
|
|
44
|
+
protected _mouseTarget?: HTMLElement | null;
|
|
45
|
+
protected _hasMultipleTooltips: boolean;
|
|
39
46
|
protected _defaultOptions: CustomTooltipOption<any>;
|
|
40
47
|
protected _grid: SlickGrid;
|
|
41
48
|
protected _eventHandler: SlickEventHandler;
|
|
@@ -43,6 +50,7 @@ export declare class SlickCustomTooltip {
|
|
|
43
50
|
get addonOptions(): CustomTooltipOption | undefined;
|
|
44
51
|
get cancellablePromise(): CancellablePromiseWrapper<any> | undefined;
|
|
45
52
|
get cellAddonOptions(): CustomTooltipOption | undefined;
|
|
53
|
+
get bodyClassName(): string;
|
|
46
54
|
get className(): string;
|
|
47
55
|
get dataView(): CustomDataView;
|
|
48
56
|
/** Getter for the Grid Options pulled through the Grid Object */
|
|
@@ -70,8 +78,8 @@ export declare class SlickCustomTooltip {
|
|
|
70
78
|
cell: number;
|
|
71
79
|
}, value: any, columnDef: Column, dataContext: any): void;
|
|
72
80
|
/** depending on the selector type, execute the necessary handler code */
|
|
73
|
-
protected
|
|
74
|
-
protected
|
|
81
|
+
protected handleOnHeaderMouseOverByType(event: SlickEventData, args: any, selector: CellType): void;
|
|
82
|
+
protected handleOnMouseOver(event: SlickEventData): Promise<void>;
|
|
75
83
|
/**
|
|
76
84
|
* Parse the Custom Formatter (when provided) or return directly the text when it is already a string.
|
|
77
85
|
* We will also sanitize the text in both cases before returning it so that it can be used safely.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slickCustomTooltip.d.ts","sourceRoot":"","sources":["../../src/slickCustomTooltip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,SAAS,EAGT,UAAU,EAEV,UAAU,EACV,aAAa,EACb,cAAc,EACd,SAAS,EACT,YAAY,EACb,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAQL,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AAGrC,KAAK,QAAQ,GAAG,YAAY,GAAG,qBAAqB,GAAG,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"slickCustomTooltip.d.ts","sourceRoot":"","sources":["../../src/slickCustomTooltip.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slickgrid-universal/custom-tooltip-plugin",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.0",
|
|
4
4
|
"description": "A plugin to add Custom Tooltip when hovering a cell, it subscribes to the cell",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/types/index.d.ts",
|
|
11
|
+
"node": "./dist/cjs/index.js",
|
|
11
12
|
"import": "./dist/esm/index.js",
|
|
12
|
-
"require": "./dist/cjs/index.js"
|
|
13
|
-
"default": "./dist/esm/index.js"
|
|
13
|
+
"require": "./dist/cjs/index.js"
|
|
14
14
|
},
|
|
15
15
|
"./package.json": "./package.json"
|
|
16
16
|
},
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"not dead"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@slickgrid-universal/common": "~4.
|
|
42
|
-
"@slickgrid-universal/utils": "~4.
|
|
43
|
-
"isomorphic-dompurify": "^2.
|
|
41
|
+
"@slickgrid-universal/common": "~4.7.0",
|
|
42
|
+
"@slickgrid-universal/utils": "~4.7.0",
|
|
43
|
+
"isomorphic-dompurify": "^2.7.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "185b6f9e44400bec2f1d79568905ca79e4b338a5"
|
|
46
46
|
}
|
|
@@ -29,6 +29,9 @@ import { isPrimitiveOrHTML } from '@slickgrid-universal/utils';
|
|
|
29
29
|
|
|
30
30
|
type CellType = 'slick-cell' | 'slick-header-column' | 'slick-headerrow-column';
|
|
31
31
|
|
|
32
|
+
const CLOSEST_TOOLTIP_FILLED_ATTR = ['title', 'data-slick-tooltip'];
|
|
33
|
+
const SELECTOR_CLOSEST_TOOLTIP_ATTR = '[title], [data-slick-tooltip]';
|
|
34
|
+
|
|
32
35
|
/**
|
|
33
36
|
* A plugin to add Custom Tooltip when hovering a cell, it subscribes to the cell "onMouseEnter" and "onMouseLeave" events.
|
|
34
37
|
* The "customTooltip" is defined in the Column Definition OR Grid Options (the first found will have priority over the second)
|
|
@@ -58,15 +61,21 @@ export class SlickCustomTooltip {
|
|
|
58
61
|
|
|
59
62
|
protected _addonOptions?: CustomTooltipOption;
|
|
60
63
|
protected _cellAddonOptions?: CustomTooltipOption;
|
|
61
|
-
protected _cellNodeElm?:
|
|
64
|
+
protected _cellNodeElm?: HTMLElement;
|
|
62
65
|
protected _cellType: CellType = 'slick-cell';
|
|
63
66
|
protected _cancellablePromise?: CancellablePromiseWrapper;
|
|
64
67
|
protected _observable$?: Subscription;
|
|
65
68
|
protected _rxjs?: RxJsFacade | null = null;
|
|
66
69
|
protected _sharedService?: SharedService | null = null;
|
|
70
|
+
protected _tooltipBodyElm?: HTMLDivElement;
|
|
67
71
|
protected _tooltipElm?: HTMLDivElement;
|
|
72
|
+
protected _mousePosition: { x: number; y: number; } = { x: 0, y: 0 };
|
|
73
|
+
protected _mouseTarget?: HTMLElement | null;
|
|
74
|
+
protected _hasMultipleTooltips = false;
|
|
68
75
|
protected _defaultOptions = {
|
|
76
|
+
bodyClassName: 'tooltip-body',
|
|
69
77
|
className: 'slick-custom-tooltip',
|
|
78
|
+
offsetArrow: 3, // same as `$slick-tooltip-arrow-side-margin` CSS/SASS variable
|
|
70
79
|
offsetLeft: 0,
|
|
71
80
|
offsetRight: 0,
|
|
72
81
|
offsetTopBottom: 4,
|
|
@@ -93,6 +102,9 @@ export class SlickCustomTooltip {
|
|
|
93
102
|
return this._cellAddonOptions;
|
|
94
103
|
}
|
|
95
104
|
|
|
105
|
+
get bodyClassName(): string {
|
|
106
|
+
return this._cellAddonOptions?.bodyClassName ?? 'tooltip-body';
|
|
107
|
+
}
|
|
96
108
|
get className(): string {
|
|
97
109
|
return this._cellAddonOptions?.className ?? 'slick-custom-tooltip';
|
|
98
110
|
}
|
|
@@ -127,12 +139,12 @@ export class SlickCustomTooltip {
|
|
|
127
139
|
this._sharedService = containerService.get<SharedService>('SharedService');
|
|
128
140
|
this._addonOptions = { ...this._defaultOptions, ...(this._sharedService?.gridOptions?.customTooltip) } as CustomTooltipOption;
|
|
129
141
|
this._eventHandler
|
|
130
|
-
.subscribe(grid.onMouseEnter, this.
|
|
131
|
-
.subscribe(grid.
|
|
132
|
-
.subscribe(grid.
|
|
142
|
+
.subscribe(grid.onMouseEnter, this.handleOnMouseOver.bind(this))
|
|
143
|
+
.subscribe(grid.onHeaderMouseOver, (e, args) => this.handleOnHeaderMouseOverByType(e, args, 'slick-header-column'))
|
|
144
|
+
.subscribe(grid.onHeaderRowMouseOver, (e, args) => this.handleOnHeaderMouseOverByType(e, args, 'slick-headerrow-column'))
|
|
133
145
|
.subscribe(grid.onMouseLeave, this.hideTooltip.bind(this))
|
|
134
|
-
.subscribe(grid.
|
|
135
|
-
.subscribe(grid.
|
|
146
|
+
.subscribe(grid.onHeaderMouseOut, this.hideTooltip.bind(this))
|
|
147
|
+
.subscribe(grid.onHeaderRowMouseOut, this.hideTooltip.bind(this));
|
|
136
148
|
}
|
|
137
149
|
|
|
138
150
|
dispose() {
|
|
@@ -180,8 +192,10 @@ export class SlickCustomTooltip {
|
|
|
180
192
|
}
|
|
181
193
|
|
|
182
194
|
/** depending on the selector type, execute the necessary handler code */
|
|
183
|
-
protected
|
|
195
|
+
protected handleOnHeaderMouseOverByType(event: SlickEventData, args: any, selector: CellType) {
|
|
184
196
|
this._cellType = selector;
|
|
197
|
+
this._mousePosition = { x: event.clientX || 0, y: event.clientY || 0 };
|
|
198
|
+
this._mouseTarget = document.elementFromPoint(event.clientX || 0, event.clientY || 0)?.closest(SELECTOR_CLOSEST_TOOLTIP_ATTR);
|
|
185
199
|
|
|
186
200
|
// before doing anything, let's remove any previous tooltip before
|
|
187
201
|
// and cancel any opened Promise/Observable when using async
|
|
@@ -221,8 +235,10 @@ export class SlickCustomTooltip {
|
|
|
221
235
|
}
|
|
222
236
|
}
|
|
223
237
|
|
|
224
|
-
protected async
|
|
238
|
+
protected async handleOnMouseOver(event: SlickEventData) {
|
|
225
239
|
this._cellType = 'slick-cell';
|
|
240
|
+
this._mousePosition = { x: event.clientX || 0, y: event.clientY || 0 };
|
|
241
|
+
this._mouseTarget = document.elementFromPoint(event.clientX || 0, event.clientY || 0)?.closest(SELECTOR_CLOSEST_TOOLTIP_ATTR);
|
|
226
242
|
|
|
227
243
|
// before doing anything, let's remove any previous tooltip before
|
|
228
244
|
// and cancel any opened Promise/Observable when using async
|
|
@@ -318,34 +334,44 @@ export class SlickCustomTooltip {
|
|
|
318
334
|
protected renderRegularTooltip(formatterOrText: Formatter | string | undefined, cell: { row: number; cell: number; }, value: any, columnDef: Column, item: any) {
|
|
319
335
|
const tmpDiv = document.createElement('div');
|
|
320
336
|
this._grid.applyHtmlCode(tmpDiv, this.parseFormatterAndSanitize(formatterOrText, cell, value, columnDef, item));
|
|
337
|
+
this._hasMultipleTooltips = (this._cellNodeElm?.querySelectorAll(SELECTOR_CLOSEST_TOOLTIP_ATTR).length || 0) > 1;
|
|
321
338
|
|
|
322
|
-
let
|
|
323
|
-
|
|
339
|
+
let tmpTitleElm: HTMLElement | null | undefined;
|
|
340
|
+
const cellElm = (this._cellAddonOptions?.useRegularTooltipFromCellTextOnly || !this._mouseTarget)
|
|
341
|
+
? this._cellNodeElm as HTMLElement
|
|
342
|
+
: this._mouseTarget;
|
|
324
343
|
|
|
344
|
+
let tooltipText = columnDef?.toolTip ?? '';
|
|
325
345
|
if (!tooltipText) {
|
|
326
|
-
if (this._cellType === 'slick-cell' &&
|
|
327
|
-
tooltipText =
|
|
346
|
+
if (this._cellType === 'slick-cell' && cellElm && (cellElm.clientWidth < cellElm.scrollWidth) && !this._cellAddonOptions?.useRegularTooltipFromFormatterOnly) {
|
|
347
|
+
tooltipText = cellElm.textContent?.trim() ?? '';
|
|
328
348
|
if (this._cellAddonOptions?.tooltipTextMaxLength && tooltipText.length > this._cellAddonOptions?.tooltipTextMaxLength) {
|
|
329
349
|
tooltipText = tooltipText.substring(0, this._cellAddonOptions.tooltipTextMaxLength - 3) + '...';
|
|
330
350
|
}
|
|
331
|
-
tmpTitleElm =
|
|
351
|
+
tmpTitleElm = cellElm;
|
|
332
352
|
} else {
|
|
333
353
|
if (this._cellAddonOptions?.useRegularTooltipFromFormatterOnly) {
|
|
334
|
-
tmpTitleElm = tmpDiv.querySelector<HTMLDivElement>(
|
|
354
|
+
tmpTitleElm = tmpDiv.querySelector<HTMLDivElement>(SELECTOR_CLOSEST_TOOLTIP_ATTR);
|
|
335
355
|
} else {
|
|
336
|
-
tmpTitleElm = findFirstAttribute(
|
|
337
|
-
|
|
338
|
-
|
|
356
|
+
tmpTitleElm = findFirstAttribute(cellElm, CLOSEST_TOOLTIP_FILLED_ATTR)
|
|
357
|
+
? cellElm
|
|
358
|
+
: tmpDiv.querySelector<HTMLDivElement>(SELECTOR_CLOSEST_TOOLTIP_ATTR);
|
|
359
|
+
|
|
360
|
+
if ((!tmpTitleElm || !findFirstAttribute(tmpTitleElm, CLOSEST_TOOLTIP_FILLED_ATTR)) && cellElm) {
|
|
361
|
+
tmpTitleElm = cellElm.querySelector<HTMLDivElement>(SELECTOR_CLOSEST_TOOLTIP_ATTR);
|
|
339
362
|
}
|
|
340
363
|
}
|
|
341
|
-
|
|
342
|
-
|
|
364
|
+
|
|
365
|
+
if (tmpTitleElm?.style.display === 'none' || (this._hasMultipleTooltips && (!cellElm || cellElm === this._cellNodeElm))) {
|
|
366
|
+
tooltipText = '';
|
|
367
|
+
} else if (!tooltipText || (typeof formatterOrText === 'function' && this._cellAddonOptions?.useRegularTooltipFromFormatterOnly)) {
|
|
368
|
+
tooltipText = findFirstAttribute(tmpTitleElm, CLOSEST_TOOLTIP_FILLED_ATTR) || '';
|
|
343
369
|
}
|
|
344
370
|
}
|
|
345
371
|
}
|
|
346
372
|
|
|
347
373
|
if (tooltipText !== '') {
|
|
348
|
-
this.renderTooltipFormatter(formatterOrText, cell, value, columnDef, item, tooltipText);
|
|
374
|
+
this.renderTooltipFormatter(formatterOrText, cell, value, columnDef, item, tooltipText, tmpTitleElm);
|
|
349
375
|
}
|
|
350
376
|
|
|
351
377
|
// also clear any "title" attribute to avoid showing a 2nd browser tooltip
|
|
@@ -355,16 +381,18 @@ export class SlickCustomTooltip {
|
|
|
355
381
|
protected renderTooltipFormatter(formatter: Formatter | string | undefined, cell: { row: number; cell: number; }, value: any, columnDef: Column, item: unknown, tooltipText?: string, inputTitleElm?: Element | null) {
|
|
356
382
|
// create the tooltip DOM element with the text returned by the Formatter
|
|
357
383
|
this._tooltipElm = createDomElement('div', { className: this.className });
|
|
384
|
+
this._tooltipBodyElm = createDomElement('div', { className: this.bodyClassName });
|
|
358
385
|
this._tooltipElm.classList.add(this.gridUid);
|
|
359
386
|
this._tooltipElm.classList.add('l' + cell.cell);
|
|
360
387
|
this._tooltipElm.classList.add('r' + cell.cell);
|
|
388
|
+
this.tooltipElm?.appendChild(this._tooltipBodyElm);
|
|
361
389
|
|
|
362
390
|
// when cell is currently lock for editing, we'll force a tooltip title search
|
|
363
391
|
// that can happen when user has a formatter but is currently editing and in that case we want the new value
|
|
364
|
-
//
|
|
392
|
+
// e.g.: when user is currently editing and uses the Slider, when dragging its value is changing, so we wish to use the editing value instead of the previous cell value.
|
|
365
393
|
if (value === null || value === undefined) {
|
|
366
|
-
const tmpTitleElm = this._cellNodeElm?.querySelector<HTMLDivElement>(
|
|
367
|
-
value = findFirstAttribute(tmpTitleElm,
|
|
394
|
+
const tmpTitleElm = this._cellNodeElm?.querySelector<HTMLDivElement>(SELECTOR_CLOSEST_TOOLTIP_ATTR);
|
|
395
|
+
value = findFirstAttribute(tmpTitleElm, CLOSEST_TOOLTIP_FILLED_ATTR) || value;
|
|
368
396
|
}
|
|
369
397
|
|
|
370
398
|
let outputText = tooltipText || this.parseFormatterAndSanitize(formatter, cell, value, columnDef, item) || '';
|
|
@@ -373,12 +401,12 @@ export class SlickCustomTooltip {
|
|
|
373
401
|
let finalOutputText = '';
|
|
374
402
|
if (!tooltipText || this._cellAddonOptions?.renderRegularTooltipAsHtml) {
|
|
375
403
|
finalOutputText = sanitizeTextByAvailableSanitizer(this.gridOptions, outputText);
|
|
376
|
-
this._grid.applyHtmlCode(this.
|
|
377
|
-
this.
|
|
404
|
+
this._grid.applyHtmlCode(this._tooltipBodyElm, finalOutputText);
|
|
405
|
+
this._tooltipBodyElm.style.whiteSpace = this._cellAddonOptions?.whiteSpace ?? this._defaultOptions.whiteSpace as string;
|
|
378
406
|
} else {
|
|
379
407
|
finalOutputText = outputText || '';
|
|
380
|
-
this.
|
|
381
|
-
this.
|
|
408
|
+
this._tooltipBodyElm.textContent = finalOutputText;
|
|
409
|
+
this._tooltipBodyElm.style.whiteSpace = this._cellAddonOptions?.regularTooltipWhiteSpace ?? this._defaultOptions.regularTooltipWhiteSpace as string; // use `pre` so that sequences of white space are collapsed. Lines are broken at newline characters
|
|
382
410
|
}
|
|
383
411
|
|
|
384
412
|
// optional max height/width of the tooltip container
|
|
@@ -430,20 +458,20 @@ export class SlickCustomTooltip {
|
|
|
430
458
|
// or when using "auto" and we detect not enough available space then we'll position to the "left" of the cell
|
|
431
459
|
// NOTE the class name is for the arrow and is inverse compare to the tooltip itself, so if user ask for "left-align", then the arrow will in fact be "arrow-right-align"
|
|
432
460
|
const position = this._cellAddonOptions?.position ?? 'auto';
|
|
461
|
+
let finalTooltipPosition = '';
|
|
433
462
|
if (position === 'center') {
|
|
434
463
|
newPositionLeft += (cellContainerWidth / 2) - (calculatedTooltipWidth / 2) + (this._cellAddonOptions?.offsetRight ?? 0);
|
|
435
|
-
|
|
436
|
-
this._tooltipElm.classList.remove('arrow-right-align');
|
|
464
|
+
finalTooltipPosition = 'top-center';
|
|
465
|
+
this._tooltipElm.classList.remove('arrow-left-align', 'arrow-right-align');
|
|
437
466
|
this._tooltipElm.classList.add('arrow-center-align');
|
|
438
|
-
|
|
439
467
|
} else if (position === 'right-align' || ((position === 'auto' || position !== 'left-align') && (newPositionLeft + calculatedTooltipWidth) > calculatedBodyWidth)) {
|
|
468
|
+
finalTooltipPosition = 'right';
|
|
440
469
|
newPositionLeft -= (calculatedTooltipWidth - cellContainerWidth - (this._cellAddonOptions?.offsetLeft ?? 0));
|
|
441
|
-
this._tooltipElm.classList.remove('arrow-center-align');
|
|
442
|
-
this._tooltipElm.classList.remove('arrow-left-align');
|
|
470
|
+
this._tooltipElm.classList.remove('arrow-center-align', 'arrow-left-align');
|
|
443
471
|
this._tooltipElm.classList.add('arrow-right-align');
|
|
444
472
|
} else {
|
|
445
|
-
|
|
446
|
-
this._tooltipElm.classList.remove('arrow-right-align');
|
|
473
|
+
finalTooltipPosition = 'left';
|
|
474
|
+
this._tooltipElm.classList.remove('arrow-center-align', 'arrow-right-align');
|
|
447
475
|
this._tooltipElm.classList.add('arrow-left-align');
|
|
448
476
|
}
|
|
449
477
|
|
|
@@ -451,11 +479,23 @@ export class SlickCustomTooltip {
|
|
|
451
479
|
// NOTE the class name is for the arrow and is inverse compare to the tooltip itself, so if user ask for "bottom", then the arrow will in fact be "arrow-top"
|
|
452
480
|
if (position === 'bottom' || ((position === 'auto' || position !== 'top') && calculatedTooltipHeight > calculateAvailableSpace(this._cellNodeElm).top)) {
|
|
453
481
|
newPositionTop = (cellPosition.top || 0) + (this.gridOptions.rowHeight ?? 0) + (this._cellAddonOptions?.offsetTopBottom ?? 0);
|
|
482
|
+
finalTooltipPosition = `bottom-${finalTooltipPosition}`;
|
|
454
483
|
this._tooltipElm.classList.remove('arrow-down');
|
|
455
484
|
this._tooltipElm.classList.add('arrow-up');
|
|
456
485
|
} else {
|
|
457
|
-
|
|
486
|
+
finalTooltipPosition = `top-${finalTooltipPosition}`;
|
|
458
487
|
this._tooltipElm.classList.remove('arrow-up');
|
|
488
|
+
this._tooltipElm.classList.add('arrow-down');
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// when having multiple tooltips, we'll try to reposition tooltip to mouse position
|
|
492
|
+
if (this._tooltipElm && (this._hasMultipleTooltips || this.cellAddonOptions?.repositionByMouseOverTarget)) {
|
|
493
|
+
const mouseElmOffset = getOffset(this._mouseTarget)!;
|
|
494
|
+
if (finalTooltipPosition.includes('left') || finalTooltipPosition === 'top-center') {
|
|
495
|
+
newPositionLeft = mouseElmOffset.left - (this._addonOptions?.offsetArrow ?? 3);
|
|
496
|
+
} else if (finalTooltipPosition.includes('right')) {
|
|
497
|
+
newPositionLeft = mouseElmOffset.left - calculatedTooltipWidth + (this._mouseTarget?.offsetWidth ?? 0) + (this._addonOptions?.offsetArrow ?? 3);
|
|
498
|
+
}
|
|
459
499
|
}
|
|
460
500
|
|
|
461
501
|
// reposition the tooltip over the cell (90% of the time this will end up using a position on the "right" of the cell)
|
|
@@ -471,6 +511,10 @@ export class SlickCustomTooltip {
|
|
|
471
511
|
protected swapAndClearTitleAttribute(inputTitleElm?: Element | null, tooltipText?: string) {
|
|
472
512
|
// the title attribute might be directly on the slick-cell container element (when formatter returns a result object)
|
|
473
513
|
// OR in a child element (most commonly as a custom formatter)
|
|
514
|
+
let cellWithTitleElm: Element | null | undefined;
|
|
515
|
+
if (inputTitleElm) {
|
|
516
|
+
cellWithTitleElm = (this._cellNodeElm && ((this._cellNodeElm.hasAttribute('title') && this._cellNodeElm.getAttribute('title')) ? this._cellNodeElm : this._cellNodeElm?.querySelector('[title]')));
|
|
517
|
+
}
|
|
474
518
|
const titleElm = inputTitleElm || (this._cellNodeElm && ((this._cellNodeElm.hasAttribute('title') && this._cellNodeElm.getAttribute('title')) ? this._cellNodeElm : this._cellNodeElm?.querySelector('[title]')));
|
|
475
519
|
|
|
476
520
|
// flip tooltip text from `title` to `data-slick-tooltip`
|
|
@@ -479,6 +523,11 @@ export class SlickCustomTooltip {
|
|
|
479
523
|
if (titleElm.hasAttribute('title')) {
|
|
480
524
|
titleElm.setAttribute('title', '');
|
|
481
525
|
}
|
|
526
|
+
// targeted element might actually not be the cell element,
|
|
527
|
+
// so let's also clear the cell element title attribute to avoid showing native + custom tooltips
|
|
528
|
+
if (cellWithTitleElm?.hasAttribute('title')) {
|
|
529
|
+
cellWithTitleElm.setAttribute('title', '');
|
|
530
|
+
}
|
|
482
531
|
}
|
|
483
532
|
}
|
|
484
533
|
}
|