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