tooltip = (selectionGroup, tooltipDiv) => {
const MOUSE_POS_OFFSET = 8;
selectionGroup.each(function () {
d3.select(this)
.on("mouseover.tooltip", handleMouseover)
.on("mousemove.tooltip", handleMousemove)
.on("mouseleave.tooltip", handleMouseleave);
});
function handleMouseover() {
showTooltip();
setContents(d3.select(this).datum());
setStyle(d3.select(this));
}
function handleMousemove(event) {
const [mouseX, mouseY] = d3.pointer(event, this);
setPosition(mouseX + dms.marginLeft, mouseY + dms.marginTop);
}
function handleMouseleave() {
hideTooltip();
resetStyle(d3.select(this));
}
function showTooltip() {
tooltipDiv.style("display", "block");
}
function hideTooltip() {
tooltipDiv.style("display", "none");
}
function setPosition(mouseX, mouseY) {
tooltipDiv
.style(
"top",
mouseY < dms.height / 2 ? `${mouseY + MOUSE_POS_OFFSET}px` : "initial"
)
.style(
"right",
mouseX > width / 2
? `${width - mouseX + MOUSE_POS_OFFSET}px`
: "initial"
)
.style(
"bottom",
mouseY > dms.height / 2
? `${dms.height - mouseY + MOUSE_POS_OFFSET}px`
: "initial"
)
.style(
"left",
mouseX < width / 2 ? `${mouseX + MOUSE_POS_OFFSET}px` : "initial"
);
}
function setContents(datum) {
tooltipDiv
.selectAll("p")
.data(Object.entries(simplifyForTT(datum)))
.join("p")
.filter(([key, value]) => value !== null && value !== undefined)
.html(([key, value]) =>
`<strong>${key}</strong>: ${
typeof value === "object" ? value.toLocaleString("en-US") : value
}`);
}
}