1 //Class c.protovis.ClusteredBarChart : Chart
  2 //This is the custom wrapper class for protovis bar charts
  3 
  4 //Constructor
  5 wso2vis.s.chart.protovis.ClusteredBarChart = 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     this.dataFieldCount = 1;
 16     this.subDataFieldCount = 1;
 17     this.maxDataValue = 50;
 18 }
 19 
 20 // this makes c.protovis.ClusteredBarChart.prototype inherit from Chart
 21 wso2vis.extend(wso2vis.s.chart.protovis.ClusteredBarChart, wso2vis.s.chart.Chart);
 22 
 23 wso2vis.s.chart.protovis.ClusteredBarChart.prototype
 24     .property("dataField")
 25     .property("dataLabel")
 26     .property("subDataField")
 27     .property("subDataValue")
 28     .property("subDataLabel")
 29     .property("ySuffix")
 30     .property("xSuffix");
 31 
 32 //Public function load
 33 //Loads the chart inside the given HTML element
 34 wso2vis.s.chart.protovis.ClusteredBarChart.prototype.load = function (w, h) {
 35     if ( w !== undefined ) {
 36         this.width(w);
 37     }
 38     if ( h !== undefined ) {
 39         this.height(h);
 40     }
 41 
 42     var thisObject = this;
 43 
 44     this.x = pv.Scale.linear(0, this.maxDataValue).range(0, this.width());
 45     this.y = pv.Scale.ordinal(pv.range(this.dataFieldCount)).splitBanded(0, this.height(), 4/5);
 46  
 47     this.vis = new pv.Panel()
 48         .canvas(function() { return thisObject.divEl(); })
 49         .width(function() { return thisObject.width(); })
 50         .height(function() { return thisObject.height(); });
 51 
 52     var chart = this.vis.add(pv.Panel)
 53         .width(function() { return (thisObject.width() - thisObject.paddingLeft() - thisObject.paddingRight()); })
 54         .height(function() { return (thisObject.height() - thisObject.paddingTop() - thisObject.paddingBottom()); })
 55         .top(thisObject.paddingTop())
 56         .bottom(thisObject.paddingBottom())
 57         .left(thisObject.paddingLeft())
 58         .right(thisObject.paddingRight());
 59      
 60     var bar = chart.add(pv.Panel)
 61         .data(function() { return thisObject.getData(thisObject); })
 62         .top(function() { return thisObject.y(this.index); })
 63       .add(pv.Bar)
 64         .data(function(a) { return a; })
 65         .top(function() { return (this.index * thisObject.y.range().band / thisObject.subDataFieldCount); })
 66         .height(function() { return (thisObject.y.range().band / thisObject.subDataFieldCount); })
 67         .left(0)
 68         .width(thisObject.x)
 69         .fillStyle(pv.Colors.category20().by(pv.index))
 70         .title(function() {
 71             var dataObj = thisObject.traverseToDataField(thisObject.data, thisObject.dataField());
 72             if( dataObj instanceof Array ) {
 73                 return thisObject.onTooltip(dataObj[this.parent.index], this.index);
 74             }
 75             else {
 76                 return thisObject.onTooltip(dataObj, this.index);
 77             }
 78         })
 79         .event("click", function() {
 80             var dataObj = thisObject.traverseToDataField(thisObject.data, thisObject.dataField());
 81             if( dataObj instanceof Array ) {
 82                 return thisObject.onClick(dataObj[this.parent.index], this.index);
 83             }
 84             else {
 85                 return thisObject.onClick(dataObj, this.index);
 86             }
 87         });
 88     
 89     /* marks */
 90     bar.anchor("right").add(pv.Label)
 91         .visible(function() { return thisObject.marks(); })
 92         .textStyle("white")
 93         .text(function(d) { return d; });
 94      
 95     chart.add(pv.Label)
 96         .data(function() { return pv.range(thisObject.dataFieldCount); })
 97         .left(0)
 98         .top(function() { return (thisObject.y(this.index) + thisObject.y.range().band / 2); })
 99         .textMargin(5)
100         .textAlign("right")
101         .text(function() { return thisObject.getDataLabel(this.index); })
102         .font(function() { return thisObject.labelFont(); })
103         .textStyle("rgb(0,0,0)");
104      
105     chart.add(pv.Rule)
106         .data(function() { return thisObject.x.ticks(); })
107         .left(function(d) { return (Math.round(thisObject.x(d)) - 0.5); })
108         .strokeStyle(function(d) { return (d ? "rgba(128,128,128,.3)" : "rgba(128,128,128,.8)"); })
109       .add(pv.Rule)
110         .bottom(0)
111         .height(5)
112         .strokeStyle("rgba(128,128,128,1)")
113       .anchor("bottom").add(pv.Label)
114         .text(function(d) { return d.toFixed(); })
115         .font(function() { return thisObject.labelFont(); })
116         .textStyle("rgb(0,0,0)");
117 
118     this.vis.add(pv.Label)
119         .left(this.width() / 2)
120         .visible(function() { return !(thisObject.title() === ""); })
121         .top(16)
122         .textAlign("center")
123         .text(function() { return thisObject.title(); })
124         .font(function() { return thisObject.titleFont(); });
125 };
126 
127 /**
128 * @private
129 */
130 wso2vis.s.chart.protovis.ClusteredBarChart.prototype.titleSpacing = function () {
131     if(this.title() === "") {
132         return 1;
133     }
134     else {
135         return 0.9;
136     }
137 };
138 
139 wso2vis.s.chart.protovis.ClusteredBarChart.prototype.populateData = function (thisObject) {
140 
141     var tmpMaxValHolder = [];
142     var _dataField = thisObject.traverseToDataField(thisObject.data, thisObject.dataField());
143 
144     var dataGrpCount = 1;
145     if( _dataField instanceof Array ) {
146         dataGrpCount = _dataField.length;
147     }
148 
149     thisObject.subDataFieldCount = 1;
150     thisObject.formattedData = pv.range(dataGrpCount).map( genDataMap );
151     thisObject.dataFieldCount = dataGrpCount;
152     thisObject.maxDataValue = tmpMaxValHolder.max() + 5; //to keep bars inside the ruler
153     if (thisObject.maxDataValue < 5) thisObject.maxDataValue = 5; // fixing value repeating issue.
154 
155     thisObject.x.domain(0, thisObject.maxDataValue).range(0, (thisObject.width() - thisObject.paddingLeft() - thisObject.paddingRight()));
156     thisObject.y.domain(pv.range(thisObject.dataFieldCount)).splitBanded(0, (thisObject.height() - thisObject.paddingTop() - thisObject.paddingBottom()), 4/5);
157 
158     function genDataMap(x) {
159         var innerArray = [];
160 
161         var rootObja;
162         if( _dataField instanceof Array ) {
163             rootObja = _dataField[x];
164         }
165         else {
166             rootObja = _dataField;
167         }
168 
169         var _subDataField = thisObject.traverseToDataField(rootObja, thisObject.subDataField());
170 
171         var subDataGrpCount = 1;
172         if( _subDataField instanceof Array ) {
173             subDataGrpCount = _subDataField.length;
174             thisObject.subDataFieldCount = (thisObject.subDataFieldCount < _subDataField.length) ? _subDataField.length : thisObject.subDataFieldCount;
175         }
176 
177         for(var y=0; y<subDataGrpCount; y++) {
178             var rootObjb;
179             if( _subDataField instanceof Array ) {
180                 rootObjb = _subDataField[y];
181             }
182             else {
183                 rootObjb = _subDataField;
184             }
185             var temp = parseInt(thisObject.traverseToDataField(rootObjb, thisObject.subDataValue()));
186             innerArray.push(temp);
187         }
188         tmpMaxValHolder.push(innerArray.max());
189         return innerArray;
190     }
191 };
192 
193 wso2vis.s.chart.protovis.ClusteredBarChart.prototype.getData = function (thisObject) {
194 
195     return thisObject.formattedData;
196 };
197 
198 wso2vis.s.chart.protovis.ClusteredBarChart.prototype.update = function () {
199 
200     this.populateData(this);
201     this.vis.render();
202     if(this.tooltip() === true) {
203         tooltip.init();
204     }
205 };
206 
207 wso2vis.s.chart.protovis.ClusteredBarChart.prototype.getDataLabel = function (i) {
208     if (this.data !== null){
209 
210         var rootObj = this.traverseToDataField(this.data, this.dataField());
211         if( rootObj instanceof Array ) {
212             return  this.traverseToDataField(rootObj[i], this.dataLabel());
213         }
214         else {
215             return  this.traverseToDataField(rootObj, this.dataLabel());
216         }
217     }
218     return i;
219 };
220 
221 wso2vis.s.chart.protovis.ClusteredBarChart.prototype.getSubDataLable = function (i, j) {
222     if (this.data !== null){
223         var rootDataObj;
224         var _dataField = this.traverseToDataField(this.data, this.dataField());
225 
226         if( _dataField instanceof Array ) {
227             rootDataObj = _dataField[i];
228         }
229         else {
230             rootDataObj = _dataField;
231         }
232 
233         var rootSubDataObj = this.traverseToDataField(rootDataObj, this.subDataField());
234 
235         if( rootSubDataObj instanceof Array ) {
236             return this.traverseToDataField(rootSubDataObj[j], this.subDataLabel());
237         }
238         else {
239             return this.traverseToDataField(rootSubDataObj, this.subDataLabel());
240         }
241     }
242     return j;
243 };
244 
245