function inlineChart(data, {
x = ([x]) => x,
y = ([, y]) => y,
z = () => 1,
marginTop = 50,
marginRight = 50,
marginBottom = 120,
marginLeft = 40,
gapTop = 0,
gapRight = 0,
gapBottom = 30,
gapLeft = 30,
width = 450,
height = 500,
barwidth = 40,
xType = d3.scaleBand,
xDomain,
xRange = [marginLeft, width - marginRight - gapLeft - gapRight],
yType = d3.scaleLinear,
yDomain,
yRange = [height - marginBottom, marginTop],
zDomain,
colors = d3.schemeCategory10,
} = {}){
const X = d3.map(data, x);
const Y = d3.map(data, y);
const Z = d3.map(data, z);
if (xDomain === undefined) xDomain = X;
if (yDomain === undefined) yDomain = [0, d3.max(Y)];
if (zDomain === undefined) zDomain = Z;
zDomain = new d3.InternSet(zDomain);
const xScale = xType(xDomain, xRange);
const yScale = yType(yDomain, yRange);
const color = d3.scaleOrdinal(zDomain, colors);
const xAxis = d3.axisBottom(xScale).ticks(0).tickSizeOuter(0);
const yAxis = d3.axisLeft(yScale).ticks(5).tickSizeOuter(10);
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;")
.attr("font-family", "Times New Roman")
;
const plot = svg.append("g")
.attr("class", "plot")
.attr("transform", `translate(${marginLeft + gapLeft}, ${marginTop + gapTop})`)
, gxaxis = plot
.selectAll("g.x-axis")
.data([0])
.join("g").attr("class", "x-axis")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(xAxis)
, gyaxis = plot
.selectAll("g.y-axis")
.data([0])
.join("g").attr("class", "y-axis")
.attr("transform", `translate(${marginLeft}, 0)`)
.call(yAxis)
;
let xwidth = xScale.bandwidth()
;
plot.selectAll("g.series")
.data(X)
.join("g").attr("class", "series")
.attr("transform", (d, i) => `translate(${xScale(X[i])}, ${ yScale(Y[i])})`)
.each(function(d, i){
let h = yScale(0) - yScale(Y[i])
, bclr = color(Z[i])
, fclr = pickBestContrast(bclr, ["#ffff", "#000000"])
;
d3.select(this)
.selectAll("rect")
.data([0])
.join("rect")
.attr("fill", color(Z[i]))
.attr("x", (xwidth - barwidth) / 2)
.attr("y", 0)
.attr("height", h)
.attr("width", barwidth);
d3.select(this)
.selectAll("text.band-label")
.data([0])
.join("text").attr("class", "band-label")
.attr("transform", `translate(${xwidth / 2}, ${h / 2}) rotate(-90) `)
.attr("text-anchor", "middle")
.attr("fill", fclr)
.text(d)
if(!/donkey/i.test(d)){
d3.select(this)
.selectAll("text.value-label")
.data([0])
.join("text").attr("class", "value-label")
.attr("transform", `translate(${xwidth / 2}, ${ yScale(100) })`)
.attr("dy", "-3.5em")
.attr("text-anchor", "middle")
.text(Y[i])
}
else{
const ovrflw = yScale(Y[i]) - yScale(100)
, sy = d3.symbol(d3.symbolTriangle, 16)
, offset = 10
, overflow = d3.select(this)
.selectAll("g.overflow")
.data([0])
.join("g").attr("class", "overflow")
.attr("fill", "#fff")
.attr("stroke", bclr)
.attr("transform", `translate(${(xwidth - barwidth) / 2}, ${-ovrflw})`)
;
overflow.selectAll("rect")
.data([0]).join("rect")
.attr("width", barwidth)
.attr("height", ovrflw)
.attr("stroke-dasharray", `0,${barwidth},${ovrflw + barwidth + ovrflw} `)
overflow
.selectAll("g.jagged")
.data([d3.quantize(d3.interpolateNumber(1, 10), 4)])
.join("g").attr("class", "jagged")
.attr("transform", `translate(${(offset) / 2}, ${ovrflw})`)
.attr("fill", bclr)
.selectAll("path")
.data(d => d)
.join("path")
.attr("transform", (d, i) => `translate(${offset * i}, -2)`)
.attr("d", sy());
let vwsymbl = overflow
.selectAll("g.value-w-symbol")
.data(["gte"])
.join("g").attr("class", "value-w-symbol")
.attr("fill", "#000")
.attr("stroke", "#000")
;
vwsymbl.call(g => g.append("use")
.attr("href", d => `#${d}`)
.attr("width", 15).attr("height", 15)
)
vwsymbl.call(g => g.append("text")
.attr("dx", "1em").attr("dy", "0.75em")
.text(Y[i]));
vwsymbl.attr("transform", `translate(${barwidth / 2 - 18}, ${ovrflw - 30})`)
}
});
plot.selectAll("g.x-axis")
.attr("font-size", null)
.attr("font-family", null)
.selectAll("text.axis-label")
.data(["Species"])
.join("text").attr("class", "axis-label")
.attr("text-rendering", "geometricPrecision")
.attr("fill", "#000")
.attr("transform", `translate(${(xRange[1]) / 2}, ${gapBottom})`)
.attr("text-anchor", "start")
.text(d => d);
plot.selectAll("g.y-axis")
.attr("font-size", null)
.attr("font-family", null)
.selectAll("text.axis-label")
.data(["Sound (in decibels)"])
.join("text").attr("class", "axis-label")
.attr("text-rendering", "geometricPrecision")
.attr("fill", "#000")
.attr("transform", `translate(${-gapLeft}, ${(yScale(0)) / 2}) rotate(-90)`)
.attr("dy", "-0.5em")
.attr("text-anchor", "middle")
.text(d => d);
//cleanup
plot.selectAll("g.x-axis")
.selectAll("g.tick").remove();
return svg.node();
}