chart = {
const svg = d3.select(DOM.svg(width, height + 30));
const g2 = svg.append('g')
.selectAll('g')
.data([1,2,4])
.enter()
.append("text")
.attr("transform", (d, i) => `translate(${(x(i) + x.bandwidth() / 2) - 10},0)`)
.attr("y", 100 / 2)
.attr("dy", ".35em")
.attr('font-size', '2em')
.text(function(d) { return d; })
.attr('fill', 'orangered')
const g = svg
.append("g")
.selectAll("g")
.data(boxes)
.join("g");
g.append("path")
.attr("stroke", "currentColor")
.attr(
"d",
(d, i) => `
M${x(i) + x.bandwidth() / 2},${y(d.range[1])}
V${y(d.range[0])}
`
);
g.append("path")
.attr("fill", "#ddd")
.attr(
"d",
(d, i) => `
M${x(i)},${y(d.quartiles[2])}
H${x(i) + x.bandwidth()}
V${y(d.quartiles[0])}
H${x(i)}
Z
`
);
g.append("path")
.attr("stroke", "currentColor")
.attr("stroke-width", 2)
.attr(
"d",
(d, i) => `
M${x(i)},${y(d.quartiles[1])}
H${x(i) + x.bandwidth()}
`
);
g.append("g")
.attr("fill", "currentColor")
.attr("fill-opacity", 0.2)
.attr("stroke", "none")
.attr("transform", (d, i) => `translate(${x(i) + x.bandwidth() / 2},0)`)
.selectAll("circle")
.data(d => d.outliers)
.join("circle")
.attr("r", 3)
.attr("cx", () => (Math.random() - 0.5) * 4)
.attr("cy", d => y(d));
svg.append("line")
.attr("transform", `translate(${margin.left + 10},0)`)
.attr("x1", 0)
.attr("x2", width - margin.left - margin.right)
.attr("y1", y(dataMean))
.attr("y2", y(dataMean))
.attr('stroke', 'orangered')
.attr('stroke-width', 3)
.attr('cursor', 'grab')
.call(drag);
svg.append("g").call(xAxis).attr('font-size', '2em');
svg.append("g").call(yAxis);
svg.selectAll("g")
.data(dat)
.enter()
.append("text")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", 100 / 2)
.attr("dy", ".35em")
.text(function(d) { return d; });
return svg.node();
}