1 //Class c.protovis.ColumnChart : Chart
  2 //This is the custom wrapper class for protovis column charts
  3 
  4 //Constructor
  5 wso2vis.s.chart.protovis.ColumnChart = function(canvas, chartTitle, chartDesc) {
  6     wso2vis.s.chart.Chart.call(this, canvas, chartTitle, chartDesc);
  7 
  8     this.ySuffix("")
  9         .xSuffix("");
 10 
 11     /* @private */
 12     this.vis = null;
 13     this.y = null;
 14     this.x = null;
 15 }
 16 
 17 // this makes c.protovis.ColumnChart.prototype inherits
 18 // from Chart.prototype
 19 wso2vis.extend(wso2vis.s.chart.protovis.ColumnChart, wso2vis.s.chart.Chart);
 20 
 21 wso2vis.s.chart.protovis.ColumnChart.prototype
 22     .property("dataField")
 23     .property("dataValue")
 24     .property("dataLabel")
 25     .property("ySuffix")
 26     .property("xSuffix");
 27 
 28 //Public function load
 29 //Loads the chart inside the given HTML element
 30 wso2vis.s.chart.protovis.ColumnChart.prototype.load = function (w, h) {
 31     if ( w !== undefined ) {
 32         this.width(w);
 33     }
 34     if ( h !== undefined ) {
 35         this.height(h);
 36     }
 37 
 38     var n = 3;
 39     var thisObject = this;
 40 
 41     this.y = pv.Scale.linear(0, 1).range(0, this.height());
 42     this.x = pv.Scale.ordinal(pv.range(n)).splitBanded(0, this.width(), 4/5);
 43  
 44     this.vis = new pv.Panel()
 45         .canvas(function() { return thisObject.divEl(); })
 46         .width(function() { return thisObject.width(); })
 47         .height(function() { return thisObject.height(); });
 48 
 49     var chart = this.vis.add(pv.Panel)
 50         .width(function() { return (thisObject.width() - thisObject.paddingLeft() - thisObject.paddingRight()); })
 51         .height(function() { return (thisObject.height() - thisObject.paddingTop() - thisObject.paddingBottom()); })
 52         .top(thisObject.paddingTop())
 53         .bottom(thisObject.paddingBottom())
 54         .left(thisObject.paddingLeft())
 55         .right(thisObject.paddingRight());
 56      
 57     var bar = chart.add(pv.Bar)
 58         .data(function() { return thisObject.getData(thisObject); })
 59         .left(function() { return thisObject.x(this.index); })
 60         .width(function() { return thisObject.x.range().band; })
 61         .bottom(0)
 62         .height(thisObject.y)
 63         .title(function() { 
 64             var dataObj = thisObject.traverseToDataField(thisObject.data, thisObject.dataField());
 65             if( dataObj instanceof Array ) {
 66                 return thisObject.onTooltip(dataObj[this.index]);
 67             }
 68             else {
 69                 return thisObject.onTooltip(dataObj);
 70             }
 71         })
 72         .event("click", function() { 
 73             var dataObj = thisObject.traverseToDataField(thisObject.data, thisObject.dataField());
 74             if( dataObj instanceof Array ) {
 75                 return thisObject.onClick(dataObj[this.index]);
 76             }
 77             else {
 78                 return thisObject.onClick(dataObj);
 79             }
 80         });
 81      
 82     bar.anchor("top").add(pv.Label)
 83         .visible(function() { return thisObject.marks(); })
 84         .textStyle("white")
 85         .textMargin(5)
 86         .text(function(d) { return d; });
 87 
 88     bar.anchor("bottom").add(pv.Label)
 89         .textMargin(10)
 90         .textBaseline("top")
 91         .textAngle(Math.PI / 2)
 92         .textAlign("left")
 93         .text(function() { return thisObject.getDataLabel(this.index); })
 94         .font(function() { return thisObject.labelFont(); });
 95         /*.add(pv.Bar).fillStyle("rgba(128,128,128,0.1)").height(6);*/
 96      
 97     chart.add(pv.Rule)
 98         .data(function() { return thisObject.y.ticks(); })
 99         .bottom(function(d) { return (Math.round(thisObject.y(d)) - 0.5); })
100         .strokeStyle(function(d) { return (d ? "rgba(128,128,128,.5)" : "#000"); })
101       .add(pv.Rule)
102         .left(0)
103         .width(5)
104         .strokeStyle("rgba(128,128,128,1)")
105       .anchor("left").add(pv.Label)
106         .text(function(d) { return d.toFixed(); })
107         .font(function() { return thisObject.labelFont(); });
108 
109     this.vis.add(pv.Label)
110         .left(this.width() / 2)
111         .visible(function() { return !(thisObject.title() === ""); })
112         .top(16)
113         .textAlign("center")
114         .text(function() { return thisObject.title(); })
115         .font(function() { return thisObject.titleFont(); });
116 };
117 
118 /**
119 * @private
120 */
121 wso2vis.s.chart.protovis.ColumnChart.prototype.titleSpacing = function () {
122     if(this.title() === "") {
123         return 1;
124     }
125     else {
126         return 0.9;
127     }
128 };
129 
130 wso2vis.s.chart.protovis.ColumnChart.prototype.populateData = function (thisObject) {
131     var _dataField = thisObject.traverseToDataField(thisObject.data, thisObject.dataField());
132 
133     var dataGrpCount = 1;
134     if( _dataField instanceof Array ) {
135         dataGrpCount = _dataField.length;
136     }
137 
138     thisObject.formattedData = pv.range(dataGrpCount).map( genDataMap );
139 
140     
141     var maxVal = thisObject.formattedData.max() + 5; //to make sure the bars are inside the rule
142     if (maxVal < 5) maxVal = 5; // fixing value repeating issue.
143 
144     this.y.domain(0, maxVal).range(0, (thisObject.height() - thisObject.paddingTop() - thisObject.paddingBottom()));
145     this.x.domain(pv.range(dataGrpCount)).splitBanded(0, (thisObject.width() - thisObject.paddingLeft() - thisObject.paddingRight()), 4/5);
146     
147     var maxLabelLength = (maxVal == 0) ? 1 : Math.floor(Math.log(maxVal)/Math.log(10)) + 1; //TODO: maxheight will never become 0. But we check it just to be in the safe side. useless?
148     this.vis.left((maxLabelLength*9.5)+5);
149 
150     function genDataMap(x) {
151         var rootObj;
152         if( _dataField instanceof Array ) {
153             rootObj = _dataField[x];
154         }
155         else {
156             rootObj = _dataField;
157         }
158         return parseInt(thisObject.traverseToDataField(rootObj, thisObject.dataValue()));
159     }
160 };
161 
162 wso2vis.s.chart.protovis.ColumnChart.prototype.getData = function (thisObject) {
163     return thisObject.formattedData;
164 };
165 
166 wso2vis.s.chart.protovis.ColumnChart.prototype.update = function () {
167     this.populateData(this);
168     this.vis.render();
169     if(this.tooltip() === true) {
170         tooltip.init();
171     }
172 };
173 
174 wso2vis.s.chart.protovis.ColumnChart.prototype.getDataLabel = function (i) {
175     if (this.data !== null){
176 
177         var rootObj = this.traverseToDataField(this.data, this.dataField());
178         if( rootObj instanceof Array ) {
179             return  this.traverseToDataField(rootObj[i], this.dataLabel());
180         }
181         else {
182             return  this.traverseToDataField(rootObj, this.dataLabel());
183         }
184     }
185     
186     return i;
187 };
188 
189