tooltip = (selection, tt) => {
selection
.on("mouseover", handleMouseover)
.on("mousemove", handleMousemove)
.on("mouseleave", handleMouseleave);
function handleMouseover() {
if (!viewof collapsed.value) {
darkenSel();
showTooltip();
setContents();
}
}
function handleMousemove(event) {
const [mouseX, mouseY] = d3.pointer(event, this);
setMoseoverDate(mouseX);
setFilteredData(mouseX);
if (!viewof collapsed.value) {
moveTooltip(mouseX, mouseY);
}
}
function handleMouseleave() {
if (!viewof collapsed.value) {
lightenSel();
hideTooltip();
}
}
function darkenSel() {
selection.attr("opacity", 1).style("mix-blend-mode", null);
}
function lightenSel() {
selection
.attr("opacity", rectProps.opacity)
.style("mix-blend-mode", "multiply");
}
function showTooltip() {
tt.style("display", "block");
}
function hideTooltip() {
tt.style("display", "none");
}
function moveTooltip(mouseX, mouseY) {
tt.style("top", yPos(mouseY)).style("left", xPos(mouseX));
}
function xPos(mouseX) {
return mouseX > width / 2
? `calc(${mouseX}px - ${tt.style("width")})`
: `${mouseX + 24}px`;
}
function yPos(mouseY) {
return mouseY > height / 2
? `calc(${mouseY - 24}px - ${tt.style("height")})`
: `${mouseY + 12}px`;
}
function setContents() {
if (!viewof collapsed.value) {
tt.selectAll("p")
.data(Object.entries(selection.datum()))
.join("p")
.html(
([key, value]) =>
`<strong>${key}</strong>: ${
typeof value === 'object' ? value.toLocaleString("en-US") : value
}`
);
} else {
tt.selectAll("p").remove();
}
}
function setMoseoverDate(mouseX) {
mutable mouseoverDate = dateXPos(mouseX).toLocaleString("en-US");
}
function setFilteredData(mouseX) {
mutable filteredData = dataAroundDate(dateXPos(mouseX));
}
function dateXPos(mouseX) {
return xScale.invert(mouseX);
}
function dataAroundDate(date) {
return parsed.filter(d => +d.startDate <= +date && +d.endDate >= +date);
}
}