While I am thinking about it I wanted to show off the code I wrote for the dojo piecharting widget I allude to here and here. It follows. A coworker sent out the link here earlier suggesting that pie charts are in fact a really stupid way to try to communicate data. After reading the article I am sold on its logic. It seems like the legend for a pie chart is the real chart and the colorful circle is just some gravy for it if you think about it. Sigh. That said I was in a car crash this evening and some pie sure does sound tasty right now.
define([
"dojo/_base/lang",
"ah/mdo",
"ah/Util",
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/dom",
"dojo/on",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dojo/text!ah/widgets/PieChart.html",
"lib/underscore",
"dojo/dom-style",
"dojo/dom-class",
"dojo/dom-construct",
"dojox/charting/Chart",
"dojox/charting/themes/Distinctive",
"dojox/charting/plot2d/Pie",
"dojox/charting/DataChart",
"dojox/charting/widget/Legend"
], function(lang, mdo, Util, declare, lang, dom, on, _WidgetBase, _TemplatedMixin,
template, _, domStyle, domClass, domConstruct, Chart, defaultTheme,
Pie, DataChart, Legend){
var app;
var legend;
var pieChart;
var pieChartData;
var legendData;
var error;
return declare("ah.widgets.PieChart", [_WidgetBase, _TemplatedMixin], {
templateString: template,
init: function() {
app = this.app;
},
postCreate: function() {
},
setData: function(data) {
pieChartData = data;
legendData = new Array();
var totalRecords = 0;
for (i = 0; i < data.length; i++) {
totalRecords = totalRecords + data[i].y;
}
for (i = 0; i < data.length; i++) {
var number = data[i].y;
var description = data[i].text;
var percentage = "-";
if (totalRecords > 0) {
var piece = (number/totalRecords)*100;
if (piece >= 10) {
percentage = piece.toPrecision(3) + "%";
} else {
percentage = piece.toPrecision(2) + "%";
}
}
legendData.push({ number: number, percentage: percentage, description:
description })
}
},
prepChart: function(theme) {
if(pieChartData) {
if(pieChart) {
pieChart.removeSeries("series");
} else {
pieChart = new Chart(this.chartNode);
}
if (theme) {
pieChart.setTheme(theme);
} else {
pieChart.setTheme(defaultTheme);
}
pieChart.addPlot("default", { type: Pie });
pieChart.addSeries("series",pieChartData);
pieChart.surface.rawNode.setAttribute('width', domStyle.get(this.chartWrapper,
"width"));
pieChart.surface.rawNode.setAttribute('height', domStyle.get(this.chartWrapper,
"height"));
pieChart.render();
pieChart.surface.rawNode.childNodes[1].setAttribute('stroke-opacity','0');
pieChart.surface.rawNode.childNodes[1].setAttribute('fill-opacity','0');
pieChart.surface.rawNode.childNodes[2].setAttribute('stroke-opacity','0');
pieChart.surface.rawNode.childNodes[2].setAttribute('fill-opacity','0');
pieChart.surface.rawNode.childNodes[3].setAttribute('stroke-opacity','0');
pieChart.surface.rawNode.childNodes[3].setAttribute('fill-opacity','0');
Legend({chart:pieChart}, this.legend);
legend = dom.byId("dojox_charting_widget_Legend_0");
if (legend) {
domClass.add(legend, "display-none");
}
} else {
error = "The call to prepChart does not have a preceding call to setData and thus
is moot.";
console.log(error);
}
},
prepLegend: function(table) {
if (pieChartData) {
while (table.hasChildNodes()) {
table.removeChild(table.lastChild);
}
var header = domConstruct.create("tr", {}, table)
domConstruct.create("td", { innerHTML: "quantity & percentage", colspan: 4, class:
"right-padding" }, header);
if (legend) {
var tableRows = legend.childNodes[0].childNodes[0].childNodes;
}
for (i = 0; i < legendData.length; i++) {
var row = domConstruct.create("tr", {}, table);
var legendKey = "";
if (legend) {
legendKey =
legend.childNodes[0].childNodes[0].childNodes[i].childNodes[0].innerHTML;
}
domConstruct.create("td", { innerHTML: legendData[i].number, class:
"data-column" }, row);
domConstruct.create("td", { innerHTML: legendData[i].percentage, class:
"data-column" }, row);
domConstruct.create("td", { innerHTML: legendData[i].description, class:
"description-column" }, row);
domConstruct.create("td", { innerHTML: legendKey }, row);
}
} else {
error = "The call to prepLegend does not have a preceding call to setData and
thus is moot.";
console.log(error);
}
},
getLegendData: function() {
return legendData;
},
getError: function() {
pieChartData = null;
return error;
},
getSvg: function() {
return pieChart.surface.rawNode;
}
});
});
No comments:
Post a Comment