outfielding-jqplot-rails 1.0.8 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +8 -4
  4. data/changes-jqplot.txt +48 -37
  5. data/copyright-jqplot.txt +17 -17
  6. data/lib/outfielding-jqplot-rails/version.rb +1 -1
  7. data/vendor/assets/javascripts/excanvas.js +1438 -1438
  8. data/vendor/assets/javascripts/jqplot-plugins/jqplot.BezierCurveRenderer.js +313 -313
  9. data/vendor/assets/javascripts/jqplot-plugins/jqplot.barRenderer.js +801 -801
  10. data/vendor/assets/javascripts/jqplot-plugins/jqplot.blockRenderer.js +234 -234
  11. data/vendor/assets/javascripts/jqplot-plugins/jqplot.bubbleRenderer.js +758 -758
  12. data/vendor/assets/javascripts/jqplot-plugins/jqplot.canvasAxisLabelRenderer.js +202 -202
  13. data/vendor/assets/javascripts/jqplot-plugins/jqplot.canvasAxisTickRenderer.js +252 -252
  14. data/vendor/assets/javascripts/jqplot-plugins/jqplot.canvasOverlay.js +1020 -1020
  15. data/vendor/assets/javascripts/jqplot-plugins/jqplot.canvasTextRenderer.js +448 -448
  16. data/vendor/assets/javascripts/jqplot-plugins/jqplot.categoryAxisRenderer.js +679 -679
  17. data/vendor/assets/javascripts/jqplot-plugins/jqplot.ciParser.js +115 -115
  18. data/vendor/assets/javascripts/jqplot-plugins/jqplot.cursor.js +1108 -1108
  19. data/vendor/assets/javascripts/jqplot-plugins/jqplot.dateAxisRenderer.js +741 -741
  20. data/vendor/assets/javascripts/jqplot-plugins/jqplot.donutRenderer.js +816 -805
  21. data/vendor/assets/javascripts/jqplot-plugins/jqplot.dragable.js +224 -224
  22. data/vendor/assets/javascripts/jqplot-plugins/jqplot.enhancedLegendRenderer.js +305 -305
  23. data/vendor/assets/javascripts/jqplot-plugins/jqplot.enhancedPieLegendRenderer.js +261 -0
  24. data/vendor/assets/javascripts/jqplot-plugins/jqplot.funnelRenderer.js +942 -942
  25. data/vendor/assets/javascripts/jqplot-plugins/jqplot.highlighter.js +464 -464
  26. data/vendor/assets/javascripts/jqplot-plugins/jqplot.json2.js +475 -475
  27. data/vendor/assets/javascripts/jqplot-plugins/jqplot.logAxisRenderer.js +533 -533
  28. data/vendor/assets/javascripts/jqplot-plugins/jqplot.mekkoAxisRenderer.js +611 -611
  29. data/vendor/assets/javascripts/jqplot-plugins/jqplot.mekkoRenderer.js +437 -437
  30. data/vendor/assets/javascripts/jqplot-plugins/jqplot.meterGaugeRenderer.js +1029 -1029
  31. data/vendor/assets/javascripts/jqplot-plugins/jqplot.mobile.js +2 -2
  32. data/vendor/assets/javascripts/jqplot-plugins/jqplot.ohlcRenderer.js +373 -373
  33. data/vendor/assets/javascripts/jqplot-plugins/jqplot.pieRenderer.js +945 -903
  34. data/vendor/assets/javascripts/jqplot-plugins/jqplot.pointLabels.js +379 -377
  35. data/vendor/assets/javascripts/jqplot-plugins/jqplot.pyramidAxisRenderer.js +728 -728
  36. data/vendor/assets/javascripts/jqplot-plugins/jqplot.pyramidGridRenderer.js +428 -428
  37. data/vendor/assets/javascripts/jqplot-plugins/jqplot.pyramidRenderer.js +513 -513
  38. data/vendor/assets/javascripts/jqplot-plugins/jqplot.trendline.js +222 -222
  39. data/vendor/assets/javascripts/jquery.jqplot.js +11477 -11411
  40. data/vendor/assets/stylesheets/jquery.jqplot.css +259 -259
  41. metadata +9 -10
@@ -1,904 +1,946 @@
1
- /**
2
- * jqPlot
3
- * Pure JavaScript plotting plugin using jQuery
4
- *
5
- * Version: 1.0.8
6
- * Revision: 1250
7
- *
8
- * Copyright (c) 2009-2013 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.
13
- *
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 .
17
- *
18
- * If you are feeling kind and generous, consider supporting the project by
19
- * making a donation at: http://www.jqplot.com/donate.php .
20
- *
21
- * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
22
- *
23
- * version 2007.04.27
24
- * author 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."
29
- *
30
- */
31
- (function($) {
32
- /**
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.
37
- *
38
- * To use this renderer, you need to include the
39
- * pie renderer plugin, for example:
40
- *
41
- * > <script type="text/javascript" src="plugins/jqplot.pieRenderer.js"></script>
42
- *
43
- * Properties described here are passed into the $.jqplot function
44
- * as options on the series renderer. For example:
45
- *
46
- * > plot2 = $.jqplot('chart2', [s1, s2], {
47
- * > seriesDefaults: {
48
- * > renderer:$.jqplot.PieRenderer,
49
- * > rendererOptions:{
50
- * > sliceMargin: 2,
51
- * > startAngle: -90
52
- * > }
53
- * > }
54
- * > });
55
- *
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.
60
- *
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.
69
- */
70
- $.jqplot.PieRenderer = function(){
71
- $.jqplot.LineRenderer.call(this);
72
- };
73
-
74
- $.jqplot.PieRenderer.prototype = new $.jqplot.LineRenderer();
75
- $.jqplot.PieRenderer.prototype.constructor = $.jqplot.PieRenderer;
76
-
77
- // called with scope of a series
78
- $.jqplot.PieRenderer.prototype.init = function(options, plot) {
79
- // Group: Properties
80
- //
81
- // prop: diameter
82
- // Outer diameter of the pie, auto computed by default
83
- this.diameter = null;
84
- // prop: padding
85
- // padding between the pie and plot edges, legend, etc.
86
- this.padding = 20;
87
- // prop: sliceMargin
88
- // angular spacing between pie slices in degrees.
89
- this.sliceMargin = 0;
90
- // prop: fill
91
- // true or false, whether to fil the slices.
92
- this.fill = true;
93
- // prop: shadowOffset
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;
97
- // prop: shadowAlpha
98
- // transparency of the shadow (0 = transparent, 1 = opaque)
99
- this.shadowAlpha = 0.07;
100
- // prop: shadowDepth
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 = [];
115
- // prop: dataLabels
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;
140
- // prop: startAngle
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.
147
- this.startAngle = 0;
148
- this.tickRenderer = $.jqplot.PieTickRenderer;
149
- // Used as check for conditions where pie shouldn't be drawn.
150
- this._drawData = true;
151
- this._type = 'pie';
152
-
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;
156
- }
157
-
158
- $.extend(true, this, options);
159
-
160
- if (this.sliceMargin < 0) {
161
- this.sliceMargin = 0;
162
- }
163
-
164
- this._diameter = null;
165
- this._radius = 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;
170
-
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);
181
- }
182
- this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')');
183
- }
184
- }
185
-
186
- this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors);
187
-
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);
196
- };
197
-
198
- $.jqplot.PieRenderer.prototype.setGridData = function(plot) {
199
- // set gridData property. This will hold angle in radians of each data point.
200
- var stack = [];
201
- var td = [];
202
- var sa = this.startAngle/180*Math.PI;
203
- var tot = 0;
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;
210
- }
211
- stack.push(this.data[i][1]);
212
- td.push([this.data[i][0]]);
213
- if (i>0) {
214
- stack[i] += stack[i-1];
215
- }
216
- tot += this.data[i][1];
217
- }
218
- var fact = Math.PI*2/stack[stack.length - 1];
219
-
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;
223
- }
224
- this.gridData = td;
225
- };
226
-
227
- $.jqplot.PieRenderer.prototype.makeGridData = function(data, plot) {
228
- var stack = [];
229
- var td = [];
230
- var tot = 0;
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;
238
- }
239
- stack.push(data[i][1]);
240
- td.push([data[i][0]]);
241
- if (i>0) {
242
- stack[i] += stack[i-1];
243
- }
244
- tot += data[i][1];
245
- }
246
- var fact = Math.PI*2/stack[stack.length - 1];
247
-
248
- for (var i=0; i<stack.length; i++) {
249
- td[i][1] = stack[i] * fact;
250
- td[i][2] = data[i][1]/tot;
251
- }
252
- return td;
253
- };
254
-
255
- function calcRadiusAdjustment(ang) {
256
- return Math.sin((ang - (ang-Math.PI) / 8 / Math.PI )/2.0);
257
- }
258
-
259
- function calcRPrime(ang1, ang2, sliceMargin, fill, lineWidth) {
260
- var rprime = 0;
261
- var ang = ang2 - ang1;
262
- var absang = Math.abs(ang);
263
- var sm = sliceMargin;
264
- if (fill == false) {
265
- sm += lineWidth;
266
- }
267
-
268
- if (sm > 0 && absang > 0.01 && absang < 6.282) {
269
- rprime = parseFloat(sm) / 2.0 / calcRadiusAdjustment(ang);
270
- }
271
-
272
- return rprime;
273
- }
274
-
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;
283
- }
284
- ctx.save();
285
- ctx.translate(this._center[0], this._center[1]);
286
-
287
- var rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);
288
-
289
- var transx = rprime * Math.cos((ang1 + ang2) / 2.0);
290
- var transy = rprime * Math.sin((ang1 + ang2) / 2.0);
291
-
292
- if ((ang2 - ang1) <= Math.PI) {
293
- r -= rprime;
294
- }
295
- else {
296
- r += rprime;
297
- }
298
-
299
- ctx.translate(transx, transy);
300
-
301
- if (isShadow) {
302
- for (var i=0, l=this.shadowDepth; i<l; i++) {
303
- ctx.save();
304
- ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));
305
- doDraw(r);
306
- }
307
- for (var i=0, l=this.shadowDepth; i<l; i++) {
308
- ctx.restore();
309
- }
310
- }
311
-
312
- else {
313
- doDraw(r);
314
- }
315
- ctx.restore();
316
- }
317
-
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;
324
- if (ang1 > ang2) {
325
- ang1 = 6.281 + this.startAngle;
326
- }
327
- }
328
- // Fix for IE, where it can't seem to handle 0 degree angles. Also avoids
329
- // ugly line on unfilled pies.
330
- if (ang1 >= ang2) {
331
- return;
332
- }
333
-
334
- ctx.beginPath();
335
- ctx.fillStyle = color;
336
- ctx.strokeStyle = color;
337
- ctx.lineWidth = lineWidth;
338
- ctx.arc(0, 0, rad, ang1, ang2, false);
339
- ctx.lineTo(0,0);
340
- ctx.closePath();
341
-
342
- if (fill) {
343
- ctx.fill();
344
- }
345
- else {
346
- ctx.stroke();
347
- }
348
- }
349
- };
350
-
351
- // called with scope of series
352
- $.jqplot.PieRenderer.prototype.draw = function (ctx, gd, options, plot) {
353
- var i;
354
- var opts = (options != undefined) ? options : {};
355
- // offset and direction of offset due to legend placement
356
- var offx = 0;
357
- var offy = 0;
358
- var trans = 1;
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) {
363
- case 'nw':
364
- offx = li.width + li.xoffset;
365
- break;
366
- case 'w':
367
- offx = li.width + li.xoffset;
368
- break;
369
- case 'sw':
370
- offx = li.width + li.xoffset;
371
- break;
372
- case 'ne':
373
- offx = li.width + li.xoffset;
374
- trans = -1;
375
- break;
376
- case 'e':
377
- offx = li.width + li.xoffset;
378
- trans = -1;
379
- break;
380
- case 'se':
381
- offx = li.width + li.xoffset;
382
- trans = -1;
383
- break;
384
- case 'n':
385
- offy = li.height + li.yoffset;
386
- break;
387
- case 's':
388
- offy = li.height + li.yoffset;
389
- trans = -1;
390
- break;
391
- default:
392
- break;
393
- }
394
- }
395
-
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);
403
- var d = mindim;
404
-
405
- // Fixes issue #272. Thanks hugwijst!
406
- // reset slice angles array.
407
- this._sliceAngles = [];
408
-
409
- var sm = this.sliceMargin;
410
- if (this.fill == false) {
411
- sm += this.lineWidth;
412
- }
413
-
414
- var rprime;
415
- var maxrprime = 0;
416
-
417
- var ang, ang1, ang2, shadowColor;
418
- var sa = this.startAngle / 180 * Math.PI;
419
-
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;
424
-
425
- this._sliceAngles.push([ang1, ang2]);
426
-
427
- rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);
428
-
429
- if (Math.abs(ang2-ang1) > Math.PI) {
430
- maxrprime = Math.max(rprime, maxrprime);
431
- }
432
- }
433
-
434
- if (this.diameter != null && this.diameter > 0) {
435
- this._diameter = this.diameter - 2*maxrprime;
436
- }
437
- else {
438
- this._diameter = d - 2*maxrprime;
439
- }
440
-
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.');
445
- return;
446
- }
447
-
448
- var r = this._radius = this._diameter/2;
449
-
450
- this._center = [(cw - trans * offx)/2 + trans * offx + maxrprime * Math.cos(sa), (ch - trans*offy)/2 + trans * offy + maxrprime * Math.sin(sa)];
451
-
452
- if (this.shadow) {
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);
456
- }
457
- }
458
-
459
- for (var i=0; i<gd.length; i++) {
460
-
461
- this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], colorGenerator.next(), false);
462
-
463
- if (this.showDataLabels && gd[i][2]*100 >= this.dataLabelThreshold) {
464
- var fstr, avgang = (this._sliceAngles[i][0] + this._sliceAngles[i][1])/2, label;
465
-
466
- if (this.dataLabels == 'label') {
467
- fstr = this.dataLabelFormatString || '%s';
468
- label = $.jqplot.sprintf(fstr, gd[i][0]);
469
- }
470
- else if (this.dataLabels == 'value') {
471
- fstr = this.dataLabelFormatString || '%d';
472
- label = $.jqplot.sprintf(fstr, this.data[i][1]);
473
- }
474
- else if (this.dataLabels == 'percent') {
475
- fstr = this.dataLabelFormatString || '%d%%';
476
- label = $.jqplot.sprintf(fstr, gd[i][2]*100);
477
- }
478
- else if (this.dataLabels.constructor == Array) {
479
- fstr = this.dataLabelFormatString || '%s';
480
- label = $.jqplot.sprintf(fstr, this.dataLabels[i]);
481
- }
482
-
483
- var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge;
484
-
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;
487
-
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;
492
- }
493
- else {
494
- x -= labelelem.width() * Math.sin(avgang/2);
495
- y -= labelelem.height()/2;
496
- }
497
- x = Math.round(x);
498
- y = Math.round(y);
499
- labelelem.css({left: x, top: y});
500
- }
501
- }
502
- };
503
-
504
- $.jqplot.PieAxisRenderer = function() {
505
- $.jqplot.LinearAxisRenderer.call(this);
506
- };
507
-
508
- $.jqplot.PieAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();
509
- $.jqplot.PieAxisRenderer.prototype.constructor = $.jqplot.PieAxisRenderer;
510
-
511
-
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){
516
- //
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};
525
- this.min = 0;
526
- this.max = 100;
527
- this.showTicks = false;
528
- this.ticks = [];
529
- this.showMark = false;
530
- this.show = false;
531
- };
532
-
533
-
534
-
535
-
536
- $.jqplot.PieLegendRenderer = function(){
537
- $.jqplot.TableLegendRenderer.call(this);
538
- };
539
-
540
- $.jqplot.PieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();
541
- $.jqplot.PieLegendRenderer.prototype.constructor = $.jqplot.PieLegendRenderer;
542
-
543
- /**
544
- * Class: $.jqplot.PieLegendRenderer
545
- * Legend Renderer specific to pie plots. Set by default
546
- * when user creates a pie plot.
547
- */
548
- $.jqplot.PieLegendRenderer.prototype.init = function(options) {
549
- // Group: Properties
550
- //
551
- // prop: numberRows
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);
558
- };
559
-
560
- // called with context of legend
561
- $.jqplot.PieLegendRenderer.prototype.draw = function() {
562
- var legend = this;
563
- if (this.show) {
564
- var series = this._series;
565
-
566
-
567
- this._elem = $(document.createElement('table'));
568
- this._elem.addClass('jqplot-table-legend');
569
-
570
- var ss = {position:'absolute'};
571
- if (this.background) {
572
- ss['background'] = this.background;
573
- }
574
- if (this.border) {
575
- ss['border'] = this.border;
576
- }
577
- if (this.fontSize) {
578
- ss['fontSize'] = this.fontSize;
579
- }
580
- if (this.fontFamily) {
581
- ss['fontFamily'] = this.fontFamily;
582
- }
583
- if (this.textColor) {
584
- ss['textColor'] = this.textColor;
585
- }
586
- if (this.marginTop != null) {
587
- ss['marginTop'] = this.marginTop;
588
- }
589
- if (this.marginBottom != null) {
590
- ss['marginBottom'] = this.marginBottom;
591
- }
592
- if (this.marginLeft != null) {
593
- ss['marginLeft'] = this.marginLeft;
594
- }
595
- if (this.marginRight != null) {
596
- ss['marginRight'] = this.marginRight;
597
- }
598
-
599
- this._elem.css(ss);
600
-
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.
603
-
604
- var pad = false,
605
- reverse = false,
606
- nr,
607
- nc;
608
- var s = series[0];
609
- var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors);
610
-
611
- if (s.show) {
612
- var pd = s.data;
613
- if (this.numberRows) {
614
- nr = this.numberRows;
615
- if (!this.numberColumns){
616
- nc = Math.ceil(pd.length/nr);
617
- }
618
- else{
619
- nc = this.numberColumns;
620
- }
621
- }
622
- else if (this.numberColumns) {
623
- nc = this.numberColumns;
624
- nr = Math.ceil(pd.length/this.numberColumns);
625
- }
626
- else {
627
- nr = pd.length;
628
- nc = 1;
629
- }
630
-
631
- var i, j;
632
- var tr, td1, td2;
633
- var lt, rs, color;
634
- var idx = 0;
635
- var div0, div1;
636
-
637
- for (i=0; i<nr; i++) {
638
- tr = $(document.createElement('tr'));
639
- tr.addClass('jqplot-table-legend');
640
-
641
- if (reverse){
642
- tr.prependTo(this._elem);
643
- }
644
-
645
- else{
646
- tr.appendTo(this._elem);
647
- }
648
-
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();
653
- if (!reverse){
654
- if (i>0){
655
- pad = true;
656
- }
657
- else{
658
- pad = false;
659
- }
660
- }
661
- else{
662
- if (i == nr -1){
663
- pad = false;
664
- }
665
- else{
666
- pad = true;
667
- }
668
- }
669
- rs = (pad) ? this.rowSpacing : '0';
670
-
671
-
672
-
673
- td1 = $(document.createElement('td'));
674
- td1.addClass('jqplot-table-legend jqplot-table-legend-swatch');
675
- td1.css({textAlign: 'center', paddingTop: rs});
676
-
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));
683
-
684
- td2 = $(document.createElement('td'));
685
- td2.addClass('jqplot-table-legend jqplot-table-legend-label');
686
- td2.css('paddingTop', rs);
687
-
688
- if (this.escapeHtml){
689
- td2.text(lt);
690
- }
691
- else {
692
- td2.html(lt);
693
- }
694
- if (reverse) {
695
- td2.prependTo(tr);
696
- td1.prependTo(tr);
697
- }
698
- else {
699
- td1.appendTo(tr);
700
- td2.appendTo(tr);
701
- }
702
- pad = true;
703
- }
704
- idx++;
705
- }
706
- }
707
- }
708
- }
709
- return this._elem;
710
- };
711
-
712
- $.jqplot.PieRenderer.prototype.handleMove = function(ev, gridpos, datapos, neighbor, plot) {
713
- if (neighbor) {
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]);
719
- }
720
- }
721
- else if (neighbor == null) {
722
- unhighlight (plot);
723
- }
724
- };
725
-
726
-
727
- // this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]);
728
-
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
737
- var setopts = false;
738
- if (options.seriesDefaults.renderer == $.jqplot.PieRenderer) {
739
- setopts = true;
740
- }
741
- else if (options.series) {
742
- for (var i=0; i < options.series.length; i++) {
743
- if (options.series[i].renderer == $.jqplot.PieRenderer) {
744
- setopts = true;
745
- }
746
- }
747
- }
748
-
749
- if (setopts) {
750
- options.axesDefaults.renderer = $.jqplot.PieAxisRenderer;
751
- options.legend.renderer = $.jqplot.PieLegendRenderer;
752
- options.legend.preDraw = true;
753
- options.seriesDefaults.pointLabels = {show: false};
754
- }
755
- }
756
-
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;
763
- }
764
- }
765
- }
766
- }
767
-
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;
773
- }
774
- }
775
-
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);
783
- }
784
-
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;
790
- }
791
- plot.plugins.pieRenderer.highlightedSeriesIndex = null;
792
- plot.target.trigger('jqplotDataUnhighlight');
793
- }
794
-
795
- function handleMove(ev, gridpos, datapos, neighbor, plot) {
796
- if (neighbor) {
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]);
809
- }
810
- }
811
- else if (neighbor == null) {
812
- unhighlight (plot);
813
- }
814
- }
815
-
816
- function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
817
- if (neighbor) {
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]);
826
- }
827
- }
828
- else if (neighbor == null) {
829
- unhighlight (plot);
830
- }
831
- }
832
-
833
- function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {
834
- var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;
835
- if (idx != null && plot.series[idx].highlightMouseDown) {
836
- unhighlight(plot);
837
- }
838
- }
839
-
840
- function handleClick(ev, gridpos, datapos, neighbor, plot) {
841
- if (neighbor) {
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);
848
- }
849
- }
850
-
851
- function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
852
- if (neighbor) {
853
- var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
854
- var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;
855
- if (idx != null && plot.series[idx].highlightMouseDown) {
856
- unhighlight(plot);
857
- }
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);
863
- }
864
- }
865
-
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;
874
- }
875
-
876
- this.plugins.pieRenderer = {highlightedSeriesIndex:null};
877
- this.plugins.pieRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
878
-
879
- // do we have any data labels? if so, put highlight canvas before those
880
- var labels = $(this.targetId+' .jqplot-data-label');
881
- if (labels.length) {
882
- $(labels[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));
883
- }
884
- // else put highlight canvas before event canvas.
885
- else {
886
- this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));
887
- }
888
-
889
- var hctx = this.plugins.pieRenderer.highlightCanvas.setContext();
890
- this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });
891
- }
892
-
893
- $.jqplot.preInitHooks.push(preInit);
894
-
895
- $.jqplot.PieTickRenderer = function() {
896
- $.jqplot.AxisTickRenderer.call(this);
897
- };
898
-
899
- $.jqplot.PieTickRenderer.prototype = new $.jqplot.AxisTickRenderer();
900
- $.jqplot.PieTickRenderer.prototype.constructor = $.jqplot.PieTickRenderer;
901
-
902
- })(jQuery);
903
-
1
+ /**
2
+ * jqPlot
3
+ * Pure JavaScript plotting plugin using jQuery
4
+ *
5
+ * Version: 1.0.9
6
+ * Revision: d96a669
7
+ *
8
+ * Copyright (c) 2009-2016 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.
13
+ *
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 .
17
+ *
18
+ * If you are feeling kind and generous, consider supporting the project by
19
+ * making a donation at: http://www.jqplot.com/donate.php .
20
+ *
21
+ * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
22
+ *
23
+ * version 2007.04.27
24
+ * author 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."
29
+ *
30
+ */
31
+ (function($) {
32
+ /**
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.
37
+ *
38
+ * To use this renderer, you need to include the
39
+ * pie renderer plugin, for example:
40
+ *
41
+ * > <script type="text/javascript" src="plugins/jqplot.pieRenderer.js"></script>
42
+ *
43
+ * Properties described here are passed into the $.jqplot function
44
+ * as options on the series renderer. For example:
45
+ *
46
+ * > plot2 = $.jqplot('chart2', [s1, s2], {
47
+ * > seriesDefaults: {
48
+ * > renderer:$.jqplot.PieRenderer,
49
+ * > rendererOptions:{
50
+ * > sliceMargin: 2,
51
+ * > startAngle: -90
52
+ * > }
53
+ * > }
54
+ * > });
55
+ *
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.
60
+ *
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
+ * 'jqplotLegendHighlight' - triggered the first time user mouses over a legend,
67
+ * if highlighting is enabled.
68
+ * 'jqplotLegendUnhighlight' - triggered when a user moves the mouse out of
69
+ * a highlighted legend.
70
+ * 'jqplotDataClick' - triggered when the user clicks on a slice.
71
+ * 'jqplotDataRightClick' - tiggered when the user right clicks on a slice if
72
+ * the "captureRightClick" option is set to true on the plot.
73
+ */
74
+ $.jqplot.PieRenderer = function(){
75
+ $.jqplot.LineRenderer.call(this);
76
+ };
77
+
78
+ $.jqplot.PieRenderer.prototype = new $.jqplot.LineRenderer();
79
+ $.jqplot.PieRenderer.prototype.constructor = $.jqplot.PieRenderer;
80
+
81
+ // called with scope of a series
82
+ $.jqplot.PieRenderer.prototype.init = function(options, plot) {
83
+ // Group: Properties
84
+ //
85
+ // prop: diameter
86
+ // Outer diameter of the pie, auto computed by default
87
+ this.diameter = null;
88
+ // prop: padding
89
+ // padding between the pie and plot edges, legend, etc.
90
+ this.padding = 20;
91
+ // prop: sliceMargin
92
+ // angular spacing between pie slices in degrees.
93
+ this.sliceMargin = 0;
94
+ // prop: fill
95
+ // true or false, whether to fil the slices.
96
+ this.fill = true;
97
+ // prop: shadowOffset
98
+ // offset of the shadow from the slice and offset of
99
+ // each succesive stroke of the shadow from the last.
100
+ this.shadowOffset = 2;
101
+ // prop: shadowAlpha
102
+ // transparency of the shadow (0 = transparent, 1 = opaque)
103
+ this.shadowAlpha = 0.07;
104
+ // prop: shadowDepth
105
+ // number of strokes to apply to the shadow,
106
+ // each stroke offset shadowOffset from the last.
107
+ this.shadowDepth = 5;
108
+ // prop: highlightMouseOver
109
+ // True to highlight slice when moused over.
110
+ // This must be false to enable highlightMouseDown to highlight when clicking on a slice.
111
+ this.highlightMouseOver = true;
112
+ // prop: highlightMouseDown
113
+ // True to highlight when a mouse button is pressed over a slice.
114
+ // This will be disabled if highlightMouseOver is true.
115
+ this.highlightMouseDown = false;
116
+ // prop: highlightColors
117
+ // an array of colors to use when highlighting a slice.
118
+ this.highlightColors = [];
119
+ // prop: dataLabels
120
+ // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices.
121
+ // Defaults to percentage of each pie slice.
122
+ this.dataLabels = 'percent';
123
+ // prop: showDataLabels
124
+ // true to show data labels on slices.
125
+ this.showDataLabels = false;
126
+ // prop: dataLabelFormatString
127
+ // Format string for data labels. If none, '%s' is used for "label" and for arrays, '%d' for value and '%d%%' for percentage.
128
+ this.dataLabelFormatString = null;
129
+ // prop: dataLabelThreshold
130
+ // Threshhold in percentage (0-100) of pie area, below which no label will be displayed.
131
+ // This applies to all label types, not just to percentage labels.
132
+ this.dataLabelThreshold = 3;
133
+ // prop: dataLabelPositionFactor
134
+ // A Multiplier (0-1) of the pie radius which controls position of label on slice.
135
+ // Increasing will slide label toward edge of pie, decreasing will slide label toward center of pie.
136
+ this.dataLabelPositionFactor = 0.52;
137
+ // prop: dataLabelNudge
138
+ // Number of pixels to slide the label away from (+) or toward (-) the center of the pie.
139
+ this.dataLabelNudge = 2;
140
+ // prop: dataLabelCenterOn
141
+ // True to center the data label at its position.
142
+ // False to set the inside facing edge of the label at its position.
143
+ this.dataLabelCenterOn = true;
144
+ // prop: startAngle
145
+ // Angle to start drawing pie in degrees.
146
+ // According to orientation of canvas coordinate system:
147
+ // 0 = on the positive x axis
148
+ // -90 = on the positive y axis.
149
+ // 90 = on the negaive y axis.
150
+ // 180 or - 180 = on the negative x axis.
151
+ this.startAngle = 0;
152
+ this.tickRenderer = $.jqplot.PieTickRenderer;
153
+ // prop: showSlice
154
+ // Array for whether the pie chart slice for a data element should be displayed.
155
+ // Containsg true or false for each data element. If not specified, defaults to true.
156
+ this.showSlice = [];
157
+ // Used as check for conditions where pie shouldn't be drawn.
158
+ this._drawData = true;
159
+ this._type = 'pie';
160
+
161
+ // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver
162
+ if (options.highlightMouseDown && options.highlightMouseOver == null) {
163
+ options.highlightMouseOver = false;
164
+ }
165
+
166
+ $.extend(true, this, options);
167
+
168
+ if (this.sliceMargin < 0) {
169
+ this.sliceMargin = 0;
170
+ }
171
+
172
+ this._diameter = null;
173
+ this._radius = null;
174
+ // array of [start,end] angles arrays, one for each slice. In radians.
175
+ this._sliceAngles = [];
176
+ // index of the currenty highlighted point, if any
177
+ this._highlightedPoint = null;
178
+
179
+ // set highlight colors if none provided
180
+ if (this.highlightColors.length == 0) {
181
+ for (var i=0; i<this.seriesColors.length; i++){
182
+ var rgba = $.jqplot.getColorComponents(this.seriesColors[i]);
183
+ var newrgb = [rgba[0], rgba[1], rgba[2]];
184
+ var sum = newrgb[0] + newrgb[1] + newrgb[2];
185
+ for (var j=0; j<3; j++) {
186
+ // when darkening, lowest color component can be is 60.
187
+ newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);
188
+ newrgb[j] = parseInt(newrgb[j], 10);
189
+ }
190
+ this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')');
191
+ }
192
+ }
193
+
194
+ this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors);
195
+
196
+ plot.postParseOptionsHooks.addOnce(postParseOptions);
197
+ plot.postInitHooks.addOnce(postInit);
198
+ plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);
199
+ plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);
200
+ plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);
201
+ plot.eventListenerHooks.addOnce('jqplotClick', handleClick);
202
+ plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);
203
+ plot.postDrawHooks.addOnce(postPlotDraw);
204
+ };
205
+
206
+ $.jqplot.PieRenderer.prototype.setGridData = function(plot) {
207
+ // set gridData property. This will hold angle in radians of each data point.
208
+ var stack = [];
209
+ var td = [];
210
+ var sa = this.startAngle/180*Math.PI;
211
+ var tot = 0;
212
+ // don't know if we have any valid data yet, so set plot to not draw.
213
+ this._drawData = false;
214
+ for (var i=0; i<this.data.length; i++){
215
+ if (this.data[i][1] != 0) {
216
+ // we have data, O.K. to draw.
217
+ this._drawData = true;
218
+ if (this.showSlice[i] === undefined) {
219
+ this.showSlice[i] = true;
220
+ }
221
+ }
222
+ stack.push(this.data[i][1]);
223
+ td.push([this.data[i][0]]);
224
+ if (i>0) {
225
+ stack[i] += stack[i-1];
226
+ }
227
+ tot += this.data[i][1];
228
+ }
229
+ var fact = Math.PI*2/stack[stack.length - 1];
230
+
231
+ for (var i=0; i<stack.length; i++) {
232
+ td[i][1] = stack[i] * fact;
233
+ td[i][2] = this.data[i][1]/tot;
234
+ }
235
+ this.gridData = td;
236
+ };
237
+
238
+ $.jqplot.PieRenderer.prototype.makeGridData = function(data, plot) {
239
+ var stack = [];
240
+ var td = [];
241
+ var tot = 0;
242
+ var sa = this.startAngle/180*Math.PI;
243
+ // don't know if we have any valid data yet, so set plot to not draw.
244
+ this._drawData = false;
245
+ for (var i=0; i<data.length; i++){
246
+ if (this.data[i][1] != 0) {
247
+ // we have data, O.K. to draw.
248
+ this._drawData = true;
249
+ }
250
+ stack.push(data[i][1]);
251
+ td.push([data[i][0]]);
252
+ if (i>0) {
253
+ stack[i] += stack[i-1];
254
+ }
255
+ tot += data[i][1];
256
+ }
257
+ var fact = Math.PI*2/stack[stack.length - 1];
258
+
259
+ for (var i=0; i<stack.length; i++) {
260
+ td[i][1] = stack[i] * fact;
261
+ td[i][2] = data[i][1]/tot;
262
+ }
263
+ return td;
264
+ };
265
+
266
+ function calcRadiusAdjustment(ang) {
267
+ return Math.sin((ang - (ang-Math.PI) / 8 / Math.PI )/2.0);
268
+ }
269
+
270
+ function calcRPrime(ang1, ang2, sliceMargin, fill, lineWidth) {
271
+ var rprime = 0;
272
+ var ang = ang2 - ang1;
273
+ var absang = Math.abs(ang);
274
+ var sm = sliceMargin;
275
+ if (fill == false) {
276
+ sm += lineWidth;
277
+ }
278
+
279
+ if (sm > 0 && absang > 0.01 && absang < 6.282) {
280
+ rprime = parseFloat(sm) / 2.0 / calcRadiusAdjustment(ang);
281
+ }
282
+
283
+ return rprime;
284
+ }
285
+
286
+ $.jqplot.PieRenderer.prototype.drawSlice = function (ctx, ang1, ang2, color, isShadow) {
287
+ if (this._drawData) {
288
+ var r = this._radius;
289
+ var fill = this.fill;
290
+ var lineWidth = this.lineWidth;
291
+ var sm = this.sliceMargin;
292
+ if (this.fill == false) {
293
+ sm += this.lineWidth;
294
+ }
295
+ ctx.save();
296
+ ctx.translate(this._center[0], this._center[1]);
297
+
298
+ var rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);
299
+
300
+ var transx = rprime * Math.cos((ang1 + ang2) / 2.0);
301
+ var transy = rprime * Math.sin((ang1 + ang2) / 2.0);
302
+
303
+ if ((ang2 - ang1) <= Math.PI) {
304
+ r -= rprime;
305
+ }
306
+ else {
307
+ r += rprime;
308
+ }
309
+
310
+ ctx.translate(transx, transy);
311
+
312
+ if (isShadow) {
313
+ for (var i=0, l=this.shadowDepth; i<l; i++) {
314
+ ctx.save();
315
+ ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));
316
+ doDraw(r);
317
+ }
318
+ for (var i=0, l=this.shadowDepth; i<l; i++) {
319
+ ctx.restore();
320
+ }
321
+ }
322
+
323
+ else {
324
+ doDraw(r);
325
+ }
326
+ ctx.restore();
327
+ }
328
+
329
+ function doDraw (rad) {
330
+ // Fix for IE and Chrome that can't seem to draw circles correctly.
331
+ // ang2 should always be <= 2 pi since that is the way the data is converted.
332
+ // 2Pi = 6.2831853, Pi = 3.1415927
333
+ if (ang2 > 6.282 + this.startAngle) {
334
+ ang2 = 6.282 + this.startAngle;
335
+ if (ang1 > ang2) {
336
+ ang1 = 6.281 + this.startAngle;
337
+ }
338
+ }
339
+ // Fix for IE, where it can't seem to handle 0 degree angles. Also avoids
340
+ // ugly line on unfilled pies.
341
+ if (ang1 >= ang2) {
342
+ return;
343
+ }
344
+
345
+ ctx.beginPath();
346
+ ctx.fillStyle = color;
347
+ ctx.strokeStyle = color;
348
+ ctx.lineWidth = lineWidth;
349
+ ctx.arc(0, 0, rad, ang1, ang2, false);
350
+ ctx.lineTo(0,0);
351
+ ctx.closePath();
352
+
353
+ if (fill) {
354
+ ctx.fill();
355
+ }
356
+ else {
357
+ ctx.stroke();
358
+ }
359
+ }
360
+ };
361
+
362
+ // called with scope of series
363
+ $.jqplot.PieRenderer.prototype.draw = function (ctx, gd, options, plot) {
364
+ var i;
365
+ var opts = (options != undefined) ? options : {};
366
+ // offset and direction of offset due to legend placement
367
+ var offx = 0;
368
+ var offy = 0;
369
+ var trans = 1;
370
+ var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);
371
+ var sliceColor;
372
+
373
+ if (options.legendInfo && options.legendInfo.placement == 'insideGrid') {
374
+ var li = options.legendInfo;
375
+ switch (li.location) {
376
+ case 'nw':
377
+ offx = li.width + li.xoffset;
378
+ break;
379
+ case 'w':
380
+ offx = li.width + li.xoffset;
381
+ break;
382
+ case 'sw':
383
+ offx = li.width + li.xoffset;
384
+ break;
385
+ case 'ne':
386
+ offx = li.width + li.xoffset;
387
+ trans = -1;
388
+ break;
389
+ case 'e':
390
+ offx = li.width + li.xoffset;
391
+ trans = -1;
392
+ break;
393
+ case 'se':
394
+ offx = li.width + li.xoffset;
395
+ trans = -1;
396
+ break;
397
+ case 'n':
398
+ offy = li.height + li.yoffset;
399
+ break;
400
+ case 's':
401
+ offy = li.height + li.yoffset;
402
+ trans = -1;
403
+ break;
404
+ default:
405
+ break;
406
+ }
407
+ }
408
+
409
+ var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
410
+ var fill = (opts.fill != undefined) ? opts.fill : this.fill;
411
+
412
+ //see http://stackoverflow.com/questions/20221461/hidpi-retina-plot-drawing
413
+ var cw = parseInt(ctx.canvas.style.width);
414
+ var ch = parseInt(ctx.canvas.style.height);
415
+ //
416
+
417
+ var w = cw - offx - 2 * this.padding;
418
+ var h = ch - offy - 2 * this.padding;
419
+ var mindim = Math.min(w,h);
420
+ var d = mindim;
421
+
422
+ // Fixes issue #272. Thanks hugwijst!
423
+ // reset slice angles array.
424
+ this._sliceAngles = [];
425
+
426
+ var sm = this.sliceMargin;
427
+ if (this.fill == false) {
428
+ sm += this.lineWidth;
429
+ }
430
+
431
+ var rprime;
432
+ var maxrprime = 0;
433
+
434
+ var ang, ang1, ang2, shadowColor;
435
+ var sa = this.startAngle / 180 * Math.PI;
436
+
437
+ // have to pre-draw shadows, so loop throgh here and calculate some values also.
438
+ for (var i=0, l=gd.length; i<l; i++) {
439
+ ang1 = (i == 0) ? sa : gd[i-1][1] + sa;
440
+ ang2 = gd[i][1] + sa;
441
+
442
+ this._sliceAngles.push([ang1, ang2]);
443
+
444
+ rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);
445
+
446
+ if (Math.abs(ang2-ang1) > Math.PI) {
447
+ maxrprime = Math.max(rprime, maxrprime);
448
+ }
449
+ }
450
+
451
+ if (this.diameter != null && this.diameter > 0) {
452
+ this._diameter = this.diameter - 2*maxrprime;
453
+ }
454
+ else {
455
+ this._diameter = d - 2*maxrprime;
456
+ }
457
+
458
+ // Need to check for undersized pie. This can happen if
459
+ // plot area too small and legend is too big.
460
+ if (this._diameter < 6) {
461
+ $.jqplot.log('Diameter of pie too small, not rendering.');
462
+ return;
463
+ }
464
+
465
+ var r = this._radius = this._diameter/2;
466
+
467
+ this._center = [(cw - trans * offx)/2 + trans * offx + maxrprime * Math.cos(sa), (ch - trans*offy)/2 + trans * offy + maxrprime * Math.sin(sa)];
468
+
469
+ if (this.shadow) {
470
+ for (var i=0, l=gd.length; i<l; i++) {
471
+ shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')';
472
+ this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], shadowColor, true);
473
+ }
474
+ }
475
+
476
+ for (var i=0; i<gd.length; i++) {
477
+
478
+ sliceColor = colorGenerator.next();
479
+
480
+ if (this.showSlice[i]) {
481
+ this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], sliceColor, false);
482
+
483
+ if (this.showDataLabels && gd[i][2]*100 >= this.dataLabelThreshold) {
484
+ var fstr, avgang = (this._sliceAngles[i][0] + this._sliceAngles[i][1])/2, label;
485
+
486
+ if (this.dataLabels == 'label') {
487
+ fstr = this.dataLabelFormatString || '%s';
488
+ label = $.jqplot.sprintf(fstr, gd[i][0]);
489
+ }
490
+ else if (this.dataLabels == 'value') {
491
+ fstr = this.dataLabelFormatString || '%d';
492
+ label = $.jqplot.sprintf(fstr, this.data[i][1]);
493
+ }
494
+ else if (this.dataLabels == 'percent') {
495
+ fstr = this.dataLabelFormatString || '%d%%';
496
+ label = $.jqplot.sprintf(fstr, gd[i][2]*100);
497
+ }
498
+ else if (this.dataLabels.constructor == Array) {
499
+ fstr = this.dataLabelFormatString || '%s';
500
+ label = $.jqplot.sprintf(fstr, this.dataLabels[i]);
501
+ }
502
+
503
+ var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge;
504
+
505
+ var x = this._center[0] + Math.cos(avgang) * fact + this.canvas._offsets.left;
506
+ var y = this._center[1] + Math.sin(avgang) * fact + this.canvas._offsets.top;
507
+
508
+ var labelelem = $('<div class="jqplot-pie-series jqplot-data-label" style="position:absolute;">' + label + '</div>').insertBefore(plot.eventCanvas._elem);
509
+ if (this.dataLabelCenterOn) {
510
+ x -= labelelem.width()/2;
511
+ y -= labelelem.height()/2;
512
+ }
513
+ else {
514
+ x -= labelelem.width() * Math.sin(avgang/2);
515
+ y -= labelelem.height()/2;
516
+ }
517
+ x = Math.round(x);
518
+ y = Math.round(y);
519
+ labelelem.css({left: x, top: y});
520
+ }
521
+ }
522
+ }
523
+ };
524
+
525
+ $.jqplot.PieAxisRenderer = function() {
526
+ $.jqplot.LinearAxisRenderer.call(this);
527
+ };
528
+
529
+ $.jqplot.PieAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();
530
+ $.jqplot.PieAxisRenderer.prototype.constructor = $.jqplot.PieAxisRenderer;
531
+
532
+
533
+ // There are no traditional axes on a pie chart. We just need to provide
534
+ // dummy objects with properties so the plot will render.
535
+ // called with scope of axis object.
536
+ $.jqplot.PieAxisRenderer.prototype.init = function(options){
537
+ //
538
+ this.tickRenderer = $.jqplot.PieTickRenderer;
539
+ $.extend(true, this, options);
540
+ // I don't think I'm going to need _dataBounds here.
541
+ // have to go Axis scaling in a way to fit chart onto plot area
542
+ // and provide u2p and p2u functionality for mouse cursor, etc.
543
+ // for convienence set _dataBounds to 0 and 100 and
544
+ // set min/max to 0 and 100.
545
+ this._dataBounds = {min:0, max:100};
546
+ this.min = 0;
547
+ this.max = 100;
548
+ this.showTicks = false;
549
+ this.ticks = [];
550
+ this.showMark = false;
551
+ this.show = false;
552
+ };
553
+
554
+
555
+
556
+
557
+ $.jqplot.PieLegendRenderer = function(){
558
+ $.jqplot.TableLegendRenderer.call(this);
559
+ };
560
+
561
+ $.jqplot.PieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();
562
+ $.jqplot.PieLegendRenderer.prototype.constructor = $.jqplot.PieLegendRenderer;
563
+
564
+ /**
565
+ * Class: $.jqplot.PieLegendRenderer
566
+ * Legend Renderer specific to pie plots. Set by default
567
+ * when user creates a pie plot.
568
+ */
569
+ $.jqplot.PieLegendRenderer.prototype.init = function(options) {
570
+ // Group: Properties
571
+ //
572
+ // prop: numberRows
573
+ // Maximum number of rows in the legend. 0 or null for unlimited.
574
+ this.numberRows = null;
575
+ // prop: numberColumns
576
+ // Maximum number of columns in the legend. 0 or null for unlimited.
577
+ this.numberColumns = null;
578
+ // prop: width
579
+ // Fixed with of legend. 0 or null for auto size
580
+ this.width = null;
581
+ $.extend(true, this, options);
582
+ };
583
+
584
+ // called with context of legend
585
+ $.jqplot.PieLegendRenderer.prototype.draw = function() {
586
+ var legend = this;
587
+ if (this.show) {
588
+ var series = this._series;
589
+
590
+
591
+ this._elem = $(document.createElement('table'));
592
+ this._elem.addClass('jqplot-table-legend');
593
+
594
+ var ss = {position:'absolute'};
595
+ if (this.background) {
596
+ ss['background'] = this.background;
597
+ }
598
+ if (this.border) {
599
+ ss['border'] = this.border;
600
+ }
601
+ if (this.fontSize) {
602
+ ss['fontSize'] = this.fontSize;
603
+ }
604
+ if (this.fontFamily) {
605
+ ss['fontFamily'] = this.fontFamily;
606
+ }
607
+ if (this.textColor) {
608
+ ss['textColor'] = this.textColor;
609
+ }
610
+ if (this.marginTop != null) {
611
+ ss['marginTop'] = this.marginTop;
612
+ }
613
+ if (this.marginBottom != null) {
614
+ ss['marginBottom'] = this.marginBottom;
615
+ }
616
+ if (this.marginLeft != null) {
617
+ ss['marginLeft'] = this.marginLeft;
618
+ }
619
+ if (this.marginRight != null) {
620
+ ss['marginRight'] = this.marginRight;
621
+ }
622
+
623
+ this._elem.css(ss);
624
+
625
+ // Pie charts legends don't go by number of series, but by number of data points
626
+ // in the series. Refactor things here for that.
627
+
628
+ var pad = false,
629
+ reverse = false,
630
+ nr,
631
+ nc;
632
+ var s = series[0];
633
+ var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors);
634
+
635
+ if (s.show) {
636
+ var pd = s.data;
637
+ if (this.numberRows) {
638
+ nr = this.numberRows;
639
+ if (!this.numberColumns){
640
+ nc = Math.ceil(pd.length/nr);
641
+ }
642
+ else{
643
+ nc = this.numberColumns;
644
+ }
645
+ }
646
+ else if (this.numberColumns) {
647
+ nc = this.numberColumns;
648
+ nr = Math.ceil(pd.length/this.numberColumns);
649
+ }
650
+ else {
651
+ nr = pd.length;
652
+ nc = 1;
653
+ }
654
+
655
+ var i, j;
656
+ var tr, td1, td2;
657
+ var lt, tt, rs, color;
658
+ var idx = 0;
659
+ var div0, div1;
660
+
661
+ for (i=0; i<nr; i++) {
662
+ tr = $(document.createElement('tr'));
663
+ tr.addClass('jqplot-table-legend');
664
+
665
+ if (reverse){
666
+ tr.prependTo(this._elem);
667
+ }
668
+
669
+ else{
670
+ tr.appendTo(this._elem);
671
+ }
672
+
673
+ for (j=0; j<nc; j++) {
674
+ if (idx < pd.length) {
675
+ tt = '';
676
+ if (this.labels[idx]) {
677
+ lt = this.labels[idx];
678
+ }
679
+ else {
680
+ if (typeof pd[idx][0] === 'object') {
681
+ lt = pd[idx][0][0].toString();
682
+ tt = pd[idx][0][1].toString();
683
+ }
684
+ else {
685
+ lt = pd[idx][0].toString();
686
+ }
687
+ }
688
+ //lt = this.labels[idx] || pd[idx][0].toString();
689
+ color = colorGenerator.next();
690
+ if (!reverse){
691
+ if (i>0){
692
+ pad = true;
693
+ }
694
+ else{
695
+ pad = false;
696
+ }
697
+ }
698
+ else{
699
+ if (i == nr -1){
700
+ pad = false;
701
+ }
702
+ else{
703
+ pad = true;
704
+ }
705
+ }
706
+ rs = (pad) ? this.rowSpacing : '0';
707
+
708
+
709
+
710
+ td1 = $(document.createElement('td'));
711
+ td1.addClass('jqplot-table-legend jqplot-table-legend-swatch');
712
+ td1.css({textAlign: 'center', paddingTop: rs});
713
+
714
+ div0 = $(document.createElement('div'));
715
+ div0.addClass('jqplot-table-legend-swatch-outline');
716
+ if (tt !== '') {
717
+ div0.attr("title", tt);
718
+ }
719
+ div1 = $(document.createElement('div'));
720
+ div1.addClass('jqplot-table-legend-swatch');
721
+ div1.css({backgroundColor: color, borderColor: color});
722
+ td1.append(div0.append(div1));
723
+
724
+ td2 = $(document.createElement('td'));
725
+ td2.addClass('jqplot-table-legend jqplot-table-legend-label');
726
+ td2.css('paddingTop', rs);
727
+
728
+ if (this.escapeHtml){
729
+ td2.text(lt);
730
+ }
731
+ else {
732
+ td2.html('<a title="' + tt + '">' + lt + "</a>");
733
+ }
734
+ if (reverse) {
735
+ td2.prependTo(tr);
736
+ td1.prependTo(tr);
737
+ }
738
+ else {
739
+ td1.appendTo(tr);
740
+ td2.appendTo(tr);
741
+ }
742
+ pad = true;
743
+ }
744
+ idx++;
745
+ }
746
+ }
747
+ }
748
+ }
749
+ return this._elem;
750
+ };
751
+
752
+ $.jqplot.PieRenderer.prototype.handleMove = function(ev, gridpos, datapos, neighbor, plot) {
753
+ if (neighbor) {
754
+ var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
755
+ plot.target.trigger('jqplotDataMouseOver', ins);
756
+ if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
757
+ plot.target.trigger('jqplotDataHighlight', ins);
758
+ highlight (plot, ins[0], ins[1]);
759
+ }
760
+ }
761
+ else if (neighbor == null) {
762
+ unhighlight (plot);
763
+ }
764
+ };
765
+
766
+
767
+ // this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]);
768
+
769
+ // setup default renderers for axes and legend so user doesn't have to
770
+ // called with scope of plot
771
+ function preInit(target, data, options) {
772
+ options = options || {};
773
+ options.axesDefaults = options.axesDefaults || {};
774
+ options.legend = options.legend || {};
775
+ options.seriesDefaults = options.seriesDefaults || {};
776
+ // only set these if there is a pie series
777
+ var setopts = false;
778
+ if (options.seriesDefaults.renderer == $.jqplot.PieRenderer) {
779
+ setopts = true;
780
+ }
781
+ else if (options.series) {
782
+ for (var i=0; i < options.series.length; i++) {
783
+ if (options.series[i].renderer == $.jqplot.PieRenderer) {
784
+ setopts = true;
785
+ }
786
+ }
787
+ }
788
+
789
+ if (setopts) {
790
+ options.axesDefaults.renderer = $.jqplot.PieAxisRenderer;
791
+ options.legend.renderer = options.legend.renderer || $.jqplot.PieLegendRenderer;
792
+ options.legend.preDraw = true;
793
+ options.seriesDefaults.pointLabels = {show: false};
794
+ }
795
+ }
796
+
797
+ function postInit(target, data, options) {
798
+ for (var i=0; i<this.series.length; i++) {
799
+ if (this.series[i].renderer.constructor == $.jqplot.PieRenderer) {
800
+ // don't allow mouseover and mousedown at same time.
801
+ if (this.series[i].highlightMouseOver) {
802
+ this.series[i].highlightMouseDown = false;
803
+ }
804
+ }
805
+ }
806
+ }
807
+
808
+ // called with scope of plot
809
+ function postParseOptions(options) {
810
+ for (var i=0; i<this.series.length; i++) {
811
+ this.series[i].seriesColors = this.seriesColors;
812
+ this.series[i].colorGenerator = $.jqplot.colorGenerator;
813
+ }
814
+ }
815
+
816
+ function highlight (plot, sidx, pidx) {
817
+ if (plot.series[sidx].showSlice[pidx]) {
818
+ var s = plot.series[sidx];
819
+ var canvas = plot.plugins.pieRenderer.highlightCanvas;
820
+ canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);
821
+ s._highlightedPoint = pidx;
822
+ plot.plugins.pieRenderer.highlightedSeriesIndex = sidx;
823
+ s.renderer.drawSlice.call(s, canvas._ctx, s._sliceAngles[pidx][0], s._sliceAngles[pidx][1], s.highlightColorGenerator.get(pidx), false);
824
+ }
825
+ }
826
+
827
+ function unhighlight (plot) {
828
+ var canvas = plot.plugins.pieRenderer.highlightCanvas;
829
+ canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);
830
+ for (var i=0; i<plot.series.length; i++) {
831
+ plot.series[i]._highlightedPoint = null;
832
+ }
833
+ plot.plugins.pieRenderer.highlightedSeriesIndex = null;
834
+ plot.target.trigger('jqplotDataUnhighlight');
835
+ }
836
+
837
+ function handleMove(ev, gridpos, datapos, neighbor, plot) {
838
+ if (neighbor) {
839
+ var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
840
+ var evt1 = jQuery.Event('jqplotDataMouseOver');
841
+ evt1.pageX = ev.pageX;
842
+ evt1.pageY = ev.pageY;
843
+ plot.target.trigger(evt1, ins);
844
+ if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
845
+ var evt = jQuery.Event('jqplotDataHighlight');
846
+ evt.which = ev.which;
847
+ evt.pageX = ev.pageX;
848
+ evt.pageY = ev.pageY;
849
+ plot.target.trigger(evt, ins);
850
+ highlight (plot, ins[0], ins[1]);
851
+ }
852
+ }
853
+ else if (neighbor == null) {
854
+ unhighlight (plot);
855
+ }
856
+ }
857
+
858
+ function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
859
+ if (neighbor) {
860
+ var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
861
+ if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
862
+ var evt = jQuery.Event('jqplotDataHighlight');
863
+ evt.which = ev.which;
864
+ evt.pageX = ev.pageX;
865
+ evt.pageY = ev.pageY;
866
+ plot.target.trigger(evt, ins);
867
+ highlight (plot, ins[0], ins[1]);
868
+ }
869
+ }
870
+ else if (neighbor == null) {
871
+ unhighlight (plot);
872
+ }
873
+ }
874
+
875
+ function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {
876
+ var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;
877
+ if (idx != null && plot.series[idx].highlightMouseDown) {
878
+ unhighlight(plot);
879
+ }
880
+ }
881
+
882
+ function handleClick(ev, gridpos, datapos, neighbor, plot) {
883
+ if (neighbor) {
884
+ var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
885
+ var evt = jQuery.Event('jqplotDataClick');
886
+ evt.which = ev.which;
887
+ evt.pageX = ev.pageX;
888
+ evt.pageY = ev.pageY;
889
+ plot.target.trigger(evt, ins);
890
+ }
891
+ }
892
+
893
+ function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
894
+ if (neighbor) {
895
+ var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
896
+ var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;
897
+ if (idx != null && plot.series[idx].highlightMouseDown) {
898
+ unhighlight(plot);
899
+ }
900
+ var evt = jQuery.Event('jqplotDataRightClick');
901
+ evt.which = ev.which;
902
+ evt.pageX = ev.pageX;
903
+ evt.pageY = ev.pageY;
904
+ plot.target.trigger(evt, ins);
905
+ }
906
+ }
907
+
908
+ // called within context of plot
909
+ // create a canvas which we can draw on.
910
+ // insert it before the eventCanvas, so eventCanvas will still capture events.
911
+ function postPlotDraw() {
912
+ // Memory Leaks patch
913
+ if (this.plugins.pieRenderer && this.plugins.pieRenderer.highlightCanvas) {
914
+ this.plugins.pieRenderer.highlightCanvas.resetCanvas();
915
+ this.plugins.pieRenderer.highlightCanvas = null;
916
+ }
917
+
918
+ this.plugins.pieRenderer = {highlightedSeriesIndex:null};
919
+ this.plugins.pieRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
920
+
921
+ // do we have any data labels? if so, put highlight canvas before those
922
+ var labels = $(this.targetId+' .jqplot-data-label');
923
+ if (labels.length) {
924
+ $(labels[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));
925
+ }
926
+ // else put highlight canvas before event canvas.
927
+ else {
928
+ this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));
929
+ }
930
+
931
+ var hctx = this.plugins.pieRenderer.highlightCanvas.setContext();
932
+ this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });
933
+ }
934
+
935
+ $.jqplot.preInitHooks.push(preInit);
936
+
937
+ $.jqplot.PieTickRenderer = function() {
938
+ $.jqplot.AxisTickRenderer.call(this);
939
+ };
940
+
941
+ $.jqplot.PieTickRenderer.prototype = new $.jqplot.AxisTickRenderer();
942
+ $.jqplot.PieTickRenderer.prototype.constructor = $.jqplot.PieTickRenderer;
943
+
944
+ })(jQuery);
945
+
904
946