function hover(b, path) {
if ("ontouchstart" in document)
b
.style("-webkit-tap-highlight-color", "transparent")
.on("touchmove", moved)
.on("touchstart", entered)
.on("touchend", left);
else
b
.on("mousemove", moved)
.on("mouseenter", entered)
.on("mouseleave", left);
const dot = b.append("g").attr("display", "none");
dot.append("circle")
.datum(data)
.attr("r", 3);
dot
.append("rect")
.attr("width", 100)
.attr("height", 30)
.attr("fill", "white")
.attr("y", -37)
.attr("x", -50)
.attr("stroke", "lightgrey");
dot
.append("text")
.attr("font-family", "Helvetica")
.attr("font-size", 11)
.attr("text-anchor", "middle")
.attr("y", -18)
.raise();
const formatTime = d3.timeFormat("%B %d");
function moved() {
d3.event.preventDefault();
const mouse = d3.mouse(this);
const xm = x.invert(mouse[0]);
const ym = y.invert(mouse[1]);
const i1 = d3.bisectLeft(data.dates, xm, 1);
const i0 = i1 - 1;
const i = xm - data.dates[i0] > data.dates[i1] - xm ? i1 : i0;
const s = d3.least(data.series, d => Math.abs(d.values[i] - ym));
path
.attr("stroke", d => (d === s ? color(s.name) : "#ddd"))
.filter(d => d === s)
.raise();
dot.attr("transform", `translate(${x(data.dates[i])},${y(s.values[i])})`);
dot
.select("circle")
.attr("fill", color(s.name));
let node = dot.select("text").node();
node.innerHTML = "";
node.appendChild(svg`
<tspan><tspan font-weight = "bold">${s.name}:</tspan> ${s.values[i]} beds in use (${formatTime(data.dates[i])}) </tspan>`
);
dot
.select("rect")
.attr(
"x",
-dot
.select("text")
.node()
.getComputedTextLength() / 2 - 10
)
.attr(
"width",
dot
.select("text")
.node()
.getComputedTextLength() + 20
);
dot.select("text").raise();
}
function entered() {
dot.attr("display", null);
}
function left() {
path.style("mix-blend-mode", "multiply").attr("stroke", d => color(d.name));
dot.attr("display", "none");
}
}