var d3 = require('d3');
var React = require('react');
var Panel = require('react-bootstrap').Panel;
module.exports = React.createClass({
displayName: "StackedBarChart",
calcMinMax: function(data) {
var children = [];
for (var child in data) {
if (data.hasOwnProperty(child))
children.push(data[child]);
}
var positiveValues = [0];
var negativeValues = [0];
if (children.length > 0 && children[0].length > 0) {
for (var j = 0; j < children[0].length; j++) {
positiveValues.push(children.reduce(function(accum, curr, i, arr) {
if (arr[i][j] > 0)
return accum + arr[i][j];
return accum;
}, 0));
negativeValues.push(children.reduce(function(accum, curr, i, arr) {
if (arr[i][j] < 0)
return accum + arr[i][j];
return accum;
}, 0));
}
}
return [Math.min.apply(Math, negativeValues), Math.max.apply(Math, positiveValues)];
},
calcAxisMarkSeparation: function(minMax, height, ticksPerHeight) {
var targetTicks = height / ticksPerHeight;
var range = minMax[1]-minMax[0];
var rangePerTick = range/targetTicks;
var roundOrder = Math.floor(Math.log(rangePerTick) / Math.LN10);
var roundTo = Math.pow(10, roundOrder);
return Math.ceil(rangePerTick/roundTo)*roundTo;
},
render: function() {
var data = this.props.data.mapReduceChildren(null,
function(accumulator, currentValue, currentIndex, array) {
return accumulator + currentValue;
}
);
height = 400;
width = 600;
legendWidth = 100;
xMargin = 70;
yMargin = 70;
height -= yMargin*2;
width -= xMargin*2;
var minMax = this.calcMinMax(data);
var y = d3.scaleLinear()
.range([0, height])
.domain(minMax);
var xAxisMarksEvery = this.calcAxisMarkSeparation(minMax, height, 40);
var x = d3.scaleLinear()
.range([0, width])
.domain([0, this.props.data.Labels.length + 0.5]);
var bars = [];
var labels = [];
var barWidth = x(0.75);
var barStart = x(0.25) + (x(1) - barWidth)/2;
var childId=0;
// Add Y axis marks and labels, and initialize positive- and
// negativeSum arrays
var positiveSum = [];
var negativeSum = [];
for (var i=0; i < this.props.data.Labels.length; i++) {
positiveSum.push(0);
negativeSum.push(0);
var labelX = x(i) + barStart + barWidth/2;
var labelY = height + 15;
labels.push((
{this.props.data.Labels[i]}
));
labels.push((
));
}
// Make X axis marks and labels
var makeXLabel = function(value) {
labels.push((
));
labels.push((
{value}
));
}
for (var i=0; i < minMax[1]; i+= xAxisMarksEvery)
makeXLabel(i);
for (var i=0-xAxisMarksEvery; i > minMax[0]; i -= xAxisMarksEvery)
makeXLabel(i);
//TODO handle Values from current series?
var legendMap = {};
for (var child in data) {
childId++;
var rectClasses = "chart-element chart-color" + (childId % 12);
if (data.hasOwnProperty(child)) {
for (var i=0; i < data[child].length; i++) {
var value = data[child][i];
if (value == 0)
continue;
legendMap[child] = childId;
if (value > 0) {
rectHeight = y(value) - y(0);
positiveSum[i] += rectHeight;
rectY = height - y(0) - positiveSum[i];
} else {
rectHeight = y(0) - y(value);
rectY = height - y(0) + negativeSum[i];
negativeSum[i] += rectHeight;
}
bars.push((
));
}
}
}
var legend = [];
for (var series in legendMap) {
var legendClasses = "chart-color" + (legendMap[series] % 12);
var legendY = (legendMap[series] - 1)*15;
legend.push((
));
legend.push((
{series}
));
}
return (
);
}
});