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