1
(function(e){e.jqplot.PieRenderer=function(){e.jqplot.LineRenderer.call(this)};e.jqplot.PieRenderer.prototype=new e.jqplot.LineRenderer();e.jqplot.PieRenderer.prototype.constructor=e.jqplot.PieRenderer;e.jqplot.PieRenderer.prototype.init=function(q,u){this.diameter=null;this.padding=20;this.sliceMargin=0;this.fill=true;this.shadowOffset=2;this.shadowAlpha=0.07;this.shadowDepth=5;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.dataLabels="percent";this.showDataLabels=false;this.dataLabelFormatString=null;this.dataLabelThreshold=3;this.dataLabelPositionFactor=0.52;this.dataLabelNudge=2;this.dataLabelCenterOn=true;this.startAngle=0;this.tickRenderer=e.jqplot.PieTickRenderer;this._drawData=true;this._type="pie";if(q.highlightMouseDown&&q.highlightMouseOver==null){q.highlightMouseOver=false}e.extend(true,this,q);if(this.sliceMargin<0){this.sliceMargin=0}this._diameter=null;this._radius=null;this._sliceAngles=[];this._highlightedPoint=null;if(this.highlightColors.length==0){for(var s=0;s<this.seriesColors.length;s++){var r=e.jqplot.getColorComponents(this.seriesColors[s]);var o=[r[0],r[1],r[2]];var t=o[0]+o[1]+o[2];for(var p=0;p<3;p++){o[p]=(t>570)?o[p]*0.8:o[p]+0.3*(255-o[p]);o[p]=parseInt(o[p],10)}this.highlightColors.push("rgb("+o[0]+","+o[1]+","+o[2]+")")}}this.highlightColorGenerator=new e.jqplot.ColorGenerator(this.highlightColors);u.postParseOptionsHooks.addOnce(m);u.postInitHooks.addOnce(g);u.eventListenerHooks.addOnce("jqplotMouseMove",b);u.eventListenerHooks.addOnce("jqplotMouseDown",a);u.eventListenerHooks.addOnce("jqplotMouseUp",l);u.eventListenerHooks.addOnce("jqplotClick",f);u.eventListenerHooks.addOnce("jqplotRightClick",n);u.postDrawHooks.addOnce(i)};e.jqplot.PieRenderer.prototype.setGridData=function(t){var p=[];var u=[];var o=this.startAngle/180*Math.PI;var s=0;this._drawData=false;for(var r=0;r<this.data.length;r++){if(this.data[r][1]!=0){this._drawData=true}p.push(this.data[r][1]);u.push([this.data[r][0]]);if(r>0){p[r]+=p[r-1]}s+=this.data[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r<p.length;r++){u[r][1]=p[r]*q;u[r][2]=this.data[r][1]/s}this.gridData=u};e.jqplot.PieRenderer.prototype.makeGridData=function(t,u){var p=[];var v=[];var s=0;var o=this.startAngle/180*Math.PI;this._drawData=false;for(var r=0;r<t.length;r++){if(this.data[r][1]!=0){this._drawData=true}p.push(t[r][1]);v.push([t[r][0]]);if(r>0){p[r]+=p[r-1]}s+=t[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r<p.length;r++){v[r][1]=p[r]*q;v[r][2]=t[r][1]/s}return v};function h(o){return Math.sin((o-(o-Math.PI)/8/Math.PI)/2)}function j(u,t,o,v,r){var w=0;var q=t-u;var s=Math.abs(q);var p=o;if(v==false){p+=r}if(p>0&&s>0.01&&s<6.282){w=parseFloat(p)/2/h(q)}return w}e.jqplot.PieRenderer.prototype.drawSlice=function(B,z,y,u,w){if(this._drawData){var p=this._radius;var A=this.fill;var x=this.lineWidth;var s=this.sliceMargin;if(this.fill==false){s+=this.lineWidth}B.save();B.translate(this._center[0],this._center[1]);var D=j(z,y,this.sliceMargin,this.fill,this.lineWidth);var o=D*Math.cos((z+y)/2);var C=D*Math.sin((z+y)/2);if((y-z)<=Math.PI){p-=D}else{p+=D}B.translate(o,C);if(w){for(var v=0,t=this.shadowDepth;v<t;v++){B.save();B.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI),this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));q(p)}for(var v=0,t=this.shadowDepth;v<t;v++){B.restore()}}else{q(p)}B.restore()}function q(r){if(y>6.282+this.startAngle){y=6.282+this.startAngle;if(z>y){z=6.281+this.startAngle}}if(z>=y){return}B.beginPath();B.fillStyle=u;B.strokeStyle=u;B.lineWidth=x;B.arc(0,0,r,z,y,false);B.lineTo(0,0);B.closePath();if(A){B.fill()}else{B.stroke()}}};e.jqplot.PieRenderer.prototype.draw=function(B,z,E,o){var W;var H=(E!=undefined)?E:{};var t=0;var s=0;var N=1;var L=new e.jqplot.ColorGenerator(this.seriesColors);if(E.legendInfo&&E.legendInfo.placement=="insideGrid"){var J=E.legendInfo;switch(J.location){case"nw":t=J.width+J.xoffset;break;case"w":t=J.width+J.xoffset;break;case"sw":t=J.width+J.xoffset;break;case"ne":t=J.width+J.xoffset;N=-1;break;case"e":t=J.width+J.xoffset;N=-1;break;case"se":t=J.width+J.xoffset;N=-1;break;case"n":s=J.height+J.yoffset;break;case"s":s=J.height+J.yoffset;N=-1;break;default:break}}var K=(H.shadow!=undefined)?H.shadow:this.shadow;var A=(H.fill!=undefined)?H.fill:this.fill;var C=B.canvas.width;var I=B.canvas.height;var Q=C-t-2*this.padding;var X=I-s-2*this.padding;var M=Math.min(Q,X);var Y=M;this._sliceAngles=[];var v=this.sliceMargin;if(this.fill==false){v+=this.lineWidth}var q;var G=0;var R,aa,Z,ab;var D=this.startAngle/180*Math.PI;for(var W=0,V=z.length;W<V;W++){aa=(W==0)?D:z[W-1][1]+D;Z=z[W][1]+D;this._sliceAngles.push([aa,Z]);q=j(aa,Z,this.sliceMargin,this.fill,this.lineWidth);if(Math.abs(Z-aa)>Math.PI){G=Math.max(q,G)}}if(this.diameter!=null&&this.diameter>0){this._diameter=this.diameter-2*G}else{this._diameter=Y-2*G}if(this._diameter<6){e.jqplot.log("Diameter of pie too small, not rendering.");return}var S=this._radius=this._diameter/2;this._center=[(C-N*t)/2+N*t+G*Math.cos(D),(I-N*s)/2+N*s+G*Math.sin(D)];if(this.shadow){for(var W=0,V=z.length;W<V;W++){ab="rgba(0,0,0,"+this.shadowAlpha+")";this.renderer.drawSlice.call(this,B,this._sliceAngles[W][0],this._sliceAngles[W][1],ab,true)}}for(var W=0;W<z.length;W++){this.renderer.drawSlice.call(this,B,this._sliceAngles[W][0],this._sliceAngles[W][1],L.next(),false);if(this.showDataLabels&&z[W][2]*100>=this.dataLabelThreshold){var F,U=(this._sliceAngles[W][0]+this._sliceAngles[W][1])/2,T;if(this.dataLabels=="label"){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,z[W][0])}else{if(this.dataLabels=="value"){F=this.dataLabelFormatString||"%d";T=e.jqplot.sprintf(F,this.data[W][1])}else{if(this.dataLabels=="percent"){F=this.dataLabelFormatString||"%d%%";T=e.jqplot.sprintf(F,z[W][2]*100)}else{if(this.dataLabels.constructor==Array){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,this.dataLabels[W])}}}}var p=(this._radius)*this.dataLabelPositionFactor+this.sliceMargin+this.dataLabelNudge;var P=this._center[0]+Math.cos(U)*p+this.canvas._offsets.left;var O=this._center[1]+Math.sin(U)*p+this.canvas._offsets.top;var u=e('<div class="jqplot-pie-series jqplot-data-label" style="position:absolute;">'+T+"</div>").insertBefore(o.eventCanvas._elem);if(this.dataLabelCenterOn){P-=u.width()/2;O-=u.height()/2}else{P-=u.width()*Math.sin(U/2);O-=u.height()/2}P=Math.round(P);O=Math.round(O);u.css({left:P,top:O})}}};e.jqplot.PieAxisRenderer=function(){e.jqplot.LinearAxisRenderer.call(this)};e.jqplot.PieAxisRenderer.prototype=new e.jqplot.LinearAxisRenderer();e.jqplot.PieAxisRenderer.prototype.constructor=e.jqplot.PieAxisRenderer;e.jqplot.PieAxisRenderer.prototype.init=function(o){this.tickRenderer=e.jqplot.PieTickRenderer;e.extend(true,this,o);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};e.jqplot.PieLegendRenderer=function(){e.jqplot.TableLegendRenderer.call(this)};e.jqplot.PieLegendRenderer.prototype=new e.jqplot.TableLegendRenderer();e.jqplot.PieLegendRenderer.prototype.constructor=e.jqplot.PieLegendRenderer;e.jqplot.PieLegendRenderer.prototype.init=function(o){this.numberRows=null;this.numberColumns=null;e.extend(true,this,o)};e.jqplot.PieLegendRenderer.prototype.draw=function(){var r=this;if(this.show){var B=this._series;this._elem=e(document.createElement("table"));this._elem.addClass("jqplot-table-legend");var E={position:"absolute"};if(this.background){E.background=this.background}if(this.border){E.border=this.border}if(this.fontSize){E.fontSize=this.fontSize}if(this.fontFamily){E.fontFamily=this.fontFamily}if(this.textColor){E.textColor=this.textColor}if(this.marginTop!=null){E.marginTop=this.marginTop}if(this.marginBottom!=null){E.marginBottom=this.marginBottom}if(this.marginLeft!=null){E.marginLeft=this.marginLeft}if(this.marginRight!=null){E.marginRight=this.marginRight}this._elem.css(E);var I=false,A=false,o,y;var C=B[0];var p=new e.jqplot.ColorGenerator(C.seriesColors);if(C.show){var J=C.data;if(this.numberRows){o=this.numberRows;if(!this.numberColumns){y=Math.ceil(J.length/o)}else{y=this.numberColumns}}else{if(this.numberColumns){y=this.numberColumns;o=Math.ceil(J.length/this.numberColumns)}else{o=J.length;y=1}}var H,G;var q,w,v;var x,z,F;var D=0;var u,t;for(H=0;H<o;H++){q=e(document.createElement("tr"));q.addClass("jqplot-table-legend");if(A){q.prependTo(this._elem)}else{q.appendTo(this._elem)}for(G=0;G<y;G++){if(D<J.length){x=this.labels[D]||J[D][0].toString();F=p.next();if(!A){if(H>0){I=true}else{I=false}}else{if(H==o-1){I=false}else{I=true}}z=(I)?this.rowSpacing:"0";w=e(document.createElement("td"));w.addClass("jqplot-table-legend jqplot-table-legend-swatch");w.css({textAlign:"center",paddingTop:z});u=e(document.createElement("div"));u.addClass("jqplot-table-legend-swatch-outline");t=e(document.createElement("div"));t.addClass("jqplot-table-legend-swatch");t.css({backgroundColor:F,borderColor:F});w.append(u.append(t));v=e(document.createElement("td"));v.addClass("jqplot-table-legend jqplot-table-legend-label");v.css("paddingTop",z);if(this.escapeHtml){v.text(x)}else{v.html(x)}if(A){v.prependTo(q);w.prependTo(q)}else{w.appendTo(q);v.appendTo(q)}I=true}D++}}}}return this._elem};e.jqplot.PieRenderer.prototype.handleMove=function(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];r.target.trigger("jqplotDataMouseOver",o);if(r.series[o[0]].highlightMouseOver&&!(o[0]==r.plugins.pieRenderer.highlightedSeriesIndex&&o[1]==r.series[o[0]]._highlightedPoint)){r.target.trigger("jqplotDataHighlight",o);d(r,o[0],o[1])}}else{if(s==null){k(r)}}};function c(s,r,p){p=p||{};p.axesDefaults=p.axesDefaults||{};p.legend=p.legend||{};p.seriesDefaults=p.seriesDefaults||{};var o=false;if(p.seriesDefaults.renderer==e.jqplot.PieRenderer){o=true}else{if(p.series){for(var q=0;q<p.series.length;q++){if(p.series[q].renderer==e.jqplot.PieRenderer){o=true}}}}if(o){p.axesDefaults.renderer=e.jqplot.PieAxisRenderer;p.legend.renderer=e.jqplot.PieLegendRenderer;p.legend.preDraw=true;p.seriesDefaults.pointLabels={show:false}}}function g(r,q,o){for(var p=0;p<this.series.length;p++){if(this.series[p].renderer.constructor==e.jqplot.PieRenderer){if(this.series[p].highlightMouseOver){this.series[p].highlightMouseDown=false}}}}function m(o){for(var p=0;p<this.series.length;p++){this.series[p].seriesColors=this.seriesColors;this.series[p].colorGenerator=e.jqplot.colorGenerator}}function d(t,r,q){var p=t.series[r];var o=t.plugins.pieRenderer.highlightCanvas;o._ctx.clearRect(0,0,o._ctx.canvas.width,o._ctx.canvas.height);p._highlightedPoint=q;t.plugins.pieRenderer.highlightedSeriesIndex=r;p.renderer.drawSlice.call(p,o._ctx,p._sliceAngles[q][0],p._sliceAngles[q][1],p.highlightColorGenerator.get(q),false)}function k(q){var o=q.plugins.pieRenderer.highlightCanvas;o._ctx.clearRect(0,0,o._ctx.canvas.width,o._ctx.canvas.height);for(var p=0;p<q.series.length;p++){q.series[p]._highlightedPoint=null}q.plugins.pieRenderer.highlightedSeriesIndex=null;q.target.trigger("jqplotDataUnhighlight")}function b(s,r,v,u,t){if(u){var q=[u.seriesIndex,u.pointIndex,u.data];var p=jQuery.Event("jqplotDataMouseOver");p.pageX=s.pageX;p.pageY=s.pageY;t.target.trigger(p,q);if(t.series[q[0]].highlightMouseOver&&!(q[0]==t.plugins.pieRenderer.highlightedSeriesIndex&&q[1]==t.series[q[0]]._highlightedPoint)){var o=jQuery.Event("jqplotDataHighlight");o.which=s.which;o.pageX=s.pageX;o.pageY=s.pageY;t.target.trigger(o,q);d(t,q[0],q[1])}}else{if(u==null){k(t)}}}function a(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];if(s.series[p[0]].highlightMouseDown&&!(p[0]==s.plugins.pieRenderer.highlightedSeriesIndex&&p[1]==s.series[p[0]]._highlightedPoint)){var o=jQuery.Event("jqplotDataHighlight");o.which=r.which;o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p);d(s,p[0],p[1])}}else{if(t==null){k(s)}}}function l(q,p,t,s,r){var o=r.plugins.pieRenderer.highlightedSeriesIndex;if(o!=null&&r.series[o].highlightMouseDown){k(r)}}function f(r,q,u,t,s){if(t){var p=[t.seriesIndex,t.pointIndex,t.data];var o=jQuery.Event("jqplotDataClick");o.which=r.which;o.pageX=r.pageX;o.pageY=r.pageY;s.target.trigger(o,p)}}function n(s,r,v,u,t){if(u){var q=[u.seriesIndex,u.pointIndex,u.data];var o=t.plugins.pieRenderer.highlightedSeriesIndex;if(o!=null&&t.series[o].highlightMouseDown){k(t)}var p=jQuery.Event("jqplotDataRightClick");p.which=s.which;p.pageX=s.pageX;p.pageY=s.pageY;t.target.trigger(p,q)}}function i(){if(this.plugins.pieRenderer&&this.plugins.pieRenderer.highlightCanvas){this.plugins.pieRenderer.highlightCanvas.resetCanvas();this.plugins.pieRenderer.highlightCanvas=null}this.plugins.pieRenderer={highlightedSeriesIndex:null};this.plugins.pieRenderer.highlightCanvas=new e.jqplot.GenericCanvas();var p=e(this.targetId+" .jqplot-data-label");if(p.length){e(p[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-pieRenderer-highlight-canvas",this._plotDimensions,this))}else{this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-pieRenderer-highlight-canvas",this._plotDimensions,this))}var o=this.plugins.pieRenderer.highlightCanvas.setContext();this.eventCanvas._elem.bind("mouseleave",{plot:this},function(q){k(q.data.plot)})}e.jqplot.preInitHooks.push(c);e.jqplot.PieTickRenderer=function(){e.jqplot.AxisTickRenderer.call(this)};e.jqplot.PieTickRenderer.prototype=new e.jqplot.AxisTickRenderer();e.jqplot.PieTickRenderer.prototype.constructor=e.jqplot.PieTickRenderer})(jQuery);
b'\\ No newline at end of file'
3
* Pure JavaScript plotting plugin using jQuery
8
* Copyright (c) 2009-2012 Chris Leonello
9
* jqPlot is currently available for use in all personal or commercial projects
10
* under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
11
* version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
12
* choose the license that best suits your project and use it accordingly.
14
* Although not required, the author would appreciate an email letting him
15
* know of any substantial use of jqPlot. You can reach the author at:
16
* chris at jqplot dot com or see http://www.jqplot.com/info.php .
18
* If you are feeling kind and generous, consider supporting the project by
19
* making a donation at: http://www.jqplot.com/donate.php .
21
* sprintf functions contained in jqplot.sprintf.js by Ash Searle:
25
* http://hexmen.com/blog/2007/03/printf-sprintf/
26
* http://hexmen.com/js/sprintf.js
27
* The author (Ash Searle) has placed this code in the public domain:
28
* "This code is unrestricted: you are free to use it however you like."
33
* Class: $.jqplot.PieRenderer
34
* Plugin renderer to draw a pie chart.
35
* x values, if present, will be used as slice labels.
36
* y values give slice size.
38
* To use this renderer, you need to include the
39
* pie renderer plugin, for example:
41
* > <script type="text/javascript" src="plugins/jqplot.pieRenderer.js"></script>
43
* Properties described here are passed into the $.jqplot function
44
* as options on the series renderer. For example:
46
* > plot2 = $.jqplot('chart2', [s1, s2], {
48
* > renderer:$.jqplot.PieRenderer,
56
* A pie plot will trigger events on the plot target
57
* according to user interaction. All events return the event object,
58
* the series index, the point (slice) index, and the point data for
59
* the appropriate slice.
61
* 'jqplotDataMouseOver' - triggered when user mouseing over a slice.
62
* 'jqplotDataHighlight' - triggered the first time user mouses over a slice,
63
* if highlighting is enabled.
64
* 'jqplotDataUnhighlight' - triggered when a user moves the mouse out of
65
* a highlighted slice.
66
* 'jqplotDataClick' - triggered when the user clicks on a slice.
67
* 'jqplotDataRightClick' - tiggered when the user right clicks on a slice if
68
* the "captureRightClick" option is set to true on the plot.
70
$.jqplot.PieRenderer = function(){
71
$.jqplot.LineRenderer.call(this);
74
$.jqplot.PieRenderer.prototype = new $.jqplot.LineRenderer();
75
$.jqplot.PieRenderer.prototype.constructor = $.jqplot.PieRenderer;
77
// called with scope of a series
78
$.jqplot.PieRenderer.prototype.init = function(options, plot) {
82
// Outer diameter of the pie, auto computed by default
85
// padding between the pie and plot edges, legend, etc.
88
// angular spacing between pie slices in degrees.
91
// true or false, wether to fil the slices.
94
// offset of the shadow from the slice and offset of
95
// each succesive stroke of the shadow from the last.
96
this.shadowOffset = 2;
98
// transparency of the shadow (0 = transparent, 1 = opaque)
99
this.shadowAlpha = 0.07;
101
// number of strokes to apply to the shadow,
102
// each stroke offset shadowOffset from the last.
103
this.shadowDepth = 5;
104
// prop: highlightMouseOver
105
// True to highlight slice when moused over.
106
// This must be false to enable highlightMouseDown to highlight when clicking on a slice.
107
this.highlightMouseOver = true;
108
// prop: highlightMouseDown
109
// True to highlight when a mouse button is pressed over a slice.
110
// This will be disabled if highlightMouseOver is true.
111
this.highlightMouseDown = false;
112
// prop: highlightColors
113
// an array of colors to use when highlighting a slice.
114
this.highlightColors = [];
116
// Either 'label', 'value', 'percent' or an array of labels to place on the pie slices.
117
// Defaults to percentage of each pie slice.
118
this.dataLabels = 'percent';
119
// prop: showDataLabels
120
// true to show data labels on slices.
121
this.showDataLabels = false;
122
// prop: dataLabelFormatString
123
// Format string for data labels. If none, '%s' is used for "label" and for arrays, '%d' for value and '%d%%' for percentage.
124
this.dataLabelFormatString = null;
125
// prop: dataLabelThreshold
126
// Threshhold in percentage (0-100) of pie area, below which no label will be displayed.
127
// This applies to all label types, not just to percentage labels.
128
this.dataLabelThreshold = 3;
129
// prop: dataLabelPositionFactor
130
// A Multiplier (0-1) of the pie radius which controls position of label on slice.
131
// Increasing will slide label toward edge of pie, decreasing will slide label toward center of pie.
132
this.dataLabelPositionFactor = 0.52;
133
// prop: dataLabelNudge
134
// Number of pixels to slide the label away from (+) or toward (-) the center of the pie.
135
this.dataLabelNudge = 2;
136
// prop: dataLabelCenterOn
137
// True to center the data label at its position.
138
// False to set the inside facing edge of the label at its position.
139
this.dataLabelCenterOn = true;
141
// Angle to start drawing pie in degrees.
142
// According to orientation of canvas coordinate system:
143
// 0 = on the positive x axis
144
// -90 = on the positive y axis.
145
// 90 = on the negaive y axis.
146
// 180 or - 180 = on the negative x axis.
148
this.tickRenderer = $.jqplot.PieTickRenderer;
149
// Used as check for conditions where pie shouldn't be drawn.
150
this._drawData = true;
153
// if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver
154
if (options.highlightMouseDown && options.highlightMouseOver == null) {
155
options.highlightMouseOver = false;
158
$.extend(true, this, options);
160
if (this.sliceMargin < 0) {
161
this.sliceMargin = 0;
164
this._diameter = null;
166
// array of [start,end] angles arrays, one for each slice. In radians.
167
this._sliceAngles = [];
168
// index of the currenty highlighted point, if any
169
this._highlightedPoint = null;
171
// set highlight colors if none provided
172
if (this.highlightColors.length == 0) {
173
for (var i=0; i<this.seriesColors.length; i++){
174
var rgba = $.jqplot.getColorComponents(this.seriesColors[i]);
175
var newrgb = [rgba[0], rgba[1], rgba[2]];
176
var sum = newrgb[0] + newrgb[1] + newrgb[2];
177
for (var j=0; j<3; j++) {
178
// when darkening, lowest color component can be is 60.
179
newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);
180
newrgb[j] = parseInt(newrgb[j], 10);
182
this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')');
186
this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors);
188
plot.postParseOptionsHooks.addOnce(postParseOptions);
189
plot.postInitHooks.addOnce(postInit);
190
plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);
191
plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);
192
plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);
193
plot.eventListenerHooks.addOnce('jqplotClick', handleClick);
194
plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);
195
plot.postDrawHooks.addOnce(postPlotDraw);
198
$.jqplot.PieRenderer.prototype.setGridData = function(plot) {
199
// set gridData property. This will hold angle in radians of each data point.
202
var sa = this.startAngle/180*Math.PI;
204
// don't know if we have any valid data yet, so set plot to not draw.
205
this._drawData = false;
206
for (var i=0; i<this.data.length; i++){
207
if (this.data[i][1] != 0) {
208
// we have data, O.K. to draw.
209
this._drawData = true;
211
stack.push(this.data[i][1]);
212
td.push([this.data[i][0]]);
214
stack[i] += stack[i-1];
216
tot += this.data[i][1];
218
var fact = Math.PI*2/stack[stack.length - 1];
220
for (var i=0; i<stack.length; i++) {
221
td[i][1] = stack[i] * fact;
222
td[i][2] = this.data[i][1]/tot;
227
$.jqplot.PieRenderer.prototype.makeGridData = function(data, plot) {
231
var sa = this.startAngle/180*Math.PI;
232
// don't know if we have any valid data yet, so set plot to not draw.
233
this._drawData = false;
234
for (var i=0; i<data.length; i++){
235
if (this.data[i][1] != 0) {
236
// we have data, O.K. to draw.
237
this._drawData = true;
239
stack.push(data[i][1]);
240
td.push([data[i][0]]);
242
stack[i] += stack[i-1];
246
var fact = Math.PI*2/stack[stack.length - 1];
248
for (var i=0; i<stack.length; i++) {
249
td[i][1] = stack[i] * fact;
250
td[i][2] = data[i][1]/tot;
255
function calcRadiusAdjustment(ang) {
256
return Math.sin((ang - (ang-Math.PI) / 8 / Math.PI )/2.0);
259
function calcRPrime(ang1, ang2, sliceMargin, fill, lineWidth) {
261
var ang = ang2 - ang1;
262
var absang = Math.abs(ang);
263
var sm = sliceMargin;
268
if (sm > 0 && absang > 0.01 && absang < 6.282) {
269
rprime = parseFloat(sm) / 2.0 / calcRadiusAdjustment(ang);
275
$.jqplot.PieRenderer.prototype.drawSlice = function (ctx, ang1, ang2, color, isShadow) {
276
if (this._drawData) {
277
var r = this._radius;
278
var fill = this.fill;
279
var lineWidth = this.lineWidth;
280
var sm = this.sliceMargin;
281
if (this.fill == false) {
282
sm += this.lineWidth;
285
ctx.translate(this._center[0], this._center[1]);
287
var rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);
289
var transx = rprime * Math.cos((ang1 + ang2) / 2.0);
290
var transy = rprime * Math.sin((ang1 + ang2) / 2.0);
292
if ((ang2 - ang1) <= Math.PI) {
299
ctx.translate(transx, transy);
302
for (var i=0, l=this.shadowDepth; i<l; i++) {
304
ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));
307
for (var i=0, l=this.shadowDepth; i<l; i++) {
318
function doDraw (rad) {
319
// Fix for IE and Chrome that can't seem to draw circles correctly.
320
// ang2 should always be <= 2 pi since that is the way the data is converted.
321
// 2Pi = 6.2831853, Pi = 3.1415927
322
if (ang2 > 6.282 + this.startAngle) {
323
ang2 = 6.282 + this.startAngle;
325
ang1 = 6.281 + this.startAngle;
328
// Fix for IE, where it can't seem to handle 0 degree angles. Also avoids
329
// ugly line on unfilled pies.
335
ctx.fillStyle = color;
336
ctx.strokeStyle = color;
337
ctx.lineWidth = lineWidth;
338
ctx.arc(0, 0, rad, ang1, ang2, false);
351
// called with scope of series
352
$.jqplot.PieRenderer.prototype.draw = function (ctx, gd, options, plot) {
354
var opts = (options != undefined) ? options : {};
355
// offset and direction of offset due to legend placement
359
var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);
360
if (options.legendInfo && options.legendInfo.placement == 'insideGrid') {
361
var li = options.legendInfo;
362
switch (li.location) {
364
offx = li.width + li.xoffset;
367
offx = li.width + li.xoffset;
370
offx = li.width + li.xoffset;
373
offx = li.width + li.xoffset;
377
offx = li.width + li.xoffset;
381
offx = li.width + li.xoffset;
385
offy = li.height + li.yoffset;
388
offy = li.height + li.yoffset;
396
var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
397
var fill = (opts.fill != undefined) ? opts.fill : this.fill;
398
var cw = ctx.canvas.width;
399
var ch = ctx.canvas.height;
400
var w = cw - offx - 2 * this.padding;
401
var h = ch - offy - 2 * this.padding;
402
var mindim = Math.min(w,h);
405
// Fixes issue #272. Thanks hugwijst!
406
// reset slice angles array.
407
this._sliceAngles = [];
409
var sm = this.sliceMargin;
410
if (this.fill == false) {
411
sm += this.lineWidth;
417
var ang, ang1, ang2, shadowColor;
418
var sa = this.startAngle / 180 * Math.PI;
420
// have to pre-draw shadows, so loop throgh here and calculate some values also.
421
for (var i=0, l=gd.length; i<l; i++) {
422
ang1 = (i == 0) ? sa : gd[i-1][1] + sa;
423
ang2 = gd[i][1] + sa;
425
this._sliceAngles.push([ang1, ang2]);
427
rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);
429
if (Math.abs(ang2-ang1) > Math.PI) {
430
maxrprime = Math.max(rprime, maxrprime);
434
if (this.diameter != null && this.diameter > 0) {
435
this._diameter = this.diameter - 2*maxrprime;
438
this._diameter = d - 2*maxrprime;
441
// Need to check for undersized pie. This can happen if
442
// plot area too small and legend is too big.
443
if (this._diameter < 6) {
444
$.jqplot.log('Diameter of pie too small, not rendering.');
448
var r = this._radius = this._diameter/2;
450
this._center = [(cw - trans * offx)/2 + trans * offx + maxrprime * Math.cos(sa), (ch - trans*offy)/2 + trans * offy + maxrprime * Math.sin(sa)];
453
for (var i=0, l=gd.length; i<l; i++) {
454
shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')';
455
this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], shadowColor, true);
459
for (var i=0; i<gd.length; i++) {
461
this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], colorGenerator.next(), false);
463
if (this.showDataLabels && gd[i][2]*100 >= this.dataLabelThreshold) {
464
var fstr, avgang = (this._sliceAngles[i][0] + this._sliceAngles[i][1])/2, label;
466
if (this.dataLabels == 'label') {
467
fstr = this.dataLabelFormatString || '%s';
468
label = $.jqplot.sprintf(fstr, gd[i][0]);
470
else if (this.dataLabels == 'value') {
471
fstr = this.dataLabelFormatString || '%d';
472
label = $.jqplot.sprintf(fstr, this.data[i][1]);
474
else if (this.dataLabels == 'percent') {
475
fstr = this.dataLabelFormatString || '%d%%';
476
label = $.jqplot.sprintf(fstr, gd[i][2]*100);
478
else if (this.dataLabels.constructor == Array) {
479
fstr = this.dataLabelFormatString || '%s';
480
label = $.jqplot.sprintf(fstr, this.dataLabels[i]);
483
var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge;
485
var x = this._center[0] + Math.cos(avgang) * fact + this.canvas._offsets.left;
486
var y = this._center[1] + Math.sin(avgang) * fact + this.canvas._offsets.top;
488
var labelelem = $('<div class="jqplot-pie-series jqplot-data-label" style="position:absolute;">' + label + '</div>').insertBefore(plot.eventCanvas._elem);
489
if (this.dataLabelCenterOn) {
490
x -= labelelem.width()/2;
491
y -= labelelem.height()/2;
494
x -= labelelem.width() * Math.sin(avgang/2);
495
y -= labelelem.height()/2;
499
labelelem.css({left: x, top: y});
504
$.jqplot.PieAxisRenderer = function() {
505
$.jqplot.LinearAxisRenderer.call(this);
508
$.jqplot.PieAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();
509
$.jqplot.PieAxisRenderer.prototype.constructor = $.jqplot.PieAxisRenderer;
512
// There are no traditional axes on a pie chart. We just need to provide
513
// dummy objects with properties so the plot will render.
514
// called with scope of axis object.
515
$.jqplot.PieAxisRenderer.prototype.init = function(options){
517
this.tickRenderer = $.jqplot.PieTickRenderer;
518
$.extend(true, this, options);
519
// I don't think I'm going to need _dataBounds here.
520
// have to go Axis scaling in a way to fit chart onto plot area
521
// and provide u2p and p2u functionality for mouse cursor, etc.
522
// for convienence set _dataBounds to 0 and 100 and
523
// set min/max to 0 and 100.
524
this._dataBounds = {min:0, max:100};
527
this.showTicks = false;
529
this.showMark = false;
536
$.jqplot.PieLegendRenderer = function(){
537
$.jqplot.TableLegendRenderer.call(this);
540
$.jqplot.PieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();
541
$.jqplot.PieLegendRenderer.prototype.constructor = $.jqplot.PieLegendRenderer;
544
* Class: $.jqplot.PieLegendRenderer
545
* Legend Renderer specific to pie plots. Set by default
546
* when user creates a pie plot.
548
$.jqplot.PieLegendRenderer.prototype.init = function(options) {
552
// Maximum number of rows in the legend. 0 or null for unlimited.
553
this.numberRows = null;
554
// prop: numberColumns
555
// Maximum number of columns in the legend. 0 or null for unlimited.
556
this.numberColumns = null;
557
$.extend(true, this, options);
560
// called with context of legend
561
$.jqplot.PieLegendRenderer.prototype.draw = function() {
564
var series = this._series;
567
this._elem = $(document.createElement('table'));
568
this._elem.addClass('jqplot-table-legend');
570
var ss = {position:'absolute'};
571
if (this.background) {
572
ss['background'] = this.background;
575
ss['border'] = this.border;
578
ss['fontSize'] = this.fontSize;
580
if (this.fontFamily) {
581
ss['fontFamily'] = this.fontFamily;
583
if (this.textColor) {
584
ss['textColor'] = this.textColor;
586
if (this.marginTop != null) {
587
ss['marginTop'] = this.marginTop;
589
if (this.marginBottom != null) {
590
ss['marginBottom'] = this.marginBottom;
592
if (this.marginLeft != null) {
593
ss['marginLeft'] = this.marginLeft;
595
if (this.marginRight != null) {
596
ss['marginRight'] = this.marginRight;
601
// Pie charts legends don't go by number of series, but by number of data points
602
// in the series. Refactor things here for that.
609
var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors);
613
if (this.numberRows) {
614
nr = this.numberRows;
615
if (!this.numberColumns){
616
nc = Math.ceil(pd.length/nr);
619
nc = this.numberColumns;
622
else if (this.numberColumns) {
623
nc = this.numberColumns;
624
nr = Math.ceil(pd.length/this.numberColumns);
637
for (i=0; i<nr; i++) {
638
tr = $(document.createElement('tr'));
639
tr.addClass('jqplot-table-legend');
642
tr.prependTo(this._elem);
646
tr.appendTo(this._elem);
649
for (j=0; j<nc; j++) {
650
if (idx < pd.length){
651
lt = this.labels[idx] || pd[idx][0].toString();
652
color = colorGenerator.next();
669
rs = (pad) ? this.rowSpacing : '0';
673
td1 = $(document.createElement('td'));
674
td1.addClass('jqplot-table-legend jqplot-table-legend-swatch');
675
td1.css({textAlign: 'center', paddingTop: rs});
677
div0 = $(document.createElement('div'));
678
div0.addClass('jqplot-table-legend-swatch-outline');
679
div1 = $(document.createElement('div'));
680
div1.addClass('jqplot-table-legend-swatch');
681
div1.css({backgroundColor: color, borderColor: color});
682
td1.append(div0.append(div1));
684
td2 = $(document.createElement('td'));
685
td2.addClass('jqplot-table-legend jqplot-table-legend-label');
686
td2.css('paddingTop', rs);
688
if (this.escapeHtml){
712
$.jqplot.PieRenderer.prototype.handleMove = function(ev, gridpos, datapos, neighbor, plot) {
714
var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
715
plot.target.trigger('jqplotDataMouseOver', ins);
716
if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
717
plot.target.trigger('jqplotDataHighlight', ins);
718
highlight (plot, ins[0], ins[1]);
721
else if (neighbor == null) {
727
// this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]);
729
// setup default renderers for axes and legend so user doesn't have to
730
// called with scope of plot
731
function preInit(target, data, options) {
732
options = options || {};
733
options.axesDefaults = options.axesDefaults || {};
734
options.legend = options.legend || {};
735
options.seriesDefaults = options.seriesDefaults || {};
736
// only set these if there is a pie series
738
if (options.seriesDefaults.renderer == $.jqplot.PieRenderer) {
741
else if (options.series) {
742
for (var i=0; i < options.series.length; i++) {
743
if (options.series[i].renderer == $.jqplot.PieRenderer) {
750
options.axesDefaults.renderer = $.jqplot.PieAxisRenderer;
751
options.legend.renderer = $.jqplot.PieLegendRenderer;
752
options.legend.preDraw = true;
753
options.seriesDefaults.pointLabels = {show: false};
757
function postInit(target, data, options) {
758
for (var i=0; i<this.series.length; i++) {
759
if (this.series[i].renderer.constructor == $.jqplot.PieRenderer) {
760
// don't allow mouseover and mousedown at same time.
761
if (this.series[i].highlightMouseOver) {
762
this.series[i].highlightMouseDown = false;
768
// called with scope of plot
769
function postParseOptions(options) {
770
for (var i=0; i<this.series.length; i++) {
771
this.series[i].seriesColors = this.seriesColors;
772
this.series[i].colorGenerator = $.jqplot.colorGenerator;
776
function highlight (plot, sidx, pidx) {
777
var s = plot.series[sidx];
778
var canvas = plot.plugins.pieRenderer.highlightCanvas;
779
canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);
780
s._highlightedPoint = pidx;
781
plot.plugins.pieRenderer.highlightedSeriesIndex = sidx;
782
s.renderer.drawSlice.call(s, canvas._ctx, s._sliceAngles[pidx][0], s._sliceAngles[pidx][1], s.highlightColorGenerator.get(pidx), false);
785
function unhighlight (plot) {
786
var canvas = plot.plugins.pieRenderer.highlightCanvas;
787
canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);
788
for (var i=0; i<plot.series.length; i++) {
789
plot.series[i]._highlightedPoint = null;
791
plot.plugins.pieRenderer.highlightedSeriesIndex = null;
792
plot.target.trigger('jqplotDataUnhighlight');
795
function handleMove(ev, gridpos, datapos, neighbor, plot) {
797
var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
798
var evt1 = jQuery.Event('jqplotDataMouseOver');
799
evt1.pageX = ev.pageX;
800
evt1.pageY = ev.pageY;
801
plot.target.trigger(evt1, ins);
802
if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
803
var evt = jQuery.Event('jqplotDataHighlight');
804
evt.which = ev.which;
805
evt.pageX = ev.pageX;
806
evt.pageY = ev.pageY;
807
plot.target.trigger(evt, ins);
808
highlight (plot, ins[0], ins[1]);
811
else if (neighbor == null) {
816
function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
818
var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
819
if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
820
var evt = jQuery.Event('jqplotDataHighlight');
821
evt.which = ev.which;
822
evt.pageX = ev.pageX;
823
evt.pageY = ev.pageY;
824
plot.target.trigger(evt, ins);
825
highlight (plot, ins[0], ins[1]);
828
else if (neighbor == null) {
833
function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {
834
var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;
835
if (idx != null && plot.series[idx].highlightMouseDown) {
840
function handleClick(ev, gridpos, datapos, neighbor, plot) {
842
var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
843
var evt = jQuery.Event('jqplotDataClick');
844
evt.which = ev.which;
845
evt.pageX = ev.pageX;
846
evt.pageY = ev.pageY;
847
plot.target.trigger(evt, ins);
851
function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
853
var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
854
var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;
855
if (idx != null && plot.series[idx].highlightMouseDown) {
858
var evt = jQuery.Event('jqplotDataRightClick');
859
evt.which = ev.which;
860
evt.pageX = ev.pageX;
861
evt.pageY = ev.pageY;
862
plot.target.trigger(evt, ins);
866
// called within context of plot
867
// create a canvas which we can draw on.
868
// insert it before the eventCanvas, so eventCanvas will still capture events.
869
function postPlotDraw() {
870
// Memory Leaks patch
871
if (this.plugins.pieRenderer && this.plugins.pieRenderer.highlightCanvas) {
872
this.plugins.pieRenderer.highlightCanvas.resetCanvas();
873
this.plugins.pieRenderer.highlightCanvas = null;
876
this.plugins.pieRenderer = {highlightedSeriesIndex:null};
877
this.plugins.pieRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
879
// do we have any data labels? if so, put highlight canvas before those
880
var labels = $(this.targetId+' .jqplot-data-label');
882
$(labels[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));
884
// else put highlight canvas before event canvas.
886
this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));
889
var hctx = this.plugins.pieRenderer.highlightCanvas.setContext();
890
this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });
893
$.jqplot.preInitHooks.push(preInit);
895
$.jqplot.PieTickRenderer = function() {
896
$.jqplot.AxisTickRenderer.call(this);
899
$.jqplot.PieTickRenderer.prototype = new $.jqplot.AxisTickRenderer();
900
$.jqplot.PieTickRenderer.prototype.constructor = $.jqplot.PieTickRenderer;
b'\\ No newline at end of file'