function renderNormalizedStackBarChart(inputData,dom_element_to_append_to) { var mainMargin = { top: 20, right: 190, bottom: 150, left: 60 }, width = 900 - mainMargin.left - mainMargin.right, height = 500 - mainMargin.top - mainMargin.bottom, miniMargin = { top: 50, bottom: 150, left: 40, right: 190 }, miniHeight = 50; var xscale = d3.time.scale() .range([0, width]); var miniXScale = d3.time.scale() .range([0, width]); var dateFormat = d3.time.format("%a %d"); var yScaleLeft = d3.scale.linear() .rangeRound([height, 0]); var yScaleRight = d3.scale.linear() .rangeRound([height, 0]); var miniyScaleLeft = d3.scale.linear() .rangeRound([miniHeight, 0]); var miniyScaleRight = d3.scale.linear() .rangeRound([miniHeight, 0]); var colors = d3.scale.ordinal() .range(["#63c172", "#ee9952", "#46d6c4", "#fee851", "#98bc9a"]); console.log(inputData); var xaxis = d3.svg.axis() .scale(xscale) .orient("bottom") .tickFormat(function(d) { return (new Date(+d) + "").substring(3,21); }); var miniXAxis = d3.svg.axis() .scale(miniXScale) .tickFormat(function(d) { return (new Date(+d) + "").substring(0,16); }) .orient("bottom"); var yAxisLeft = d3.svg.axis() .scale(yScaleLeft) .orient("left") .tickFormat(d3.format(".0%")); var yAxisRight = d3.svg.axis() .scale(yScaleRight) .orient("right") .tickFormat(d3.format(".0%")); var line = d3.svg.line() .x(function(d, i) { return xscale(d.response) ; }) .y(function(d) { return yScaleRight(d.value); }); var miniLine = d3.svg.line() .x(function(d, i) { return miniXScale(d.response) + miniXScale.rangeBand()/2; }) .y(function(d) { return miniyScaleRight(d.value); }); var svg = d3.select(dom_element_to_append_to).append("svg") .attr("width", width + mainMargin.left + mainMargin.right ) .attr("height", height + mainMargin.top + mainMargin.bottom); svg.append("g") .attr("class", "y axisLeft") .attr("transform", function() { return "translate(" + (mainMargin.left ) + "," + mainMargin.top + ")"; }) .call(yAxisLeft); svg.append("g") .attr("class", "y axisRight") .attr("transform", function() { return "translate(" + (width + mainMargin.left ) + "," + mainMargin.top + ")"; }) .call(yAxisRight); var main = svg.append("svg") .attr("width", width + mainMargin.left ) .append("g") .attr("transform", "translate(" + mainMargin.left + "," + mainMargin.top + ")"); var mini = svg.append("svg") .attr("width", width + miniMargin.left + 15 ) .append("g") .attr("transform", "translate(" + (miniMargin.left*1.5) + "," + (0) + ")"); var tip = d3.tip() .attr('class', 'd3-tip') .offset([-10, 0]) .html(function(d) { var date = (new Date(+d.CategoryNames) + "" ).substring(0,25); return "
Date: " + date + "
" + "
" + d.response+ " (" + (d.yp1*100).toFixed(0) +"%): " + "" + d.y1 + " times
"; }); svg.call(tip); var categories = d3.keys(inputData[0]).filter(function(key) { return key !== "CategoryNames"; }); var parsedata = categories.map(function(name) { return { "CategoryNames": name }; }); inputData.forEach(function(d) { parsedata.forEach(function(pd) { pd[d["CategoryNames"]] = d[pd["CategoryNames"]]; }); }); colors.domain(d3.keys(parsedata[0]).filter(function(key) { return key !== "CategoryNames" && key !== "Base"; })); parsedata.forEach(function(pd) { var y0 = 0; pd.responses = colors.domain().map(function(response) { var responseobj = {response: response, y0: y0, yp0: y0}; y0 += +pd[response]; responseobj.y1 = y0; responseobj.yp1 = y0; responseobj.CategoryNames = pd.CategoryNames; return responseobj; }); pd.responses.forEach(function(d) { d.yp0 /= y0; d.yp1 /= y0; }); pd.totalresponses = pd.responses[pd.responses.length - 1].y1; }); xscale.domain(d3.extent(parsedata, function(d) { return +d.CategoryNames; }) ); //mainX1.domain(xscale.domain()); miniXScale.domain(xscale.domain()); yScaleRight.domain([0, d3.max(parsedata, function(d) { return d.totalresponses; })]); yAxisRight.tickFormat(d3.format(".2s")); var brush = d3.svg.brush() .x(miniXScale) .on("brush", brushed); xaxis.ticks(parsedata.length); main.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xaxis) .selectAll("text") .attr("y", 5) .attr("x", 7) .attr("dy", ".35em") .attr("transform", "rotate(65)") .style("text-anchor", "start"); var category = main.selectAll(".category") .data(parsedata) .enter().append("g") .attr("class", "category") .attr("transform", function(d) { return "translate(" + xscale(+d.CategoryNames) + ",0)"; }); console.log(parsedata); category.selectAll("rect") .data(function(d) { return d.responses; }) .enter().append("rect") .attr("width", width/(parsedata.length+10)) .attr("y", function(d) { return yScaleLeft(d.yp1); }) .attr("height", function(d) { return yScaleLeft(d.yp0) - yScaleLeft(d.yp1); }) .attr("fill", function(d) { return colors(d.response); }) .on('mouseover', tip.show) .on('mouseout', tip.hide); var convertedData = []; parsedata.forEach(function(item) { convertedData.push({response: item.CategoryNames, value: item.responses[0].y1}) }); main.append("path") .data(convertedData) .attr("class", "line") .attr("d", line(convertedData)) .attr("stroke", "blue") .attr("stroke-width", 2) .attr("fill", "none"); var miniCategory = mini.selectAll(".mini_category") .data(parsedata) .enter().append("g") .attr("class", "mini_category") .attr("transform", function(d) { return "translate(" + (miniXScale(d.CategoryNames) ) + "," + (height+miniMargin.top + 50) + ")"; }); miniCategory.selectAll("rect") .data(function(d) { return d.responses; }) .enter().append("rect") .attr("width", width/(parsedata.length+10)) .attr("y", function(d) { return miniyScaleLeft(d.yp1); }) .attr("height", function(d) { return miniyScaleLeft(d.yp0) - miniyScaleLeft(d.yp1) ; }) .style("fill", function(d) { return colors(d.response); }); mini.append("g") .attr("class", "x brush") .call(brush) .selectAll("rect") .attr("y", -6) .attr("height", miniHeight + 15) .attr("transform", "translate(" + 0 + "," + (height+miniMargin.top + 50) + ")"); var legend = svg.selectAll(".legend") .data(colors.domain()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(82," + (((height+miniMargin.top + 50)) + (i * 20)) + ")"; }); legend.append("rect") .attr("x", width - 18) .attr("width", 18) .attr("height", 18) .style("fill", colors); legend.append("text") .attr("x", width + 10) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "start") .text(function(d) { return d; }); mini.append("g") .attr("class", "x axis1") .attr("transform", "translate(0," + (height+miniMargin.top + 50 + miniHeight) + ")") .call(miniXAxis); d3.selectAll("input").on("change", handleFormClick); function handleFormClick() { if (this.value === "bypercent") { transitionPercent(); } else { transitionCount(); } } function transitionPercent() { yScaleLeft.domain([0, 1]); miniyScaleLeft.domain([0, 1]); var transMain = main.transition().duration(250); var transMini = mini.transition().duration(250); var categories = transMain.selectAll(".category"); categories.selectAll("rect") .attr("y", function(d) { return yScaleLeft(d.yp1); }) .attr("height", function(d) { return yScaleLeft(d.yp0) - yScaleLeft(d.yp1); }); var miniCategories = transMini.selectAll(".mini_category"); miniCategories.selectAll("rect") .attr("y", function(d) { return miniyScaleLeft(d.yp1); }) .attr("height", function(d) { return miniyScaleLeft(d.yp0) - miniyScaleLeft(d.yp1); }); yAxisLeft.tickFormat(d3.format(".0%")); main.selectAll(".y.axisLeft").call(yAxisLeft); } function transitionCount() { yScaleLeft.domain([0, d3.max(parsedata, function(d) { return d.totalresponses; })]); miniyScaleLeft.domain([0, d3.max(parsedata, function(d) { return d.totalresponses; })]); var transoneMain = main.transition().duration(100); var transoneMini = mini.transition().duration(100); var categoriesone = transoneMain.selectAll(".category"); categoriesone.selectAll("rect") .attr("y", function(d) { return this.getBBox().y + this.getBBox().height - (yScaleLeft(d.y0) - yScaleLeft(d.y1)) }) .attr("height", function(d) { return yScaleLeft(d.y0) - yScaleLeft(d.y1); }); var miniCategoriesone = transoneMini.selectAll(".mini_category"); miniCategoriesone.selectAll("rect") .attr("y", function(d) { return this.getBBox().y + this.getBBox().height - (miniyScaleLeft(d.y0) - miniyScaleLeft(d.y1)) }) .attr("height", function(d) { return miniyScaleLeft(d.y0) - miniyScaleLeft(d.y1); }); var transtwoMain = transoneMain.transition() .delay(150) .duration(200) .ease("bounce"); var transtwoMini = transoneMini.transition() .delay(150) .duration(200) .ease("bounce"); var categoriestwo = transtwoMain.selectAll(".category"); categoriestwo.selectAll("rect") .attr("y", function(d) { return yScaleLeft(d.y1); }); var miniCategoriestwo = transtwoMini.selectAll(".mini_category"); miniCategoriestwo.selectAll("rect") .attr("y", function(d) { return miniyScaleLeft(d.y1); }); yAxisLeft.tickFormat(d3.format(".2s")); main.selectAll(".y.axisLeft").call(yAxisLeft); } function brushed() { xscale.domain(brush.empty() ? miniXScale.domain() : brush.extent()); main.selectAll(".category") .attr("transform", function(d) { return "translate(" + xscale(+d.CategoryNames) + ",0)"; }); main.selectAll(".line") .data(convertedData) .attr("d", function(d) { return line(convertedData); }) main.select("g.x.axis") .call(xaxis) .selectAll("text") .attr("y", 5) .attr("x", 7) .attr("dy", ".35em") .attr("transform", "rotate(65)") .style("text-anchor", "start"); } d3.select(self.frameElement).style("height", (height + mainMargin.top + mainMargin.bottom) + "px"); }