/
RcsbFvTooltipManager.ts
110 lines (102 loc) · 4.14 KB
/
RcsbFvTooltipManager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import {RcsbFvDOMConstants} from "../RcsbFvConfig/RcsbFvDOMConstants";
import {computePosition, detectOverflow} from "@floating-ui/dom";
import {RcsbFvTrackDataElementInterface} from "../../RcsbDataManager/RcsbDataManager";
import {RcsbFvTooltipInterface} from "./RcsbFvTooltipInterface";
export class RcsbFvTooltipManager {
private readonly boardId: string;
private readonly tooltipDiv: HTMLDivElement;
private readonly tooltipDescriptionDiv: HTMLDivElement;
private readonly refDiv: HTMLDivElement;
private readonly tooltip: RcsbFvTooltipInterface;
constructor(boardId: string, tooltip: RcsbFvTooltipInterface) {
this.boardId = boardId;
this.tooltip = tooltip;
const refDiv: HTMLDivElement | null= document.querySelector("#"+this.boardId);
if(refDiv == null)
throw "Main board DOM element not found";
this.refDiv = refDiv;
const tooltipDiv: HTMLDivElement | null= document.querySelector("#"+this.boardId+RcsbFvDOMConstants.TOOLTIP_DOM_ID_PREFIX);
if(tooltipDiv == null)
throw "Tooltip DOM element not found";
this.tooltipDiv = tooltipDiv;
const tooltipDescriptionDiv: HTMLDivElement | null = document.querySelector("#"+this.boardId+RcsbFvDOMConstants.TOOLTIP_DESCRIPTION_DOM_ID_PREFIX);
if(tooltipDescriptionDiv == null)
throw "Tooltip DOM element not found";
this.tooltipDescriptionDiv = tooltipDescriptionDiv;
Object.assign(this.tooltipDiv.style, {
position: 'absolute',
visibility: 'hidden',
whiteSpace: 'nowrap',
top: '0',
left: '0',
});
Object.assign(this.tooltipDescriptionDiv.style, {
position: 'absolute',
visibility: 'hidden',
whiteSpace: 'nowrap',
top: '0',
left: '0',
});
}
showTooltip(d: RcsbFvTrackDataElementInterface){
this.tooltipDiv.textContent = "";
const divTooltip = this.tooltip.showTooltip(d);
if(!divTooltip)
return;
this.tooltipDiv.append(divTooltip);
computePosition(this.refDiv,this.tooltipDiv,{
placement:'top-end',
middleware:[{
name: 'middleware',
async fn(middlewareArguments) {
const overflow = await detectOverflow(middlewareArguments,{
rootBoundary: "viewport"
});
if(overflow.top > 0)
return {y:overflow.top+middlewareArguments.y};
return {};
},
}]
}).then((o) => {
Object.assign(this.tooltipDiv.style, {
left: `${o.x}px`,
top: `${o.y}px`,
visibility: 'visible'
});
});
}
showTooltipDescription(d: RcsbFvTrackDataElementInterface){
this.tooltipDescriptionDiv.textContent = "";
this.tooltipDescriptionDiv.style.visibility = "hidden";
const description = this.tooltip.showTooltipDescription?.(d);
if(!description)
return;
this.tooltipDescriptionDiv.append(description);
computePosition(this.refDiv,this.tooltipDescriptionDiv,{
placement:'top-end',
middleware:[{
name: 'middleware',
async fn(middlewareArguments) {
const overflow = await detectOverflow(middlewareArguments,{
rootBoundary: "viewport"
});
if(overflow.top > 0)
return {y:overflow.top+middlewareArguments.y};
return {};
},
}]
}).then(({x, y}) => {
Object.assign(this.tooltipDescriptionDiv.style, {
left: `${x}px`,
top: `${y-30}px`,
visibility: 'visible'
});
});
}
hideTooltip(){
this.tooltipDiv.innerHTML = "";
this.tooltipDiv.style.visibility = "hidden";
this.tooltipDescriptionDiv.innerHTML = "";
this.tooltipDescriptionDiv.style.visibility = "hidden";
}
}