/** Function: renderTreemap
* Variables :
* * dataTreeMap: contains data to be plotted as treeMap, data is grouped in the suitable format using the d3.nest function called in the controller
* sample can be found in the 'cashflowrollupCtrl' controller, in which the data is requested using the http request as a JSON object and grouped
* accordingly.
* * dom_element_to_append_to : class name of the div element to which the treemap has to be appended.
* * keyPassed: string element passed as a param, shown at the top og graph as the title of graph.
* * isColorCategorySplitable: set it true if two parent elements are there and both have different color schemes , an false when colorscheme is same throughout
* the graph,example can be found in the positive and negative cashflow graphs together with different coloschemes, if 'true ' then set the colorSchemes
* namely 'positiveColorScheme' and 'negativeColorScheme' manually provided as varibles in the rootscope at the variable declaraions.
* * isForwarUnit: set it 'true' if passed unit is to be placed at the forward of the vaule else false if to be placed at the backwards , else if no value passed then it can be set either true or false
* * * unitName: name of the unit to be placed in the graph, set it "" if no unit is required
*/
function renderTreemap (dataTreeMap,dom_element_to_append_to, titlePassed, keyPassed,isColorCategorySplitable,isForwardUnit, unitName,
defaultColorScheme, positiveColorScheme, negativeColorScheme) {
var treemap_card_width = 800;
var defaults = {
margin: {top: 24, right: 0, bottom: 0, left: 0},
rootname: "TOP",
format: ",d",
title: "",
width: (treemap_card_width ? treemap_card_width : 500),
//height: $(window).height() - 120
height: treemap_card_width * 3/5
};
function main(o, data) {
var root,
opts = $.extend(true, {}, defaults, o),
formatNumber = d3.format(opts.format),
rname = opts.rootname,
margin = opts.margin,
theight = 36 + 16;
$(dom_element_to_append_to).width(opts.width).height(opts.height);
var width = opts.width - margin.left - margin.right,
height = opts.height - margin.top - margin.bottom - theight,
transitioning;
if(!isColorCategorySplitable)
var color = d3.scale.ordinal().range(defaultColorScheme);
else {
var positiveColor = d3.scale.ordinal().range(positiveColorScheme);
var negativeColor = d3.scale.ordinal().range(negativeColorScheme);
}
var x = d3.scale.linear()
.domain([0, width])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, height])
.range([0, height]);
var treemap = d3.layout.treemap()
.children(function(d, depth) { return depth ? null : d._children; })
.sort(function(a, b) { return a.value - b.value; })
.ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
.round(false);
var svg = d3.select(dom_element_to_append_to).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.bottom + margin.top)
.style("margin-left", -margin.left + "px")
.style("margin.right", -margin.right + "px")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.style("shape-rendering", "crispEdges");
var grandparent = svg.append("g")
.attr("class", "grandparent");
grandparent.append("rect")
.attr("y", -margin.top)
.attr("width", width)
.attr("height", margin.top);
grandparent.append("text")
.attr("x", 6)
.attr("y", 6 - margin.top)
.attr("dy", ".85em");
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([0, 0])
.html(function(d) {
if(isForwardUnit)
return "
Category: " + d.key + "
" +
"Value: " + unitName +"" + d3.format(",")(d.value) + "
";
else
return "Category: " + d.key + "
" +
"Value: " + d3.format(",")(d.value) +"" + unitName + "
";
});
svg.call(tip);
if (data instanceof Array) {
root = { key: rname, values: data };
} else {
root = data;
}
initialize(root);
accumulate(root);
layout(root);
display(root);
if (window.parent !== window) {
var myheight = document.documentElement.scrollHeight || document.body.scrollHeight;
window.parent.postMessage({height: myheight}, '*');
}
function initialize(root) {
root.x = root.y = 0;
root.dx = width;
root.dy = height;
root.depth = 0;
}
function accumulate(d) {
return (d._children = d.values)
? d.value = d.values.reduce(function(p, v) { return p + accumulate(v); }, 0)
: d.value;
}
function layout(d) {
if (d._children) {
treemap.nodes({_children: d._children});
d._children.forEach(function(c) {
c.x = d.x + c.x * d.dx;
c.y = d.y + c.y * d.dy;
c.dx *= d.dx;
c.dy *= d.dy;
c.parent = d;
layout(c);
});
}
}
function display(d) {
grandparent
.datum(d.parent)
.on("click", transition)
.select("text")
.text(name(d));
var g1 = svg.insert("g", ".grandparent")
.datum(d)
.attr("class", "depth");
var g = g1.selectAll("g")
.data(d._children)
.enter().append("g");
g.filter(function(d) { return d._children; })
.classed("children", true)
.on("click", transition);
var children = g.selectAll(".child")
.data(function(d) { return d._children || [d]; })
.enter().append("g");
children.append("rect")
.attr("class", "child")
.call(rect)
.append("title")
.text(function(d) { return d.key + " (" + formatNumber(d.value) + ")"; });
children.append("text")
.attr("class", "ctext")
.text(function(d) { return d.key; })
.call(text2);
g.append("rect")
.attr("class", "parent")
.call(rect)
.append("title");
var t = g.append("text")
.attr("class", "ptext")
.attr("dy", "0.90em")
.style("font-size", width * 0.010)
t.append("tspan")
.text(function(d) { return d.key; });
if(isForwardUnit) {
t.append("tspan")
.attr("dy", "1.0em")
.text(function(d) { return unitName + "" +formatNumber(d.value); });
t.call(text);
}
else {
t.append("tspan")
.attr("dy", "1.0em")
.text(function(d) { return formatNumber(d.value) + "" + unitName; });
t.call(text);
}
g.selectAll("rect")
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.style("fill", function(d) {
if(isColorCategorySplitable) {
if(d.parent.key=="Positive Cashflow")
return positiveColor(d.key);
else if(d.parent.key=="Negative Cashflow")
return negativeColor(d.key);
}
else
return color(d.key);
});
function transition(d) {
if (transitioning || !d) return;
transitioning = true;
var g2 = display(d),
t1 = g1.transition().duration(750),
t2 = g2.transition().duration(750);
x.domain([d.x, d.x + d.dx]);
y.domain([d.y, d.y + d.dy]);
svg.style("shape-rendering", null);
svg.selectAll(".depth").sort(function(a, b) { return a.depth - b.depth; });
g2.selectAll("text").style("fill-opacity", 0);
t1.selectAll(".ptext").call(text).style("fill-opacity", 0);
t1.selectAll(".ctext").call(text2).style("fill-opacity", 0);
t2.selectAll(".ptext").call(text).style("fill-opacity", 1);
t2.selectAll(".ctext").call(text2).style("fill-opacity", 1);
t1.selectAll("rect").call(rect);
t2.selectAll("rect").call(rect);
t1.remove().each("end", function() {
svg.style("shape-rendering", "crispEdges");
transitioning = false;
});
}
return g;
}
function text(text) {
text.selectAll("tspan")
.attr("x", function(d) { return x(d.x) + 6; })
text.attr("x", function(d) { return x(d.x) + 6; })
.attr("y", function(d) { return y(d.y) + 6; })
.style("opacity", function(d) { return this.getComputedTextLength() < x(d.x + d.dx) - x(d.x) ? 1 : 0; });
}
function text2(text) {
text.attr("x", function(d) { return x(d.x + d.dx) - this.getComputedTextLength() - 6; })
.attr("y", function(d) { return y(d.y + d.dy) - 6; })
.style("opacity", function(d) { return this.getComputedTextLength() < x(d.x + d.dx) - x(d.x) ? 1 : 0; });
}
function rect(rect) {
rect.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return y(d.y); })
.attr("width", function(d) { return x(d.x + d.dx) - x(d.x); })
.attr("height", function(d) { return y(d.y + d.dy) - y(d.y); });
}
function name(d) {
return d.parent
? name(d.parent) + " / " + d.key + " (" + formatNumber(d.value) + ")"
: d.key + " (" + formatNumber(d.value) + ")";
}
}
main({title: titlePassed}, {key: keyPassed, values: dataTreeMap});
};