rgraph-rails 4.62 → 4.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +3 -4
  3. data/lib/rgraph-rails/version.rb +1 -1
  4. data/vendor/assets/javascripts/RGraph.bar.js +240 -3742
  5. data/vendor/assets/javascripts/RGraph.bipolar.js +165 -2005
  6. data/vendor/assets/javascripts/RGraph.common.annotate.js +35 -395
  7. data/vendor/assets/javascripts/RGraph.common.context.js +30 -595
  8. data/vendor/assets/javascripts/RGraph.common.core.js +418 -5359
  9. data/vendor/assets/javascripts/RGraph.common.csv.js +20 -276
  10. data/vendor/assets/javascripts/RGraph.common.deprecated.js +35 -450
  11. data/vendor/assets/javascripts/RGraph.common.dynamic.js +88 -1395
  12. data/vendor/assets/javascripts/RGraph.common.effects.js +90 -1545
  13. data/vendor/assets/javascripts/RGraph.common.key.js +52 -753
  14. data/vendor/assets/javascripts/RGraph.common.resizing.js +37 -563
  15. data/vendor/assets/javascripts/RGraph.common.sheets.js +29 -352
  16. data/vendor/assets/javascripts/RGraph.common.tooltips.js +32 -450
  17. data/vendor/assets/javascripts/RGraph.common.zoom.js +14 -219
  18. data/vendor/assets/javascripts/RGraph.cornergauge.js +71 -0
  19. data/vendor/assets/javascripts/RGraph.drawing.background.js +34 -570
  20. data/vendor/assets/javascripts/RGraph.drawing.circle.js +33 -544
  21. data/vendor/assets/javascripts/RGraph.drawing.image.js +51 -755
  22. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +37 -645
  23. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +36 -633
  24. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +35 -514
  25. data/vendor/assets/javascripts/RGraph.drawing.poly.js +37 -559
  26. data/vendor/assets/javascripts/RGraph.drawing.rect.js +33 -548
  27. data/vendor/assets/javascripts/RGraph.drawing.text.js +36 -664
  28. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +50 -812
  29. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +51 -856
  30. data/vendor/assets/javascripts/RGraph.fuel.js +58 -964
  31. data/vendor/assets/javascripts/RGraph.funnel.js +55 -984
  32. data/vendor/assets/javascripts/RGraph.gantt.js +77 -1354
  33. data/vendor/assets/javascripts/RGraph.gauge.js +85 -1421
  34. data/vendor/assets/javascripts/RGraph.hbar.js +162 -2788
  35. data/vendor/assets/javascripts/RGraph.hprogress.js +80 -1401
  36. data/vendor/assets/javascripts/RGraph.line.js +249 -4248
  37. data/vendor/assets/javascripts/RGraph.meter.js +74 -1280
  38. data/vendor/assets/javascripts/RGraph.modaldialog.js +19 -301
  39. data/vendor/assets/javascripts/RGraph.odo.js +71 -1264
  40. data/vendor/assets/javascripts/RGraph.pie.js +137 -2288
  41. data/vendor/assets/javascripts/RGraph.radar.js +110 -1847
  42. data/vendor/assets/javascripts/RGraph.rose.js +108 -1977
  43. data/vendor/assets/javascripts/RGraph.rscatter.js +80 -1432
  44. data/vendor/assets/javascripts/RGraph.scatter.js +172 -3163
  45. data/vendor/assets/javascripts/RGraph.semicircularprogress.js +60 -1120
  46. data/vendor/assets/javascripts/RGraph.svg.bar.js +66 -1735
  47. data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +21 -246
  48. data/vendor/assets/javascripts/RGraph.svg.common.core.js +255 -3937
  49. data/vendor/assets/javascripts/RGraph.svg.common.csv.js +20 -276
  50. data/vendor/assets/javascripts/RGraph.svg.common.fx.js +68 -1303
  51. data/vendor/assets/javascripts/RGraph.svg.common.key.js +19 -205
  52. data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +29 -352
  53. data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +22 -273
  54. data/vendor/assets/javascripts/RGraph.svg.funnel.js +32 -0
  55. data/vendor/assets/javascripts/RGraph.svg.hbar.js +59 -1400
  56. data/vendor/assets/javascripts/RGraph.svg.line.js +70 -1580
  57. data/vendor/assets/javascripts/RGraph.svg.pie.js +55 -1131
  58. data/vendor/assets/javascripts/RGraph.svg.radar.js +57 -1502
  59. data/vendor/assets/javascripts/RGraph.svg.rose.js +66 -1817
  60. data/vendor/assets/javascripts/RGraph.svg.scatter.js +58 -1261
  61. data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +28 -865
  62. data/vendor/assets/javascripts/RGraph.svg.waterfall.js +45 -1252
  63. data/vendor/assets/javascripts/RGraph.thermometer.js +63 -1136
  64. data/vendor/assets/javascripts/RGraph.vprogress.js +83 -1470
  65. data/vendor/assets/javascripts/RGraph.waterfall.js +83 -1347
  66. metadata +5 -4
  67. data/vendor/assets/javascripts/financial-data.js +0 -1067
@@ -1,2289 +1,138 @@
1
- // version: 2017-05-08
2
- /**
3
- * o--------------------------------------------------------------------------------o
4
- * | This file is part of the RGraph package - you can learn more at: |
5
- * | |
6
- * | http://www.rgraph.net |
7
- * | |
8
- * | RGraph is licensed under the Open Source MIT license. That means that it's |
9
- * | totally free to use! |
10
- * o--------------------------------------------------------------------------------o
11
- */
12
1
 
13
- RGraph = window.RGraph || {isRGraph: true};
14
-
15
- /**
16
- * The pie chart constructor
17
- *
18
- * @param data array The data to be represented on the Pie chart
19
- */
20
- RGraph.Pie = function (conf)
21
- {
22
- /**
23
- * Allow for object config style
24
- */
25
- if ( typeof conf === 'object'
26
- && typeof conf.data === 'object'
27
- && typeof conf.id === 'string') {
28
-
29
- var id = conf.id,
30
- canvas = document.getElementById(id),
31
- data = conf.data,
32
- parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor
33
-
34
- } else {
35
-
36
- var id = conf,
37
- canvas = document.getElementById(id),
38
- data = arguments[1];
39
- }
40
-
41
-
42
-
43
-
44
- // Get the canvas and context objects
45
- this.id = id;
46
- this.canvas = canvas;
47
- this.context = this.canvas.getContext ? this.canvas.getContext("2d", {alpha: (typeof id === 'object' && id.alpha === false) ? false : true}) : null;
48
- this.canvas.__object__ = this;
49
- this.total = 0;
50
- this.subTotal = 0;
51
- this.angles = [];
52
- this.data = data;
53
- this.properties = [];
54
- this.type = 'pie';
55
- this.isRGraph = true;
56
- this.coords = [];
57
- this.coords.key = [];
58
- this.coordsSticks = [];
59
- this.coordsText = [];
60
- this.uid = RGraph.CreateUID();
61
- this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
62
- this.colorsParsed = false;
63
- this.original_colors = [];
64
- this.firstDraw = true; // After the first draw this will be false
65
- this.exploding = null;
66
-
67
-
68
- //
69
- // Go through the data and convert strings to numbers
70
- //
71
- for (var i=0; i<this.data.length; ++i) {
72
- if (typeof this.data[i] === 'string') {
73
- this.data[i] = parseFloat(this.data[i]);
74
- }
75
- }
76
-
77
- this.properties =
78
- {
79
- 'chart.centerx.adjust': 0,
80
- 'chart.centery.adjust': 0,
81
- 'chart.colors': ['red', '#ccc', '#cfc', 'blue', 'pink', 'yellow', 'black', 'orange', 'cyan', 'purple', '#78CAEA', '#E284E9', 'white', 'blue', '#9E7BF6'],
82
- 'chart.strokestyle': 'white',
83
- 'chart.linewidth': 3,
84
- 'chart.labels': [],
85
- 'chart.labels.bold': false,
86
- 'chart.labels.sticks': false,
87
- 'chart.labels.sticks.length': 7,
88
- 'chart.labels.sticks.colors': null,
89
- 'chart.labels.sticks.usecolors': true,
90
- 'chart.labels.sticks.linewidth': 1,
91
- 'chart.labels.sticks.hlength': 5,
92
- 'chart.labels.sticks.list': false,
93
- 'chart.labels.ingraph': null,
94
- 'chart.labels.ingraph.color': null,
95
- 'chart.labels.ingraph.font': null,
96
- 'chart.labels.ingraph.size': null,
97
- 'chart.labels.ingraph.bounding':true,
98
- 'chart.labels.ingraph.bounding.fill':'white',
99
- 'chart.labels.ingraph.specific':null,
100
- 'chart.labels.ingraph.units.pre':'',
101
- 'chart.labels.ingraph.units.post':'',
102
- 'chart.labels.ingraph.radius': null,
103
- 'chart.labels.center': null,
104
- 'chart.labels.center.size': 26,
105
- 'chart.labels.center.font': 'Segoe UI, Arial, Verdana, sans-serif',
106
- 'chart.labels.center.color': 'black',
107
- 'chart.labels.center.italic': false,
108
- 'chart.labels.center.bold': false,
109
- 'chart.labels.center.units.pre': '',
110
- 'chart.labels.center.units.post': '',
111
- 'chart.gutter.left': 25,
112
- 'chart.gutter.right': 25,
113
- 'chart.gutter.top': 25,
114
- 'chart.gutter.bottom': 25,
115
- 'chart.title': '',
116
- 'chart.title.background': null,
117
- 'chart.title.hpos': null,
118
- 'chart.title.vpos': 0.5,
119
- 'chart.title.bold': true,
120
- 'chart.title.font': null,
121
- 'chart.title.x': null,
122
- 'chart.title.y': null,
123
- 'chart.title.halign': null,
124
- 'chart.title.valign': null,
125
- 'chart.shadow': true,
126
- 'chart.shadow.color': '#aaa',
127
- 'chart.shadow.offsetx': 0,
128
- 'chart.shadow.offsety': 0,
129
- 'chart.shadow.blur': 15,
130
- 'chart.text.size': 12,
131
- 'chart.text.color': 'black',
132
- 'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
133
- 'chart.text.accessible': true,
134
- 'chart.text.accessible.overflow': 'visible',
135
- 'chart.text.accessible.pointerevents': true,
136
- 'chart.contextmenu': null,
137
- 'chart.tooltips': null,
138
- 'chart.tooltips.event': 'onclick',
139
- 'chart.tooltips.effect': 'fade',
140
- 'chart.tooltips.css.class': 'RGraph_tooltip',
141
- 'chart.tooltips.highlight': true,
142
- 'chart.highlight.style': '2d',
143
- 'chart.highlight.style.twod.fill': 'rgba(255,255,255,0.7)',
144
- 'chart.highlight.style.twod.stroke': 'rgba(255,255,255,0.7)',
145
- 'chart.highlight.style.outline.width': null,
146
- 'chart.centerx': null,
147
- 'chart.centery': null,
148
- 'chart.radius': null,
149
- 'chart.border': false,
150
- 'chart.border.color': 'rgba(255,255,255,0.5)',
151
- 'chart.key': null,
152
- 'chart.key.background': 'white',
153
- 'chart.key.position': 'graph',
154
- 'chart.key.halign': 'right',
155
- 'chart.key.shadow': false,
156
- 'chart.key.shadow.color': '#666',
157
- 'chart.key.shadow.blur': 3,
158
- 'chart.key.shadow.offsetx': 2,
159
- 'chart.key.shadow.offsety': 2,
160
- 'chart.key.position.gutter.boxed': false,
161
- 'chart.key.position.x': null,
162
- 'chart.key.position.y': null,
163
- 'chart.key.color.shape': 'square',
164
- 'chart.key.rounded': true,
165
- 'chart.key.linewidth': 1,
166
- 'chart.key.colors': null,
167
- 'chart.key.interactive': false,
168
- 'chart.key.interactive.highlight.chart.stroke': 'black',
169
- 'chart.key.interactive.highlight.chart.fill': 'rgba(255,255,255,0.7)',
170
- 'chart.key.interactive.highlight.label': 'rgba(255,0,0,0.2)',
171
- 'chart.key.text.color': 'black',
172
- 'chart.annotatable': false,
173
- 'chart.annotate.color': 'black',
174
- 'chart.zoom.factor': 1.5,
175
- 'chart.zoom.fade.in': true,
176
- 'chart.zoom.fade.out': true,
177
- 'chart.zoom.hdir': 'right',
178
- 'chart.zoom.vdir': 'down',
179
- 'chart.zoom.frames': 25,
180
- 'chart.zoom.delay': 16.666,
181
- 'chart.zoom.shadow': true,
182
- 'chart.zoom.background': true,
183
- 'chart.zoom.action': 'zoom',
184
- 'chart.resizable': false,
185
- 'chart.resize.handle.adjust': [0,0],
186
- 'chart.resize.handle.background': null,
187
- 'chart.variant': 'pie',
188
- 'chart.variant.donut.width': null,
189
- 'chart.variant.threed.depth': 20,
190
- 'chart.exploded': [],
191
- 'chart.effect.roundrobin.multiplier': 1,
192
- 'chart.events.click': null,
193
- 'chart.events.mousemove': null,
194
- 'chart.centerpin': null,
195
- 'chart.centerpin.fill': 'gray',
196
- 'chart.centerpin.stroke': 'white',
197
- 'chart.origin': 0 - (Math.PI / 2),
198
- 'chart.events': true,
199
- 'chart.labels.colors': [],
200
- 'chart.clearto': 'rgba(0,0,0,0)'
201
- }
202
-
203
-
204
-
205
- /**
206
- * Calculate the total
207
- */
208
- for (var i=0,len=data.length; i<len; i++) {
209
- this.total += data[i];
210
-
211
- // This loop also creates the $xxx objects - this isn't related to
212
- // the code above but just saves doing another loop through the data
213
- this['$' + i] = {};
214
- }
215
-
216
-
217
- /**
218
- * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
219
- * done already
220
- */
221
- if (!this.canvas.__rgraph_aa_translated__) {
222
- this.context.translate(0.5,0.5);
223
-
224
- this.canvas.__rgraph_aa_translated__ = true;
225
- }
226
-
227
-
228
-
229
-
230
- // Short variable names
231
- var RG = RGraph,
232
- ca = this.canvas,
233
- co = ca.getContext('2d'),
234
- prop = this.properties,
235
- pa2 = RG.path2,
236
- win = window,
237
- doc = document,
238
- ma = Math
239
-
240
-
241
-
242
- /**
243
- * "Decorate" the object with the generic effects if the effects library has been included
244
- */
245
- if (RG.Effects && typeof RG.Effects.decorate === 'function') {
246
- RG.Effects.decorate(this);
247
- }
248
-
249
-
250
-
251
-
252
- /**
253
- * A generic setter
254
- */
255
- this.set =
256
- this.Set = function (name)
257
- {
258
- var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
259
-
260
- /**
261
- * the number of arguments is only one and it's an
262
- * object - parse it for configuration data and return.
263
- */
264
- if (arguments.length === 1 && typeof name === 'object') {
265
- RG.parseObjectStyleConfig(this, name);
266
- return this;
267
- }
268
-
269
-
270
-
271
-
272
-
273
- /**
274
- * This should be done first - prepend the property name with "chart." if necessary
275
- */
276
- if (name.substr(0,6) != 'chart.') {
277
- name = 'chart.' + name;
278
- }
279
-
280
-
281
-
282
-
283
- // Convert uppercase letters to dot+lower case letter
284
- while(name.match(/([A-Z])/)) {
285
- name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
286
- }
287
-
288
-
289
-
290
- if (name == 'chart.highlight.style.twod.color') {
291
- name = 'chart.highlight.style.twod.fill';
292
- }
293
-
294
-
295
- if (name == 'chart.labels.spaced') {
296
- name = 'chart.labels.sticks.list';
297
- }
298
-
299
-
300
-
301
-
302
-
303
-
304
- prop[name] = value;
305
-
306
- return this;
307
- };
308
-
309
-
310
-
311
-
312
- /**
313
- * A generic getter
314
- */
315
- this.get =
316
- this.Get = function (name)
317
- {
318
- /**
319
- * This should be done first - prepend the property name with "chart." if necessary
320
- */
321
- if (name.substr(0,6) != 'chart.') {
322
- name = 'chart.' + name;
323
- }
324
-
325
- // Convert uppercase letters to dot+lower case letter
326
- while(name.match(/([A-Z])/)) {
327
- name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
328
- }
329
-
330
- if (name == 'chart.highlight.style.twod.color') {
331
- name = 'chart.highlight.style.twod.fill';
332
- }
333
-
334
- return prop[name];
335
- };
336
-
337
-
338
-
339
-
340
- /**
341
- * This draws the pie chart
342
- */
343
- this.draw =
344
- this.Draw = function ()
345
- {
346
- /**
347
- * Fire the onbeforedraw event
348
- */
349
- RG.FireCustomEvent(this, 'onbeforedraw');
350
-
351
- // NB: Colors are parsed further down so that the center X/Y can be used
352
-
353
-
354
- /**
355
- * This is new in May 2011 and facilitates indiviual gutter settings,
356
- * eg chart.gutter.left
357
- */
358
- this.gutterLeft = prop['chart.gutter.left'];
359
- this.gutterRight = prop['chart.gutter.right'];
360
- this.gutterTop = prop['chart.gutter.top'];
361
- this.gutterBottom = prop['chart.gutter.bottom'];
362
-
363
- this.radius = this.getRadius();// MUST be first
364
- this.centerx = (this.graph.width / 2) + this.gutterLeft + prop['chart.centerx.adjust'];
365
- this.centery = (this.graph.height / 2) + this.gutterTop + prop['chart.centery.adjust'];
366
- this.subTotal = this.properties['chart.origin'];
367
- this.angles = [];
368
- this.coordsText = [];
369
-
370
- /**
371
- * Allow specification of a custom radius & center X/Y
372
- */
373
- if (typeof prop['chart.radius'] === 'number') this.radius = prop['chart.radius'];
374
- if (typeof prop['chart.centerx'] === 'number') this.centerx = prop['chart.centerx'];
375
- if (typeof prop['chart.centery'] === 'number') this.centery = prop['chart.centery'];
376
-
377
-
378
- if (this.radius <= 0) {
379
- return;
380
- }
381
-
382
- /**
383
- * Parse the colors for gradients. Its down here so that the center X/Y can be used
384
- */
385
- if (!this.colorsParsed) {
386
-
387
- this.parseColors();
388
-
389
- // Don't want to do this again
390
- this.colorsParsed = true;
391
- }
392
-
393
-
394
-
395
-
396
- /**
397
- * This sets the label colors. Doing it here saves lots of if() conditions in the draw method
398
- */
399
- if (prop['chart.labels.colors'].length < prop['chart.labels'].length) {
400
- while (prop['chart.labels.colors'].length < prop['chart.labels'].length) {
401
- prop['chart.labels.colors'].push(prop['chart.labels.colors'][prop['chart.labels.colors'].length - 1]);
402
- }
403
- } else {
404
- if (typeof prop['chart.labels.colors'] === 'undefined') {
405
- prop['chart.labels.colors'] = [];
406
- }
407
-
408
- while (prop['chart.labels.colors'].length < prop['chart.labels'].length) {
409
- prop['chart.labels.colors'].push(prop['chart.text.color']);
410
- }
411
- }
412
-
413
-
414
-
415
-
416
- if (prop['chart.variant'].indexOf('3d') > 0) {
417
- return this.draw3d();
418
- }
419
-
420
-
421
-
422
-
423
- /**
424
- * Draw the title
425
- */
426
- RG.DrawTitle(
427
- this,
428
- prop['chart.title'],
429
- (ca.height / 2) - this.radius - 5,
430
- this.centerx,
431
- prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2
432
- );
433
-
434
- /**
435
- * Draw the shadow if required
436
- *
437
- * ???
438
- */
439
- //if (prop['chart.shadow'] && false) {
440
- //
441
- // var offsetx = doc.all ? prop['chart.shadow.offsetx'] : 0;
442
- // var offsety = doc.all ? prop['chart.shadow.offsety'] : 0;
443
- //
444
- // co.beginPath();
445
- // co.fillStyle = prop['chart.shadow.color'];
446
- //
447
- // co.shadowColor = prop['chart.shadow.color'];
448
- // co.shadowBlur = prop['chart.shadow.blur'];
449
- // co.shadowOffsetX = prop['chart.shadow.offsetx'];
450
- // co.shadowOffsetY = prop['chart.shadow.offsety'];
451
- //
452
- // co.arc(this.centerx + offsetx, this.centery + offsety, this.radius, 0, TWOPI, 0);
453
- //
454
- // co.fill();
455
- //
456
- // // Now turn off the shadow
457
- // RG.NoShadow(this);
458
- //}
459
-
460
- /**
461
- * The total of the array of values
462
- */
463
- this.total = RG.array_sum(this.data);
464
- var tot = this.total;
465
- var data = this.data;
466
-
467
- for (var i=0,len=this.data.length; i<len; i++) {
468
-
469
- var angle = ((data[i] / tot) * RG.TWOPI);
470
-
471
- // Draw the segment
472
- this.DrawSegment(angle,prop['chart.colors'][i],i == (len - 1), i);
473
- }
474
-
475
- RG.NoShadow(this);
476
-
477
- /**
478
- * Redraw the seperating lines
479
- */
480
- if (prop['chart.linewidth'] > 0) {
481
- this.DrawBorders();
482
- }
483
-
484
- /**
485
- * Now draw the segments again with shadow turned off. This is always performed,
486
- * not just if the shadow is on.
487
- */
488
- var len = this.angles.length;
489
- var r = this.radius;
490
-
491
-
492
- for (var action=0; action<2; action+=1) {
493
- for (var i=0; i<len; i++) {
494
-
495
- co.beginPath();
496
-
497
- var segment = this.angles[i];
498
-
499
- if (action === 1) {
500
- co.strokeStyle = typeof(prop['chart.strokestyle']) == 'object' ? prop['chart.strokestyle'][i] : prop['chart.strokestyle'];
501
- }
502
- prop['chart.colors'][i] ? co.fillStyle = prop['chart.colors'][i] : null;
503
- co.lineJoin = 'round';
504
-
505
- co.arc(segment[2],
506
- segment[3],
507
- r,
508
- (segment[0]),
509
- (segment[1]),
510
- false);
511
- if (prop['chart.variant'] == 'donut') {
512
-
513
- co.arc(
514
- segment[2],
515
- segment[3],
516
- typeof(prop['chart.variant.donut.width']) == 'number' ? r - prop['chart.variant.donut.width'] : r / 2,
517
- (segment[1]),
518
- (segment[0]),
519
- true
520
- );
521
-
522
- } else {
523
- co.lineTo(segment[2], segment[3]);
524
- }
525
- co.closePath();
526
- action === 0 ? co.fill() : co.stroke();
527
- }
528
- }
529
-
530
-
531
-
532
-
533
- /**
534
- * Draw label sticks
535
- */
536
- if (prop['chart.labels.sticks']) {
537
-
538
- this.DrawSticks();
539
-
540
- // Redraw the border going around the Pie chart if the stroke style is NOT white
541
- var strokeStyle = prop['chart.strokestyle'];
542
- }
543
-
544
- /**
545
- * Draw the labels
546
- */
547
- if (prop['chart.labels']) {
548
- this.DrawLabels();
549
- }
550
-
551
-
552
- /**
553
- * Draw centerpin if requested
554
- */
555
- if (prop['chart.centerpin']) {
556
- this.DrawCenterpin();
557
- }
558
-
559
-
560
-
561
-
562
- /**
563
- * Draw ingraph labels
564
- */
565
- if (prop['chart.labels.ingraph']) {
566
- this.DrawInGraphLabels();
567
- }
568
-
569
-
570
-
571
-
572
- /**
573
- * Draw the center label if requested
574
- */
575
- if (!RG.isNull(prop['chart.labels.center'])) {
576
- this.drawCenterLabel(prop['chart.labels.center']);
577
- }
578
-
579
-
580
- /**
581
- * Setup the context menu if required
582
- */
583
- if (prop['chart.contextmenu']) {
584
- RG.ShowContext(this);
585
- }
586
-
587
-
588
-
589
- /**
590
- * If a border is pecified, draw it
591
- */
592
- if (prop['chart.border']) {
593
- co.beginPath();
594
- co.lineWidth = 5;
595
- co.strokeStyle = prop['chart.border.color'];
596
-
597
- co.arc(this.centerx,
598
- this.centery,
599
- this.radius - 2,
600
- 0,
601
- RG.TWOPI,
602
- 0);
603
-
604
- co.stroke();
605
- }
606
-
607
- /**
608
- * Draw the kay if desired
609
- */
610
- if (prop['chart.key'] && prop['chart.key'].length) {
611
- RG.DrawKey(this, prop['chart.key'], prop['chart.colors']);
612
- }
613
-
614
- RG.NoShadow(this);
615
-
616
-
617
- /**
618
- * This function enables resizing
619
- */
620
- if (prop['chart.resizable']) {
621
- RG.AllowResizing(this);
622
- }
623
-
624
-
625
- /**
626
- * This installs the event listeners
627
- */
628
- if (prop['chart.events'] == true) {
629
- RG.InstallEventListeners(this);
630
- }
631
-
632
-
633
- /**
634
- * Fire the onfirstdraw event
635
- */
636
- if (this.firstDraw) {
637
- RG.fireCustomEvent(this, 'onfirstdraw');
638
- this.firstDraw = false;
639
- this.firstDrawFunc();
640
- }
641
-
642
-
643
-
644
-
645
- /**
646
- * Fire the RGraph ondraw event
647
- */
648
- RG.FireCustomEvent(this, 'ondraw');
649
-
650
- return this;
651
- };
652
-
653
-
654
-
655
- /**
656
- * Used in chaining. Runs a function there and then - not waiting for
657
- * the events to fire (eg the onbeforedraw event)
658
- *
659
- * @param function func The function to execute
660
- */
661
- this.exec = function (func)
662
- {
663
- func(this);
664
-
665
- return this;
666
- };
667
-
668
-
669
-
670
-
671
- /**
672
- * Draws a single segment of the pie chart
673
- *
674
- * @param int degrees The number of degrees for this segment
675
- */
676
- this.drawSegment =
677
- this.DrawSegment = function (radians, color, last, index)
678
- {
679
- // IE7/8/ExCanvas fix (when there's only one segment the Pie chart doesn't display
680
- if (RGraph.ISOLD && radians == RG.TWOPI) {
681
- radians -= 0.0001;
682
- } else if (RGraph.ISOLD && radians == 0) {
683
- radians = 0.001;
684
- }
685
-
686
- var subTotal = this.subTotal;
687
- radians = radians * prop['chart.effect.roundrobin.multiplier'];
688
-
689
- co.beginPath();
690
-
691
- color ? co.fillStyle = color : null;
692
- co.strokeStyle = prop['chart.strokestyle'];
693
- co.lineWidth = 0;
694
-
695
- if (prop['chart.shadow']) {
696
- RG.setShadow(
697
- this,
698
- prop['chart.shadow.color'],
699
- prop['chart.shadow.offsetx'],
700
- prop['chart.shadow.offsety'],
701
- prop['chart.shadow.blur']
702
- );
703
- }
704
-
705
- /**
706
- * Exploded segments
707
- */
708
- if ( (typeof(prop['chart.exploded']) == 'object' && prop['chart.exploded'][index] > 0) || typeof(prop['chart.exploded']) == 'number') {
709
-
710
- var explosion = typeof(prop['chart.exploded']) == 'number' ? prop['chart.exploded'] : prop['chart.exploded'][index];
711
- var x = 0;
712
- var y = 0;
713
- var h = explosion;
714
- var t = subTotal + (radians / 2);
715
- var x = (Math.cos(t) * explosion);
716
- var y = (Math.sin(t) * explosion);
717
- var r = this.radius;
718
-
719
- co.moveTo(this.centerx + x, this.centery + y);
720
- } else {
721
- var x = 0;
722
- var y = 0;
723
- var r = this.radius;
724
- }
725
-
726
- /**
727
- * Calculate the angles
728
- */
729
- var startAngle = subTotal;
730
- var endAngle = ((subTotal + radians));
731
-
732
- co.arc(this.centerx + x,
733
- this.centery + y,
734
- r,
735
- startAngle,
736
- endAngle,
737
- 0);
738
-
739
- if (prop['chart.variant'] == 'donut') {
740
-
741
- co.arc(this.centerx + x,
742
- this.centery + y,
743
- typeof(prop['chart.variant.donut.width']) == 'number' ? r - prop['chart.variant.donut.width'] : r / 2,
744
- endAngle,
745
- startAngle,
746
- true);
747
- } else {
748
- co.lineTo(this.centerx + x, this.centery + y);
749
- }
750
-
751
- co.closePath();
752
-
753
-
754
- // Keep hold of the angles
755
- this.angles.push([subTotal, subTotal + radians, this.centerx + x, this.centery + y]);
756
-
757
-
758
-
759
- //co.stroke();
760
- co.fill();
761
-
762
- /**
763
- * Calculate the segment angle
764
- */
765
- this.subTotal += radians;
766
- };
767
-
768
-
769
-
770
-
771
- /**
772
- * Draws the graphs labels
773
- */
774
- this.drawLabels =
775
- this.DrawLabels = function ()
776
- {
777
- // New way of spacing labels out
778
- if (prop['chart.labels'].length && prop['chart.labels.sticks.list']) {
779
- return this.drawLabelsList();
780
- }
781
-
782
- var hAlignment = 'left',
783
- vAlignment = 'center',
784
- labels = prop['chart.labels'],
785
- context = co,
786
- font = prop['chart.text.font'],
787
- bold = prop['chart.labels.bold'],
788
- text_size = prop['chart.text.size'],
789
- cx = this.centerx,
790
- cy = this.centery,
791
- r = this.radius;
792
-
793
- /**
794
- * Turn the shadow off
795
- */
796
- RG.noShadow(this);
797
-
798
- co.fillStyle = 'black';
799
- co.beginPath();
800
-
801
- /**
802
- * Draw the labels
803
- */
804
- if (labels && labels.length) {
805
-
806
- for (i=0; i<this.angles.length; ++i) {
807
-
808
- var segment = this.angles[i];
809
-
810
- if (typeof labels[i] != 'string' && typeof labels[i] != 'number') {
811
- continue;
812
- }
813
-
814
- // Move to the centre
815
- co.moveTo(cx,cy);
816
-
817
- var a = segment[0] + ((segment[1] - segment[0]) / 2),
818
- angle = ((segment[1] - segment[0]) / 2) + segment[0];
819
-
820
- /**
821
- * Handle the additional "explosion" offset
822
- */
823
- if (typeof prop['chart.exploded'] === 'object' && prop['chart.exploded'][i] || typeof prop['chart.exploded'] == 'number') {
824
-
825
- var t = ((segment[1] - segment[0]) / 2),
826
- seperation = typeof(prop['chart.exploded']) == 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i];
827
-
828
- // Adjust the angles
829
- var explosion_offsetx = (Math.cos(angle) * seperation),
830
- explosion_offsety = (Math.sin(angle) * seperation);
831
- } else {
832
- var explosion_offsetx = 0,
833
- explosion_offsety = 0;
834
- }
835
-
836
- /**
837
- * Allow for the label sticks
838
- */
839
- if (prop['chart.labels.sticks']) {
840
- explosion_offsetx += (ma.cos(angle) * (typeof prop['chart.labels.sticks.length'] === 'object' ? prop['chart.labels.sticks.length'][i] : prop['chart.labels.sticks.length']) );
841
- explosion_offsety += (ma.sin(angle) * (typeof prop['chart.labels.sticks.length'] === 'object' ? prop['chart.labels.sticks.length'][i] : prop['chart.labels.sticks.length']) );
842
- }
843
-
844
- /**
845
- * Coords for the text
846
- */
847
- var x = cx + explosion_offsetx + ((r + 10)* Math.cos(a)) + (prop['chart.labels.sticks'] ? (a < RG.HALFPI || a > (RG.TWOPI + RG.HALFPI) ? 2 : -2) : 0),
848
- y = cy + explosion_offsety + (((r + 10) * Math.sin(a)));
849
-
850
-
851
-
852
-
853
- /**
854
- * If sticks are enabled use the endpoints that have been saved
855
- */
856
- if (this.coordsSticks && this.coordsSticks[i]) {
857
- var x = this.coordsSticks[i][4][0] + (x < cx ? -5 : 5),
858
- y = this.coordsSticks[i][4][1];
859
- }
860
-
861
-
862
- /**
863
- * Alignment
864
- */
865
- //vAlignment = y < cy ? 'center' : 'center';
866
- vAlignment = 'center';
867
- hAlignment = x < cx ? 'right' : 'left';
868
-
869
- co.fillStyle = prop['chart.text.color'];
870
- if ( typeof prop['chart.labels.colors'] === 'object' && prop['chart.labels.colors'] && prop['chart.labels.colors'][i]) {
871
- co.fillStyle = prop['chart.labels.colors'][i];
872
- }
873
-
874
-
875
- RG.text2(this, {
876
- font: font,
877
- size: text_size,
878
- x: x,
879
- y: y,
880
- text: labels[i],
881
- valign: vAlignment,
882
- halign: hAlignment,
883
- tag: 'labels',
884
- bold: bold,
885
- color: prop['chart.labels.sticks.usecolors'] ? prop['chart.colors'][i] : 'black'
886
- });
887
- }
888
-
889
- co.fill();
890
- }
891
- };
892
-
893
-
894
-
895
-
896
- //
897
- // A new way of spacing out labels
898
- //
899
- this.drawLabelsList = function ()
900
- {
901
- var segment = this.angles[i],
902
- labels = prop['chart.labels'],
903
- labels_right = [],
904
- labels_left = [],
905
- text_font = prop['chart.text.font'],
906
- text_size = prop['chart.text.size'],
907
- text_color = prop['chart.text.color'],
908
- left = [],
909
- right = [],
910
- centerx = this.centerx,
911
- centery = this.centery,
912
- radius = this.radius,
913
- offset = 50
914
-
915
-
916
-
917
-
918
-
919
-
920
-
921
-
922
- //
923
- // Draw the right hand side labels first
924
- //
925
- for (var i=0; i<this.angles.length; ++i) {
926
-
927
- var angle = this.angles[i][0] + ((this.angles[i][1] - this.angles[i][0]) / 2), // Midpoint
928
- endpoint_inner = RG.getRadiusEndPoint(centerx, centery, angle, radius + 5),
929
- endpoint_outer = RG.getRadiusEndPoint(centerx, centery, angle, radius + 10),
930
- explosion = [
931
- (typeof prop['chart.exploded'] === 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i]),
932
- (ma.cos(angle) * (typeof prop['chart.exploded'] === 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i])),
933
- (ma.sin(angle) * (typeof prop['chart.exploded'] === 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i]))
934
- ]
935
-
936
-
937
- //
938
- // Work out the color
939
- //
940
- if ( typeof prop['chart.labels.sticks.colors'] === 'object' && prop['chart.labels.sticks.colors'] && prop['chart.labels.sticks.colors'][i] ) {
941
- var color = prop['chart.labels.sticks.colors'][i];
942
- } else if ( prop['chart.labels.sticks.usecolors'] && prop['chart.colors'][i] ) {
943
- var color = prop['chart.colors'][i];
944
- } else {
945
- var color = prop['chart.text.color'];
946
- }
947
-
948
-
949
-
950
-
951
- if (angle > (-1 * RG.HALFPI) && angle < RG.HALFPI) {
952
- labels_right.push([
953
- i,
954
- angle,
955
- labels[i] ? labels[i] : '',
956
- endpoint_inner,
957
- endpoint_outer,
958
- color,
959
- RG.arrayClone(explosion)
960
- ]);
961
- } else {
962
- labels_left.push([
963
- i,
964
- angle,
965
- labels[i] ? labels[i] : '',
966
- endpoint_inner,
967
- endpoint_outer,
968
- color,
969
- RG.arrayClone(explosion)
970
- ]);
971
- }
972
- }
973
-
974
-
975
-
976
-
977
- //
978
- // Draw the right hand side labels first
979
- //
980
-
981
-
982
- // Calculate how much space there is for each label
983
- var vspace_right = (ca.height - prop['chart.gutter.top'] - prop['chart.gutter.bottom']) / labels_right.length
984
-
985
- for (var i=0,y=(prop['chart.gutter.top'] + (vspace_right / 2)); i<labels_right.length; y+=vspace_right,i++) {
986
-
987
- if (labels_right[i][2]) {
988
-
989
- var x = this.centerx + this.radius + offset,
990
- idx = labels_right[i][0],
991
- explosionX = labels_right[i][6][0] ? labels_right[i][6][1] : 0,
992
- explosionY = labels_right[i][6][0] ? labels_right[i][6][2] : 0
993
-
994
- var ret = RG.text2(this, {
995
- font: text_font,
996
- size: text_size,
997
- x: x + explosionX,
998
- y: y + explosionY,
999
- text: labels_right[i][2],
1000
- valign: 'center',
1001
- halign: 'left',
1002
- tag: 'labels',
1003
- color: labels_right[i][5]
1004
- });
1005
-
1006
- if (ret && ret.node) {
1007
- ret.node.__index__ = labels_right[i][0];
1008
- }
1009
-
1010
-
1011
- pa2(co, 'lc round lw % b m % % l % % l % % l % % s %',
1012
-
1013
- prop['chart.labels.sticks.linewidth'],
1014
-
1015
- labels_right[i][3][0] + explosionX,
1016
- labels_right[i][3][1] + explosionY,
1017
-
1018
- labels_right[i][4][0] + explosionX,
1019
- labels_right[i][4][1] + explosionY,
1020
-
1021
- this.centerx + this.radius + 25 + explosionX,
1022
- ma.round(labels_right[i][4][1] + explosionY),
1023
-
1024
- ret.x - 5 ,
1025
- ret.y + (ret.height / 2),
1026
-
1027
- labels_right[i][5]
1028
- );
1029
- }
1030
- }
1031
-
1032
-
1033
-
1034
-
1035
-
1036
-
1037
-
1038
-
1039
-
1040
- //
1041
- // Draw the left hand side labels
1042
- //
1043
-
1044
-
1045
-
1046
-
1047
-
1048
- // Calculate how much space there is for each label
1049
- var vspace_left = (ca.height - prop['chart.gutter.top'] - prop['chart.gutter.bottom']) / labels_left.length
1050
-
1051
- for (var i=(labels_left.length - 1),y=(prop['chart.gutter.top'] + (vspace_left / 2)); i>=0; y+=vspace_left,i--) {
1052
-
1053
- if (labels_left[i][2]) {
1054
-
1055
- var x = this.centerx - this.radius - offset,
1056
- idx = labels_left[i][0],
1057
- explosionX = labels_left[i][6][0] ? labels_left[i][6][1] : 0,
1058
- explosionY = labels_left[i][6][0] ? labels_left[i][6][2] : 0
1059
-
1060
- var ret = RG.text2(this, {
1061
- font: text_font,
1062
- size: text_size,
1063
- x: x + explosionX,
1064
- y: y + explosionY,
1065
- text: labels_left[i][2],
1066
- valign: 'center',
1067
- halign: 'right',
1068
- tag: 'labels',
1069
- color: labels_left[i][5]
1070
- });
1071
-
1072
- if (ret && ret.node) {
1073
- ret.node.__index__ = labels_left[i][0];
1074
- }
1075
-
1076
- pa2(co,
1077
- 'lw % b m % % l % % l % % l % % s %',
1078
-
1079
- prop['chart.labels.sticks.linewidth'],
1080
-
1081
- labels_left[i][3][0] + explosionX,
1082
- labels_left[i][3][1] + explosionY,
1083
-
1084
- labels_left[i][4][0] + explosionX,
1085
- labels_left[i][4][1] + explosionY,
1086
-
1087
- this.centerx - this.radius - 25 + explosionX,
1088
- ma.round(labels_left[i][4][1] + explosionY),
1089
-
1090
- ret.x + 5 + ret.width,
1091
- ret.y + (ret.height / 2),
1092
-
1093
- labels_left[i][5]
1094
- );
1095
- }
1096
- }
1097
- };
1098
-
1099
-
1100
-
1101
-
1102
-
1103
-
1104
-
1105
-
1106
-
1107
-
1108
-
1109
-
1110
-
1111
-
1112
-
1113
-
1114
-
1115
-
1116
-
1117
- /**
1118
- * This function draws the pie chart sticks (for the labels)
1119
- */
1120
- this.drawSticks =
1121
- this.DrawSticks = function ()
1122
- {
1123
- var offset = prop['chart.linewidth'] / 2,
1124
- exploded = prop['chart.exploded'],
1125
- sticks = prop['chart.labels.sticks'],
1126
- colors = prop['chart.colors'],
1127
- cx = this.centerx,
1128
- cy = this.centery,
1129
- radius = this.radius,
1130
- points = [],
1131
- linewidth = prop['chart.labels.sticks.linewidth']
1132
-
1133
- for (var i=0,len=this.angles.length; i<len; ++i) {
1134
-
1135
- var segment = this.angles[i];
1136
-
1137
- // This allows the chart.labels.sticks to be an array as well as a boolean
1138
- if (typeof sticks === 'object' && !sticks[i]) {
1139
- continue;
1140
- }
1141
-
1142
- var radians = segment[1] - segment[0];
1143
-
1144
- co.beginPath();
1145
- co.strokeStyle = typeof prop['chart.labels.sticks.colors'] === 'string' ? prop['chart.labels.sticks.colors'] : (!RG.isNull(prop['chart.labels.sticks.colors']) ? prop['chart.labels.sticks.colors'][i] : 'gray');
1146
- co.lineWidth = linewidth;
1147
-
1148
- if (typeof prop['chart.labels.sticks.color'] === 'string') {
1149
- co.strokeStyle = prop['chart.labels.sticks.color'];
1150
- }
1151
-
1152
- //
1153
- // Allow for labelsSticksUseColors
1154
- //
1155
- if (prop['chart.labels.sticks.usecolors']) {
1156
- co.strokeStyle = prop['chart.colors'][i];
1157
- }
1158
-
1159
- var midpoint = (segment[0] + (radians / 2));
1160
-
1161
- if (typeof exploded === 'object' && exploded[i]) {
1162
- var extra = exploded[i];
1163
- } else if (typeof exploded === 'number') {
1164
- var extra = exploded;
1165
- } else {
1166
- var extra = 0;
1167
- }
1168
-
1169
- /**
1170
- * Determine the stick length
1171
- */
1172
- var stickLength = typeof prop['chart.labels.sticks.length'] === 'object' ? prop['chart.labels.sticks.length'][i] : prop['chart.labels.sticks.length'];
1173
-
1174
-
1175
- points[0] = RG.getRadiusEndPoint(cx, cy, midpoint, radius + extra + offset);
1176
- points[1] = RG.getRadiusEndPoint(cx, cy, midpoint, radius + stickLength + extra - 5);
1177
-
1178
- points[2] = RG.getRadiusEndPoint(cx, cy, midpoint, radius + stickLength + extra);
1179
-
1180
- points[3] = RG.getRadiusEndPoint(cx, cy, midpoint, radius + stickLength + extra);
1181
- points[3][0] += (points[3][0] > cx ? 5 : -5);
1182
-
1183
- points[4] = [
1184
- points[2][0] + (points[2][0] > cx ? 5 + prop['chart.labels.sticks.hlength'] : -5 - prop['chart.labels.sticks.hlength']),
1185
- points[2][1]
1186
- ];
1187
-
1188
-
1189
- co.moveTo(points[0][0], points[0][1]);
1190
- co.quadraticCurveTo(points[2][0], points[2][1], points[4][0], points[4][1]);
1191
-
1192
- co.stroke();
1193
-
1194
- /**
1195
- * Save the stick end coords
1196
- */
1197
- this.coordsSticks[i] = [points[0],points[1], points[2], points[3], points[4]];
1198
- }
1199
- };
1200
-
1201
-
1202
-
1203
-
1204
- /**
1205
- * The (now Pie chart specific) getSegment function
1206
- *
1207
- * @param object e The event object
1208
- */
1209
- this.getShape =
1210
- this.getSegment = function (e)
1211
- {
1212
- RG.FixEventObject(e);
1213
-
1214
- // The optional arg provides a way of allowing some accuracy (pixels)
1215
- var accuracy = arguments[1] ? arguments[1] : 0;
1216
-
1217
- var canvas = ca;
1218
- var context = co;
1219
- var mouseCoords = RG.getMouseXY(e);
1220
- var mouseX = mouseCoords[0];
1221
- var mouseY = mouseCoords[1];
1222
- var r = this.radius;
1223
- var angles = this.angles;
1224
- var ret = [];
1225
-
1226
- for (var i=0,len=angles.length; i<len; ++i) {
1227
-
1228
- // DRAW THE SEGMENT AGAIN SO IT CAN BE TESTED //////////////////////////
1229
- co.beginPath();
1230
- co.strokeStyle = 'rgba(0,0,0,0)';
1231
- co.arc(angles[i][2], angles[i][3], this.radius, angles[i][0], angles[i][1], false);
1232
-
1233
- if (this.type == 'pie' && prop['chart.variant'] == 'donut') {
1234
- co.arc(angles[i][2], angles[i][3], (typeof(prop['chart.variant.donut.width']) == 'number' ? this.radius - prop['chart.variant.donut.width'] : this.radius / 2), angles[i][1], angles[i][0], true);
1235
- } else {
1236
- co.lineTo(angles[i][2], angles[i][3]);
1237
- }
1238
- co.closePath();
1239
-
1240
- if (!co.isPointInPath(mouseX, mouseY)) {
1241
- continue;
1242
- }
1243
-
1244
- ////////////////////////////////////////////////////////////////////////
1245
-
1246
- ret[0] = angles[i][2];
1247
- ret[1] = angles[i][3];
1248
- ret[2] = this.radius;
1249
- ret[3] = angles[i][0] - RG.TWOPI;
1250
- ret[4] = angles[i][1];
1251
- ret[5] = i;
1252
-
1253
-
1254
-
1255
- if (ret[3] < 0) ret[3] += RG.TWOPI;
1256
- if (ret[4] > RG.TWOPI) ret[4] -= RG.TWOPI;
1257
-
1258
- /**
1259
- * Add the tooltip to the returned shape
1260
- */
1261
- var tooltip = RG.parseTooltipText ? RG.parseTooltipText(prop['chart.tooltips'], ret[5]) : null;
1262
-
1263
- /**
1264
- * Now return textual keys as well as numerics
1265
- */
1266
- ret['object'] = this;
1267
- ret['x'] = ret[0];
1268
- ret['y'] = ret[1];
1269
- ret['radius'] = ret[2];
1270
- ret['angle.start'] = ret[3];
1271
- ret['angle.end'] = ret[4];
1272
- ret['index'] = ret[5];
1273
- ret['tooltip'] = tooltip;
1274
-
1275
- return ret;
1276
- }
1277
-
1278
- return null;
1279
- };
1280
-
1281
-
1282
-
1283
-
1284
- this.drawBorders =
1285
- this.DrawBorders = function ()
1286
- {
1287
- if (prop['chart.linewidth'] > 0) {
1288
-
1289
- co.lineWidth = prop['chart.linewidth'];
1290
- co.strokeStyle = prop['chart.strokestyle'];
1291
-
1292
- var r = this.radius;
1293
-
1294
- for (var i=0,len=this.angles.length; i<len; ++i) {
1295
-
1296
- var segment = this.angles[i];
1297
-
1298
- co.beginPath();
1299
- co.arc(segment[2],
1300
- segment[3],
1301
- r,
1302
- (segment[0]),
1303
- (segment[0] + 0.001),
1304
- 0);
1305
- co.arc(segment[2],
1306
- segment[3],
1307
- prop['chart.variant'] == 'donut' ? (typeof(prop['chart.variant.donut.width']) == 'number' ? this.radius - prop['chart.variant.donut.width'] : r / 2): r,
1308
- segment[0],
1309
- segment[0] + 0.0001,
1310
- 0);
1311
- co.closePath();
1312
- co.stroke();
1313
- }
1314
- }
1315
- };
1316
-
1317
-
1318
-
1319
-
1320
- /**
1321
- * Returns the radius of the pie chart
1322
- *
1323
- * [06-02-2012] Maintained for compatibility ONLY.
1324
- */
1325
- this.getRadius = function ()
1326
- {
1327
- this.graph = {width: ca.width - prop['chart.gutter.left'] - prop['chart.gutter.right'], height: ca.height - prop['chart.gutter.top'] - prop['chart.gutter.bottom']}
1328
-
1329
- if (typeof(prop['chart.radius']) == 'number') {
1330
- this.radius = prop['chart.radius'];
1331
- } else {
1332
- this.radius = Math.min(this.graph.width, this.graph.height) / 2;
1333
- }
1334
-
1335
- return this.radius;
1336
- };
1337
-
1338
-
1339
-
1340
-
1341
- /**
1342
- * A programmatic explode function
1343
- *
1344
- * @param object obj The chart object
1345
- * @param number index The zero-indexed number of the segment
1346
- * @param number size The size (in pixels) of the explosion
1347
- */
1348
- this.explodeSegment =
1349
- this.Explode = function (index, size)
1350
- {
1351
- if (typeof this.exploding === 'number' && this.exploding === index) {
1352
- return;
1353
- }
1354
-
1355
- //this.Set('chart.exploded', []);
1356
- if (!prop['chart.exploded']) {
1357
- prop['chart.exploded'] = [];
1358
- }
1359
-
1360
- // If chart.exploded is a number - convert it to an array
1361
- if (typeof(prop['chart.exploded']) == 'number') {
1362
-
1363
- var original_explode = prop['chart.exploded'];
1364
- var exploded = prop['chart.exploded'];
1365
-
1366
- prop['chart.exploded'] = [];
1367
-
1368
- for (var i=0,len=this.data.length; i<len; ++i) {
1369
- prop['chart.exploded'][i] = exploded;
1370
- }
1371
- }
1372
-
1373
- prop['chart.exploded'][index] = typeof(original_explode) == 'number' ? original_explode : 0;
1374
-
1375
- this.exploding = index;
1376
- var delay = RG.ISIE && !RG.ISIE10 ? 25 : 16.666;
1377
-
1378
- for (var o=0; o<size; ++o) {
1379
-
1380
- setTimeout(
1381
- function ()
1382
- {
1383
- prop['chart.exploded'][index] += 1;
1384
- RG.Clear(ca);
1385
- RG.RedrawCanvas(ca);
1386
- }, o * delay);
1387
- }
1388
-
1389
- var obj = this;
1390
- setTimeout(function ()
1391
- {
1392
- obj.exploding = null;
1393
- }, size * delay);
1394
- };
1395
-
1396
-
1397
-
1398
-
1399
- /**
1400
- * This function highlights a segment
1401
- *
1402
- * @param array segment The segment information that is returned by the pie.getSegment(e) function
1403
- */
1404
- this.highlight_segment = function (segment)
1405
- {
1406
- co.beginPath();
1407
- co.strokeStyle = prop['chart.highlight.style.twod.stroke'];
1408
- co.fillStyle = prop['chart.highlight.style.twod.fill'];
1409
- co.moveTo(segment[0], segment[1]);
1410
- co.arc(segment[0], segment[1], segment[2], this.angles[segment[5]][0], this.angles[segment[5]][1], 0);
1411
- co.lineTo(segment[0], segment[1]);
1412
- co.closePath();
1413
-
1414
- co.stroke();
1415
- co.fill();
1416
- };
1417
-
1418
-
1419
-
1420
-
1421
- /**
1422
- * Each object type has its own Highlight() function which highlights
1423
- * the appropriate shape
1424
- *
1425
- * @param object shape The shape to highlight
1426
- */
1427
- this.highlight =
1428
- this.Highlight = function (shape)
1429
- {
1430
- if (prop['chart.tooltips.highlight']) {
1431
-
1432
- if (typeof prop['chart.highlight.style'] === 'function') {
1433
- (prop['chart.highlight.style'])(shape);
1434
-
1435
- /**
1436
- * 3D style of highlighting
1437
- */
1438
- } else if (prop['chart.highlight.style'] == '3d') {
1439
-
1440
- co.lineWidth = 1;
1441
-
1442
- // This is the extent of the 2D effect. Bigger values will give the appearance of a larger "protusion"
1443
- var extent = 2;
1444
-
1445
- // Draw a white-out where the segment is
1446
- co.beginPath();
1447
- RG.NoShadow(this);
1448
- co.fillStyle = 'rgba(0,0,0,0)';
1449
- co.arc(shape['x'], shape['y'], shape['radius'], shape['angle.start'], shape['angle.end'], false);
1450
- if (prop['chart.variant'] == 'donut') {
1451
- co.arc(shape['x'], shape['y'], shape['radius'] / 5, shape['angle.end'], shape['angle.start'], true);
1452
- } else {
1453
- co.lineTo(shape['x'], shape['y']);
1454
- }
1455
- co.closePath();
1456
- co.fill();
1457
-
1458
- // Draw the new segment
1459
- co.beginPath();
1460
-
1461
- co.shadowColor = '#666';
1462
- co.shadowBlur = 3;
1463
- co.shadowOffsetX = 3;
1464
- co.shadowOffsetY = 3;
1465
-
1466
- co.fillStyle = prop['chart.colors'][shape['index']];
1467
- co.strokeStyle = prop['chart.strokestyle'];
1468
- co.arc(shape['x'] - extent, shape['y'] - extent, shape['radius'], shape['angle.start'], shape['angle.end'], false);
1469
- if (prop['chart.variant'] == 'donut') {
1470
- co.arc(shape['x'] - extent, shape['y'] - extent, shape['radius'] / 2, shape['angle.end'], shape['angle.start'], true)
1471
- } else {
1472
- co.lineTo(shape['x'] - extent, shape['y'] - extent);
1473
- }
1474
- co.closePath();
1475
-
1476
- co.stroke();
1477
- co.fill();
1478
-
1479
- // Turn off the shadow
1480
- RG.NoShadow(this);
1481
-
1482
- /**
1483
- * If a border is defined, redraw that
1484
- */
1485
- if (prop['chart.border']) {
1486
- co.beginPath();
1487
- co.strokeStyle = prop['chart.border.color'];
1488
- co.lineWidth = 5;
1489
- co.arc(shape['x'] - extent, shape['y'] - extent, shape['radius'] - 2, shape['angle.start'], shape['angle.end'], false);
1490
- co.stroke();
1491
- }
1492
-
1493
-
1494
-
1495
-
1496
- // Outline style of highlighting
1497
- } else if (prop['chart.highlight.style'] === 'outline') {
1498
-
1499
- var tooltip = RG.Registry.get('chart.tooltip'),
1500
- index = tooltip.__index__,
1501
- coords = this.angles[index],
1502
- color = this.get('colors')[index]
1503
- width = this.radius / 12.5;
1504
-
1505
- // Allow custom setting of outline
1506
- if (typeof prop['chart.highlight.style.outline.width'] === 'number') {
1507
- width = prop['chart.highlight.style.outline.width'];
1508
- }
1509
-
1510
-
1511
-
1512
- RGraph.path2(
1513
- co,
1514
- 'ga 0.25 b a % % % % % false a % % % % % true c f % ga 1',
1515
- coords[2],
1516
- coords[3],
1517
- this.radius + 2 + width,
1518
- coords[0],
1519
- coords[1],
1520
-
1521
- coords[2],
1522
- coords[3],
1523
- this.radius + 2,
1524
- coords[1],
1525
- coords[0],
1526
- color
1527
- );
1528
-
1529
-
1530
-
1531
-
1532
-
1533
-
1534
- // Default 2D style of highlighting
1535
- } else {
1536
-
1537
- co.beginPath();
1538
-
1539
- co.strokeStyle = prop['chart.highlight.style.twod.stroke'];
1540
- co.fillStyle = prop['chart.highlight.style.twod.fill'];
1541
-
1542
- if (prop['chart.variant'].indexOf('donut') > -1) {
1543
- co.arc(shape['x'], shape['y'], shape['radius'], shape['angle.start'], shape['angle.end'], false);
1544
- co.arc(shape['x'], shape['y'], typeof(prop['chart.variant.donut.width']) == 'number' ? this.radius - prop['chart.variant.donut.width'] : shape['radius'] / 2, shape['angle.end'], shape['angle.start'], true);
1545
- } else {
1546
- co.arc(shape['x'], shape['y'], shape['radius'] + 1, shape['angle.start'], shape['angle.end'], false);
1547
- co.lineTo(shape['x'], shape['y']);
1548
- }
1549
- co.closePath();
1550
-
1551
- co.stroke();
1552
- co.fill();
1553
- }
1554
- }
1555
- };
1556
-
1557
-
1558
-
1559
-
1560
- /**
1561
- * The getObjectByXY() worker method. The Pie chart is able to use the
1562
- * getShape() method - so it does.
1563
- */
1564
- this.getObjectByXY = function (e)
1565
- {
1566
- if (this.getShape(e)) {
1567
- return this;
1568
- }
1569
- };
1570
-
1571
-
1572
-
1573
-
1574
- /**
1575
- * Draws the centerpin if requested
1576
- */
1577
- this.drawCenterpin =
1578
- this.DrawCenterpin = function ()
1579
- {
1580
- if (typeof(prop['chart.centerpin']) == 'number' && prop['chart.centerpin'] > 0) {
1581
-
1582
- var cx = this.centerx;
1583
- var cy = this.centery;
1584
-
1585
- co.beginPath();
1586
- co.strokeStyle = prop['chart.centerpin.stroke'] ? prop['chart.centerpin.stroke'] : prop['chart.strokestyle'];
1587
- co.fillStyle = prop['chart.centerpin.fill'] ? prop['chart.centerpin.fill'] : prop['chart.strokestyle'];
1588
- co.moveTo(cx, cy);
1589
- co.arc(cx, cy, prop['chart.centerpin'], 0, RG.TWOPI, false);
1590
- co.stroke();
1591
- co.fill();
1592
- }
1593
- };
1594
-
1595
-
1596
-
1597
-
1598
- /**
1599
- * This function positions a tooltip when it is displayed
1600
- *
1601
- * @param obj object The chart object
1602
- * @param int x The X coordinate specified for the tooltip
1603
- * @param int y The Y coordinate specified for the tooltip
1604
- * @param objec tooltip The tooltips DIV element
1605
- *
1606
- this.positionTooltip = function (obj, x, y, tooltip, idx)
1607
- {
1608
- var coordX = obj.angles[idx][2];
1609
- var coordY = obj.angles[idx][3];
1610
- var mouseXY = RG.getMouseXY(window.event);
1611
- var angleStart = obj.angles[idx][0];
1612
- var angleEnd = obj.angles[idx][1];
1613
- var angleCenter = ((angleEnd - angleStart) / 2) + angleStart;
1614
- var canvasXY = RGraph.getCanvasXY(obj.canvas);
1615
- var gutterLeft = prop['chart.gutter.left'];
1616
- var gutterTop = prop['chart.gutter.top'];
1617
- var width = tooltip.offsetWidth;
1618
- var height = tooltip.offsetHeight;
1619
- var x = canvasXY[0] + this.angles[idx][2] + (Math.cos(angleCenter) * (prop['chart.variant'] == 'donut' && typeof(prop['chart.variant.donut.width']) == 'number' ? ((this.radius - prop['chart.variant.donut.width']) + (prop['chart.variant.donut.width'] / 2)) : (this.radius * 0.5)));
1620
- var y = canvasXY[1] + this.angles[idx][3] + (Math.sin(angleCenter) * (prop['chart.variant'] == 'donut' && typeof(prop['chart.variant.donut.width']) == 'number' ? ((this.radius - prop['chart.variant.donut.width']) + (prop['chart.variant.donut.width'] / 2)) : (this.radius * 0.5)));
1621
-
1622
-
1623
- // By default any overflow is hidden
1624
- tooltip.style.overflow = '';
1625
-
1626
- // Set the top position
1627
- tooltip.style.left = 0;
1628
- tooltip.style.top = window.event.pageY - height - 5 + 'px';
1629
-
1630
-
1631
- // Reposition the tooltip if at the edges:
1632
-
1633
- // LEFT edge
1634
- if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
1635
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
1636
-
1637
- // RIGHT edge
1638
- } else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
1639
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
1640
-
1641
- // Default positioning - CENTERED
1642
- } else {
1643
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
1644
- }
1645
- };*/
1646
-
1647
-
1648
-
1649
-
1650
- /**
1651
- * This draws Ingraph labels
1652
- */
1653
- this.drawInGraphLabels =
1654
- this.DrawInGraphLabels = function ()
1655
- {
1656
- var context = co;
1657
- var cx = this.centerx;
1658
- var cy = this.centery;
1659
- var radius = prop['chart.labels.ingraph.radius'];
1660
-
1661
- //
1662
- // Is the radius less than 2? If so then it's a factor and not n exact point
1663
- //
1664
- if (radius <= 2 && radius > 0) {
1665
- radiusFactor = radius;
1666
- } else {
1667
- radiusFactor = 0.5;
1668
- }
1669
-
1670
- if (prop['chart.variant'] == 'donut') {
1671
- var r = this.radius * (0.5 + (radiusFactor * 0.5));
1672
-
1673
- if (typeof(prop['chart.variant.donut.width']) == 'number') {
1674
- var r = (this.radius - prop['chart.variant.donut.width']) + (prop['chart.variant.donut.width'] / 2);
1675
- }
1676
- } else {
1677
- var r = this.radius * radiusFactor;
1678
- }
1679
-
1680
- if (radius > 2) {
1681
- r = radius;
1682
- }
1683
-
1684
- for (var i=0,len=this.angles.length; i<len; ++i) {
1685
-
1686
- // This handles any explosion that the segment may have
1687
- if (typeof(prop['chart.exploded']) == 'object' && typeof(prop['chart.exploded'][i]) == 'number') {
1688
- var explosion = prop['chart.exploded'][i];
1689
- } else if (typeof(prop['chart.exploded']) == 'number') {
1690
- var explosion = parseInt(prop['chart.exploded']);
1691
- } else {
1692
- var explosion = 0;
1693
- }
1694
-
1695
- var angleStart = this.angles[i][0];
1696
- var angleEnd = this.angles[i][1];
1697
- var angleCenter = ((angleEnd - angleStart) / 2) + angleStart;
1698
- var coords = RG.getRadiusEndPoint(
1699
- this.centerx,
1700
- this.centery,
1701
- angleCenter,
1702
- r + (explosion ? explosion : 0)
1703
- );
1704
-
1705
- var x = coords[0];
1706
- var y = coords[1];
1707
-
1708
- var text = prop['chart.labels.ingraph.specific'] && typeof(prop['chart.labels.ingraph.specific'][i]) == 'string' ? prop['chart.labels.ingraph.specific'][i] : RG.number_format(this, this.data[i], prop['chart.labels.ingraph.units.pre'] , prop['chart.labels.ingraph.units.post']);
1709
-
1710
- if (text) {
1711
- co.beginPath();
1712
-
1713
- var font = typeof prop['chart.labels.ingraph.font'] === 'string' ? prop['chart.labels.ingraph.font'] : prop['chart.text.font'];
1714
- var size = typeof prop['chart.labels.ingraph.size'] === 'number' ? prop['chart.labels.ingraph.size'] : prop['chart.text.size'] + 2;
1715
-
1716
- //
1717
- // Set the colors
1718
- //
1719
- co.fillStyle = prop['chart.labels.ingraph.color'] ? prop['chart.labels.ingraph.color'] : 'black';
1720
-
1721
- RG.Text2(this, {
1722
- 'font':font,
1723
- 'size':size,
1724
- 'x':x,
1725
- 'y':y,
1726
- 'text':text,
1727
- 'valign':'center',
1728
- 'halign':'center',
1729
- 'bounding': prop['chart.labels.ingraph.bounding'],
1730
- 'bounding.fill': prop['chart.labels.ingraph.bounding.fill'],
1731
- 'tag':'labels.ingraph'
1732
- });
1733
- co.stroke();
1734
- }
1735
- }
1736
- };
1737
-
1738
-
1739
-
1740
-
1741
- //
1742
- // Draws the center label if required
1743
- //
1744
- this.drawCenterLabel = function (label)
1745
- {
1746
- var font = prop['chart.labels.center.font'],
1747
- size = prop['chart.labels.center.size'],
1748
- color = prop['chart.labels.center.color'],
1749
- unitsPre = prop['chart.labels.center.units.pre'],
1750
- unitsPost = prop['chart.labels.center.units.post'],
1751
- bold = prop['chart.labels.center.bold'],
1752
- italic = prop['chart.labels.center.italic'];
1753
-
1754
-
1755
- RG.text2(this, {
1756
- color: color,
1757
- bold: bold,
1758
- italic: italic,
1759
- font: font,
1760
- size: size,
1761
- x: this.centerx,
1762
- y: this.centery,
1763
- halign: 'center',
1764
- valign: 'center',
1765
- text: RG.numberFormat(this, label,unitsPre, unitsPost)
1766
- });
1767
- }
1768
-
1769
-
1770
-
1771
-
1772
- /**
1773
- * This returns the angle for a value based around the maximum number
1774
- *
1775
- * @param number value The value to get the angle for
1776
- */
1777
- this.getAngle = function (value)
1778
- {
1779
- if (value > this.total) {
1780
- return null;
1781
- }
1782
-
1783
- var angle = (value / this.total) * RG.TWOPI;
1784
-
1785
- // Handle the origin (it can br -HALFPI or 0)
1786
- angle += prop['chart.origin'];
1787
-
1788
- return angle;
1789
- };
1790
-
1791
-
1792
-
1793
-
1794
- /**
1795
- * This allows for easy specification of gradients
1796
- */
1797
- this.parseColors = function ()
1798
- {
1799
- // Save the original colors so that they can be restored when the canvas is reset
1800
- if (this.original_colors.length === 0) {
1801
- this.original_colors['chart.colors'] = RG.arrayClone(prop['chart.colors']);
1802
- this.original_colors['chart.key.colors'] = RG.arrayClone(prop['chart.key.colors']);
1803
- this.original_colors['chart.strokestyle'] = RG.arrayClone(prop['chart.strokestyle']);
1804
- this.original_colors['chart.highlight.stroke'] = RG.arrayClone(prop['chart.highlight.stroke']);
1805
- this.original_colors['chart.highlight.style.twod.fill'] = RG.arrayClone(prop['chart.highlight.style.twod.fill']);
1806
- this.original_colors['chart.highlight.style.twod.stroke'] = RG.arrayClone(prop['chart.highlight.style.twod.stroke']);
1807
- this.original_colors['chart.ingraph.bounding.fill'] = RG.arrayClone(prop['chart.ingraph.bounding.fill']);
1808
- this.original_colors['chart.ingraph.color'] = RG.arrayClone(prop['chart.ingraph.color']);
1809
- }
1810
-
1811
- for (var i=0; i<prop['chart.colors'].length; ++i) {
1812
- prop['chart.colors'][i] = this.parseSingleColorForGradient(prop['chart.colors'][i]);
1813
- }
1814
-
1815
- var keyColors = prop['chart.key.colors'];
1816
- if (keyColors) {
1817
- for (var i=0; i<keyColors.length; ++i) {
1818
- keyColors[i] = this.parseSingleColorForGradient(keyColors[i]);
1819
- }
1820
- }
1821
-
1822
- prop['chart.strokestyle'] = this.parseSingleColorForGradient(prop['chart.strokestyle']);
1823
- prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
1824
- prop['chart.highlight.style.twod.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.style.twod.fill']);
1825
- prop['chart.highlight.style.twod.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.style.twod.stroke']);
1826
- prop['chart.labels.ingraph.bounding.fill'] = this.parseSingleColorForGradient(prop['chart.labels.ingraph.bounding.fill']);
1827
- prop['chart.labels.ingraph.color'] = this.parseSingleColorForGradient(prop['chart.labels.ingraph.color']);
1828
- };
1829
-
1830
-
1831
-
1832
-
1833
- /**
1834
- * Use this function to reset the object to the post-constructor state. Eg reset colors if
1835
- * need be etc
1836
- */
1837
- this.reset = function ()
1838
- {
1839
- };
1840
-
1841
-
1842
-
1843
-
1844
- /**
1845
- * This parses a single color value
1846
- */
1847
- this.parseSingleColorForGradient = function (color)
1848
- {
1849
-
1850
- if (!color || typeof(color) != 'string') {
1851
- return color;
1852
- }
1853
-
1854
- if (color.match(/^gradient\((.*)\)$/i)) {
1855
-
1856
- var parts = RegExp.$1.split(':');
1857
-
1858
- // If the chart is a donut - the first width should half the total radius
1859
- if (prop['chart.variant'] == 'donut') {
1860
- var radius_start = typeof(prop['chart.variant.donut.width']) == 'number' ? this.radius - prop['chart.variant.donut.width'] : this.radius / 2;
1861
- } else {
1862
- var radius_start = 0;
1863
- }
1864
-
1865
- // Create the gradient
1866
- var grad = co.createRadialGradient(this.centerx, this.centery, radius_start, this.centerx, this.centery, Math.min(ca.width - prop['chart.gutter.left'] - prop['chart.gutter.right'], ca.height - prop['chart.gutter.top'] - prop['chart.gutter.bottom']) / 2);
1867
-
1868
-
1869
- var diff = 1 / (parts.length - 1);
1870
-
1871
- grad.addColorStop(0, RG.trim(parts[0]));
1872
-
1873
- for (var j=1; j<parts.length; ++j) {
1874
- grad.addColorStop(j * diff, RG.trim(parts[j]));
1875
- }
1876
- }
1877
-
1878
- return grad ? grad : color;
1879
- };
1880
-
1881
-
1882
-
1883
-
1884
- /**
1885
- * This function handles highlighting an entire data-series for the interactive
1886
- * key
1887
- *
1888
- * @param int index The index of the data series to be highlighted
1889
- */
1890
- this.interactiveKeyHighlight = function (index)
1891
- {
1892
- if (this.angles && this.angles[index]) {
1893
-
1894
- var segment = this.angles[index];
1895
- var x = segment[2];
1896
- var y = segment[3];
1897
- var start = segment[0];
1898
- var end = segment[1];
1899
-
1900
- co.strokeStyle = prop['chart.key.interactive.highlight.chart.stroke'];
1901
- co.fillStyle = prop['chart.key.interactive.highlight.chart.fill'];
1902
- co.lineWidth = 2;
1903
- co.lineJoin = 'bevel';
1904
-
1905
- co.beginPath();
1906
- co.moveTo(x, y);
1907
- co.arc(x, y, this.radius, start, end, false);
1908
- co.closePath();
1909
- co.fill();
1910
- co.stroke();
1911
- }
1912
- };
1913
-
1914
-
1915
-
1916
-
1917
- /**
1918
- * Using a function to add events makes it easier to facilitate method chaining
1919
- *
1920
- * @param string type The type of even to add
1921
- * @param function func
1922
- */
1923
- this.on = function (type, func)
1924
- {
1925
- if (type.substr(0,2) !== 'on') {
1926
- type = 'on' + type;
1927
- }
1928
-
1929
- if (typeof this[type] !== 'function') {
1930
- this[type] = func;
1931
- } else {
1932
- RG.addCustomEventListener(this, type, func);
1933
- }
1934
-
1935
- return this;
1936
- };
1937
-
1938
-
1939
-
1940
-
1941
- /**
1942
- * This function runs once only
1943
- * (put at the end of the file (before any effects))
1944
- */
1945
- this.firstDrawFunc = function ()
1946
- {
1947
- };
1948
-
1949
-
1950
-
1951
-
1952
- //
1953
- // Draw a 3D Pie/Donut chart
1954
- //
1955
- this.draw3d = function ()
1956
- {
1957
- var scaleX = 1.5,
1958
- depth = prop['chart.variant.threed.depth'],
1959
- prop_shadow = prop['chart.shadow'],
1960
- prop_labels = prop['chart.labels'],
1961
- prop_labelsSticks = prop['chart.labels.sticks']
1962
-
1963
- this.set({
1964
- labels: [],
1965
- labelsSticks: false,
1966
- strokestyle: 'rgba(0,0,0,0)'
1967
- });
1968
-
1969
- //
1970
- // Change the variant so that the draw function doesn't keep
1971
- // coming in here
1972
- //
1973
- this.set({
1974
- variant: this.get('variant').replace(/3d/, '')
1975
- });
1976
-
1977
- this.context.setTransform(scaleX, 0, 0, 1, (ca.width * (scaleX) - ca.width) * -0.5, 0);
1978
-
1979
- for (var i=depth; i>0; i-=1) {
1980
-
1981
- this.set({
1982
- centeryAdjust: i
1983
- });
1984
-
1985
- if (i === parseInt(depth / 2) ) {
1986
- this.set({
1987
- labels: prop_labels,
1988
- labelsSticks: prop_labelsSticks
1989
- });
1990
- }
1991
-
1992
- if (i === 0) {
1993
- this.set({
1994
- shadow: prop_shadow
1995
- });
1996
- }
1997
-
1998
- this.draw();
1999
-
2000
- // Turn off the shadow after the bottom pie/donut has
2001
- // been drawn
2002
- this.set('shadow', false);
2003
-
2004
- //
2005
- // If on the middle pie/donut turn the labels and sticks off
2006
- //
2007
- if (i <= parseInt(depth / 2) ) {
2008
- this.set({
2009
- labels: [],
2010
- labelsSticks: false
2011
- });
2012
- }
2013
-
2014
- //
2015
- // Make what we're drawng darker by going over
2016
- // it in a semi-transparent dark color
2017
- //
2018
- if (i > 1) {
2019
- if (prop['chart.variant'].indexOf('donut') !== -1) {
2020
-
2021
- for (var j=0; j<this.angles.length; ++j) {
2022
- pa2(co,[
2023
- 'b',
2024
- 'a', this.angles[j][2], this.angles[j][3], this.radius + 1, this.angles[j][0], this.angles[j][1] * prop['chart.effect.roundrobin.multiplier'], false,
2025
- 'a', this.angles[j][2], this.angles[j][3], this.radius / 2, this.angles[j][1] * prop['chart.effect.roundrobin.multiplier'], this.angles[j][0], true,
2026
- 'f', 'rgba(0,0,0,0.15)'
2027
- ]);
2028
- }
2029
-
2030
- // Draw the pie chart darkened segments
2031
- } else {
2032
-
2033
- for (var j=0; j<this.angles.length; ++j) {
2034
-
2035
- pa2(co,[
2036
- 'b',
2037
- 'm', this.angles[j][2], this.angles[j][3],
2038
- 'a', this.angles[j][2],
2039
- this.angles[j][3],
2040
- this.radius + 1,
2041
- this.angles[j][0],
2042
- this.angles[j][1] * prop['chart.effect.roundrobin.multiplier'],
2043
- false,
2044
- 'c',
2045
- 'f', 'rgba(0,0,0,0.15)'
2046
- ]);
2047
- }
2048
- }
2049
- }
2050
- }
2051
-
2052
- //
2053
- // Reset the variant by adding the 3d back on
2054
- //
2055
- this.set({
2056
- variant: this.get('variant') + '3d',
2057
- shadow: prop_shadow,
2058
- labels: prop_labels,
2059
- labelsSticks: prop_labelsSticks
2060
- });
2061
-
2062
- // Necessary to allow method chaining
2063
- return this;
2064
- };
2065
-
2066
-
2067
-
2068
-
2069
- /**
2070
- * Pie chart explode
2071
- *
2072
- * Explodes the Pie chart - gradually incrementing the size of the chart.explode property
2073
- *
2074
- * @param object Options for the effect
2075
- * @param function An optional callback function to call when the animation completes
2076
- */
2077
- this.explode = function ()
2078
- {
2079
- var obj = this;
2080
- var opt = arguments[0] ? arguments[0] : {};
2081
- var callback = arguments[1] ? arguments[1] : function () {};
2082
- var frames = opt.frames ? opt.frames : 30;
2083
- var frame = 0;
2084
- var maxExplode = Number(typeof opt.radius === 'number' ? opt.radius : ma.max(ca.width, ca.height));
2085
- var currentExplode = Number(obj.get('exploded')) || 0;
2086
- var step = (maxExplode - currentExplode) / frames;
2087
-
2088
- // chart.exploded
2089
- var iterator = function ()
2090
- {
2091
- obj.set('exploded', currentExplode + (step * frame) );
2092
-
2093
- RGraph.clear(obj.canvas);
2094
- RGraph.redrawCanvas(obj.canvas);
2095
-
2096
- if (frame++ < frames) {
2097
- RGraph.Effects.updateCanvas(iterator);
2098
- } else {
2099
- callback(obj);
2100
- }
2101
- }
2102
-
2103
- iterator();
2104
-
2105
- return this;
2106
- };
2107
-
2108
-
2109
-
2110
-
2111
- /**
2112
- * Pie chart grow
2113
- *
2114
- * Gradually increases the pie chart radius
2115
- *
2116
- * @param object OPTIONAL An object of options
2117
- * @param function OPTIONAL A callback function
2118
- */
2119
- this.grow = function ()
2120
- {
2121
- var obj = this;
2122
- var canvas = obj.canvas;
2123
- var opt = arguments[0] ? arguments[0] : {};
2124
- var frames = opt.frames || 30;
2125
- var frame = 0;
2126
- var callback = arguments[1] ? arguments[1] : function () {};
2127
- var radius = obj.getRadius();
2128
-
2129
-
2130
- prop['chart.radius'] = 0;
2131
-
2132
- var iterator = function ()
2133
- {
2134
- obj.set('chart.radius', (frame / frames) * radius);
2135
-
2136
- RG.redrawCanvas(ca);
2137
-
2138
- if (frame++ < frames) {
2139
- RG.Effects.updateCanvas(iterator);
2140
-
2141
- } else {
2142
-
2143
- RG.redrawCanvas(obj.canvas);
2144
-
2145
-
2146
- callback(obj);
2147
- }
2148
- };
2149
-
2150
- iterator();
2151
-
2152
- return this;
2153
- };
2154
-
2155
-
2156
-
2157
-
2158
-
2159
- /**
2160
- * RoundRobin
2161
- *
2162
- * This effect does two things:
2163
- * 1. Gradually increases the size of each segment
2164
- * 2. Gradually increases the size of the radius from 0
2165
- *
2166
- * @param object OPTIONAL Options for the effect
2167
- * @param function OPTIONAL A callback function
2168
- */
2169
- this.roundrobin =
2170
- this.roundRobin = function ()
2171
- {
2172
- var obj = this,
2173
- opt = arguments[0] || {},
2174
- callback = arguments[1] || function () {},
2175
- frame = 0,
2176
- frames = opt.frames || 30,
2177
- radius = obj.getRadius(),
2178
- labels = obj.get('labels')
2179
-
2180
- obj.Set('chart.events', false);
2181
- obj.Set('chart.labels', []);
2182
-
2183
- var iterator = function ()
2184
- {
2185
- obj.set(
2186
- 'effect.roundrobin.multiplier',
2187
- RG.Effects.getEasingMultiplier(frames, frame)
2188
- );
2189
-
2190
- RGraph.redrawCanvas(ca);
2191
-
2192
- if (frame++ < frames) {
2193
- RGraph.Effects.updateCanvas(iterator);
2194
-
2195
- } else {
2196
-
2197
- obj.set({
2198
- events: true,
2199
- labels: labels
2200
- });
2201
-
2202
- RG.redrawCanvas(obj.canvas);
2203
- callback(obj);
2204
- }
2205
- };
2206
-
2207
- iterator();
2208
-
2209
- return this;
2210
- };
2211
-
2212
-
2213
-
2214
-
2215
- RG.att(ca);
2216
-
2217
-
2218
-
2219
-
2220
-
2221
-
2222
-
2223
-
2224
-
2225
- /**
2226
- * Pie chart implode
2227
- *
2228
- * Implodes the Pie chart - gradually decreasing the size of the chart.explode property. It starts at the largest of
2229
- * the canvas width./height
2230
- *
2231
- * @param object Optional options for the effect. You can pass in frames here - such as:
2232
- * myPie.implode({frames: 60}; function () {alert('Done!');})
2233
- * @param function A callback function which is called when the effect is finished
2234
- */
2235
- this.implode = function ()
2236
- {
2237
- var obj = this,
2238
- opt = arguments[0] || {},
2239
- callback = arguments[1] || function (){},
2240
- frames = opt.frames || 30,
2241
- frame = 0,
2242
- explodedMax = ma.max(ca.width, ca.height),
2243
- exploded = explodedMax;
2244
-
2245
-
2246
-
2247
- function iterator ()
2248
- {
2249
- exploded = explodedMax - ((frame / frames) * explodedMax);
2250
-
2251
- // Set the new value
2252
- obj.Set('exploded', exploded);
2253
-
2254
- RG.clear(ca);
2255
- RG.redrawCanvas(ca);
2256
-
2257
- if (frame++ < frames) {
2258
- RG.Effects.updateCanvas(iterator);
2259
- } else {
2260
- RG.clear(obj.canvas);
2261
- RG.redrawCanvas(obj.canvas);
2262
- callback(obj);
2263
- }
2264
- }
2265
-
2266
- iterator();
2267
-
2268
- return this;
2269
- };
2270
-
2271
-
2272
-
2273
-
2274
- /**
2275
- * Now need to register all chart types. MUST be after the setters/getters are defined
2276
- */
2277
- RG.register(this);
2278
-
2279
-
2280
-
2281
-
2282
- /**
2283
- * This is the 'end' of the constructor so if the first argument
2284
- * contains configuration data - handle that.
2285
- */
2286
- if (parseConfObjectForOptions) {
2287
- RG.parseObjectStyleConfig(this, conf.options);
2288
- }
2289
- };
2
+ RGraph=window.RGraph||{isRGraph:true};RGraph.Pie=function(conf)
3
+ {if(typeof conf==='object'&&typeof conf.data==='object'&&typeof conf.id==='string'){var id=conf.id,canvas=document.getElementById(id),data=conf.data,parseConfObjectForOptions=true;}else{var id=conf,canvas=document.getElementById(id),data=arguments[1];}
4
+ this.id=id;this.canvas=canvas;this.context=this.canvas.getContext?this.canvas.getContext("2d",{alpha:(typeof id==='object'&&id.alpha===false)?false:true}):null;this.canvas.__object__=this;this.total=0;this.subTotal=0;this.angles=[];this.data=data;this.properties=[];this.type='pie';this.isRGraph=true;this.coords=[];this.coords.key=[];this.coordsSticks=[];this.coordsText=[];this.uid=RGraph.CreateUID();this.canvas.uid=this.canvas.uid?this.canvas.uid:RGraph.CreateUID();this.colorsParsed=false;this.original_colors=[];this.firstDraw=true;this.exploding=null;for(var i=0;i<this.data.length;++i){if(typeof this.data[i]==='string'){this.data[i]=parseFloat(this.data[i]);}}
5
+ this.properties={'chart.centerx.adjust':0,'chart.centery.adjust':0,'chart.colors':['red','#ccc','#cfc','blue','pink','yellow','black','orange','cyan','purple','#78CAEA','#E284E9','white','blue','#9E7BF6'],'chart.strokestyle':'white','chart.linewidth':3,'chart.labels':[],'chart.labels.bold':false,'chart.labels.sticks':false,'chart.labels.sticks.length':7,'chart.labels.sticks.colors':null,'chart.labels.sticks.usecolors':false,'chart.labels.sticks.linewidth':1,'chart.labels.sticks.hlength':5,'chart.labels.sticks.list':false,'chart.labels.ingraph':null,'chart.labels.ingraph.color':null,'chart.labels.ingraph.font':null,'chart.labels.ingraph.size':null,'chart.labels.ingraph.bounding':true,'chart.labels.ingraph.bounding.fill':'white','chart.labels.ingraph.specific':null,'chart.labels.ingraph.units.pre':'','chart.labels.ingraph.units.post':'','chart.labels.ingraph.radius':null,'chart.labels.center':null,'chart.labels.center.size':26,'chart.labels.center.font':'Segoe UI, Arial, Verdana, sans-serif','chart.labels.center.color':'black','chart.labels.center.italic':false,'chart.labels.center.bold':false,'chart.labels.center.units.pre':'','chart.labels.center.units.post':'','chart.gutter.left':25,'chart.gutter.right':25,'chart.gutter.top':25,'chart.gutter.bottom':25,'chart.title':'','chart.title.background':null,'chart.title.hpos':null,'chart.title.vpos':0.5,'chart.title.bold':true,'chart.title.font':null,'chart.title.x':null,'chart.title.y':null,'chart.title.halign':null,'chart.title.valign':null,'chart.shadow':true,'chart.shadow.color':'#aaa','chart.shadow.offsetx':0,'chart.shadow.offsety':0,'chart.shadow.blur':15,'chart.text.size':12,'chart.text.color':'black','chart.text.font':'Segoe UI, Arial, Verdana, sans-serif','chart.text.accessible':true,'chart.text.accessible.overflow':'visible','chart.text.accessible.pointerevents':true,'chart.contextmenu':null,'chart.tooltips':null,'chart.tooltips.event':'onclick','chart.tooltips.effect':'fade','chart.tooltips.css.class':'RGraph_tooltip','chart.tooltips.highlight':true,'chart.highlight.style':'2d','chart.highlight.style.twod.fill':'rgba(255,255,255,0.7)','chart.highlight.style.twod.stroke':'rgba(255,255,255,0.7)','chart.highlight.style.outline.width':null,'chart.centerx':null,'chart.centery':null,'chart.radius':null,'chart.border':false,'chart.border.color':'rgba(255,255,255,0.5)','chart.key':null,'chart.key.background':'white','chart.key.position':'graph','chart.key.halign':'right','chart.key.shadow':false,'chart.key.shadow.color':'#666','chart.key.shadow.blur':3,'chart.key.shadow.offsetx':2,'chart.key.shadow.offsety':2,'chart.key.position.gutter.boxed':false,'chart.key.position.x':null,'chart.key.position.y':null,'chart.key.color.shape':'square','chart.key.rounded':true,'chart.key.linewidth':1,'chart.key.colors':null,'chart.key.interactive':false,'chart.key.interactive.highlight.chart.stroke':'black','chart.key.interactive.highlight.chart.fill':'rgba(255,255,255,0.7)','chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)','chart.key.text.color':'black','chart.annotatable':false,'chart.annotate.color':'black','chart.zoom.factor':1.5,'chart.zoom.fade.in':true,'chart.zoom.fade.out':true,'chart.zoom.hdir':'right','chart.zoom.vdir':'down','chart.zoom.frames':25,'chart.zoom.delay':16.666,'chart.zoom.shadow':true,'chart.zoom.background':true,'chart.zoom.action':'zoom','chart.resizable':false,'chart.resize.handle.adjust':[0,0],'chart.resize.handle.background':null,'chart.variant':'pie','chart.variant.donut.width':null,'chart.variant.threed.depth':20,'chart.exploded':[],'chart.effect.roundrobin.multiplier':1,'chart.events.click':null,'chart.events.mousemove':null,'chart.centerpin':null,'chart.centerpin.fill':'gray','chart.centerpin.stroke':'white','chart.origin':0-(Math.PI/2),'chart.events':true,'chart.labels.colors':[],'chart.clearto':'rgba(0,0,0,0)'}
6
+ for(var i=0,len=data.length;i<len;i++){this.total+=data[i];this['$'+i]={};}
7
+ if(!this.canvas.__rgraph_aa_translated__){this.context.translate(0.5,0.5);this.canvas.__rgraph_aa_translated__=true;}
8
+ var RG=RGraph,ca=this.canvas,co=ca.getContext('2d'),prop=this.properties,pa2=RG.path2,win=window,doc=document,ma=Math
9
+ if(RG.Effects&&typeof RG.Effects.decorate==='function'){RG.Effects.decorate(this);}
10
+ this.set=this.Set=function(name)
11
+ {var value=typeof arguments[1]==='undefined'?null:arguments[1];if(arguments.length===1&&typeof name==='object'){RG.parseObjectStyleConfig(this,name);return this;}
12
+ if(name.substr(0,6)!='chart.'){name='chart.'+name;}
13
+ while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
14
+ if(name=='chart.highlight.style.twod.color'){name='chart.highlight.style.twod.fill';}
15
+ if(name=='chart.labels.spaced'){name='chart.labels.sticks.list';}
16
+ prop[name]=value;return this;};this.get=this.Get=function(name)
17
+ {if(name.substr(0,6)!='chart.'){name='chart.'+name;}
18
+ while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
19
+ if(name=='chart.highlight.style.twod.color'){name='chart.highlight.style.twod.fill';}
20
+ return prop[name];};this.draw=this.Draw=function()
21
+ {RG.FireCustomEvent(this,'onbeforedraw');this.gutterLeft=prop['chart.gutter.left'];this.gutterRight=prop['chart.gutter.right'];this.gutterTop=prop['chart.gutter.top'];this.gutterBottom=prop['chart.gutter.bottom'];this.radius=this.getRadius();this.centerx=(this.graph.width/2)+this.gutterLeft+prop['chart.centerx.adjust'];this.centery=(this.graph.height/2)+this.gutterTop+prop['chart.centery.adjust'];this.subTotal=this.properties['chart.origin'];this.angles=[];this.coordsText=[];if(typeof prop['chart.radius']==='number')this.radius=prop['chart.radius'];if(typeof prop['chart.centerx']==='number')this.centerx=prop['chart.centerx'];if(typeof prop['chart.centery']==='number')this.centery=prop['chart.centery'];if(this.radius<=0){return;}
22
+ if(!this.colorsParsed){this.parseColors();this.colorsParsed=true;}
23
+ if(prop['chart.labels.colors'].length<prop['chart.labels'].length){while(prop['chart.labels.colors'].length<prop['chart.labels'].length){prop['chart.labels.colors'].push(prop['chart.labels.colors'][prop['chart.labels.colors'].length-1]);}}else{if(typeof prop['chart.labels.colors']==='undefined'){prop['chart.labels.colors']=[];}
24
+ while(prop['chart.labels.colors'].length<prop['chart.labels'].length){prop['chart.labels.colors'].push(prop['chart.text.color']);}}
25
+ if(prop['chart.variant'].indexOf('3d')>0){return this.draw3d();}
26
+ RG.DrawTitle(this,prop['chart.title'],(ca.height/2)-this.radius-5,this.centerx,prop['chart.title.size']?prop['chart.title.size']:prop['chart.text.size']+2);this.total=RG.array_sum(this.data);var tot=this.total;var data=this.data;for(var i=0,len=this.data.length;i<len;i++){var angle=((data[i]/tot)*RG.TWOPI);this.DrawSegment(angle,prop['chart.colors'][i],i==(len-1),i);}
27
+ RG.NoShadow(this);if(prop['chart.linewidth']>0){this.DrawBorders();}
28
+ var len=this.angles.length;var r=this.radius;for(var action=0;action<2;action+=1){for(var i=0;i<len;i++){co.beginPath();var segment=this.angles[i];if(action===1){co.strokeStyle=typeof(prop['chart.strokestyle'])=='object'?prop['chart.strokestyle'][i]:prop['chart.strokestyle'];}
29
+ prop['chart.colors'][i]?co.fillStyle=prop['chart.colors'][i]:null;co.lineJoin='round';co.arc(segment[2],segment[3],r,(segment[0]),(segment[1]),false);if(prop['chart.variant']=='donut'){co.arc(segment[2],segment[3],typeof(prop['chart.variant.donut.width'])=='number'?r-prop['chart.variant.donut.width']:r/2,(segment[1]),(segment[0]),true);}else{co.lineTo(segment[2],segment[3]);}
30
+ co.closePath();action===0?co.fill():co.stroke();}}
31
+ if(prop['chart.labels.sticks']){this.DrawSticks();var strokeStyle=prop['chart.strokestyle'];}
32
+ if(prop['chart.labels']){this.DrawLabels();}
33
+ if(prop['chart.centerpin']){this.DrawCenterpin();}
34
+ if(prop['chart.labels.ingraph']){this.DrawInGraphLabels();}
35
+ if(!RG.isNull(prop['chart.labels.center'])){this.drawCenterLabel(prop['chart.labels.center']);}
36
+ if(prop['chart.contextmenu']){RG.ShowContext(this);}
37
+ if(prop['chart.border']){co.beginPath();co.lineWidth=5;co.strokeStyle=prop['chart.border.color'];co.arc(this.centerx,this.centery,this.radius-2,0,RG.TWOPI,0);co.stroke();}
38
+ if(prop['chart.key']&&prop['chart.key'].length){RG.DrawKey(this,prop['chart.key'],prop['chart.colors']);}
39
+ RG.NoShadow(this);if(prop['chart.resizable']){RG.AllowResizing(this);}
40
+ if(prop['chart.events']==true){RG.InstallEventListeners(this);}
41
+ if(this.firstDraw){this.firstDraw=false;RG.fireCustomEvent(this,'onfirstdraw');this.firstDrawFunc();}
42
+ RG.FireCustomEvent(this,'ondraw');return this;};this.exec=function(func)
43
+ {func(this);return this;};this.drawSegment=this.DrawSegment=function(radians,color,last,index)
44
+ {if(RGraph.ISOLD&&radians==RG.TWOPI){radians-=0.0001;}else if(RGraph.ISOLD&&radians==0){radians=0.001;}
45
+ var subTotal=this.subTotal;radians=radians*prop['chart.effect.roundrobin.multiplier'];co.beginPath();color?co.fillStyle=color:null;co.strokeStyle=prop['chart.strokestyle'];co.lineWidth=0;if(prop['chart.shadow']){RG.setShadow(this,prop['chart.shadow.color'],prop['chart.shadow.offsetx'],prop['chart.shadow.offsety'],prop['chart.shadow.blur']);}
46
+ if((typeof(prop['chart.exploded'])=='object'&&prop['chart.exploded'][index]>0)||typeof(prop['chart.exploded'])=='number'){var explosion=typeof(prop['chart.exploded'])=='number'?prop['chart.exploded']:prop['chart.exploded'][index];var x=0;var y=0;var h=explosion;var t=subTotal+(radians/2);var x=(Math.cos(t)*explosion);var y=(Math.sin(t)*explosion);var r=this.radius;co.moveTo(this.centerx+x,this.centery+y);}else{var x=0;var y=0;var r=this.radius;}
47
+ var startAngle=subTotal;var endAngle=((subTotal+radians));co.arc(this.centerx+x,this.centery+y,r,startAngle,endAngle,0);if(prop['chart.variant']=='donut'){co.arc(this.centerx+x,this.centery+y,typeof(prop['chart.variant.donut.width'])=='number'?r-prop['chart.variant.donut.width']:r/2,endAngle,startAngle,true);}else{co.lineTo(this.centerx+x,this.centery+y);}
48
+ co.closePath();this.angles.push([subTotal,subTotal+radians,this.centerx+x,this.centery+y]);co.fill();this.subTotal+=radians;};this.drawLabels=this.DrawLabels=function()
49
+ {if(prop['chart.labels'].length&&prop['chart.labels.sticks.list']){return this.drawLabelsList();}
50
+ var hAlignment='left',vAlignment='center',labels=prop['chart.labels'],context=co,font=prop['chart.text.font'],bold=prop['chart.labels.bold'],text_size=prop['chart.text.size'],cx=this.centerx,cy=this.centery,r=this.radius;RG.noShadow(this);co.fillStyle='black';co.beginPath();if(labels&&labels.length){for(i=0;i<this.angles.length;++i){var segment=this.angles[i];if(typeof labels[i]!='string'&&typeof labels[i]!='number'){continue;}
51
+ co.moveTo(cx,cy);var a=segment[0]+((segment[1]-segment[0])/2),angle=((segment[1]-segment[0])/2)+segment[0];if(typeof prop['chart.exploded']==='object'&&prop['chart.exploded'][i]||typeof prop['chart.exploded']=='number'){var t=((segment[1]-segment[0])/2),seperation=typeof(prop['chart.exploded'])=='number'?prop['chart.exploded']:prop['chart.exploded'][i];var explosion_offsetx=(Math.cos(angle)*seperation),explosion_offsety=(Math.sin(angle)*seperation);}else{var explosion_offsetx=0,explosion_offsety=0;}
52
+ if(prop['chart.labels.sticks']){explosion_offsetx+=(ma.cos(angle)*(typeof prop['chart.labels.sticks.length']==='object'?prop['chart.labels.sticks.length'][i]:prop['chart.labels.sticks.length']));explosion_offsety+=(ma.sin(angle)*(typeof prop['chart.labels.sticks.length']==='object'?prop['chart.labels.sticks.length'][i]:prop['chart.labels.sticks.length']));}
53
+ var x=cx+explosion_offsetx+((r+10)*Math.cos(a))+(prop['chart.labels.sticks']?(a<RG.HALFPI||a>(RG.TWOPI+RG.HALFPI)?2:-2):0),y=cy+explosion_offsety+(((r+10)*Math.sin(a)));if(this.coordsSticks&&this.coordsSticks[i]){var x=this.coordsSticks[i][4][0]+(x<cx?-5:5),y=this.coordsSticks[i][4][1];}
54
+ vAlignment='center';hAlignment=x<cx?'right':'left';co.fillStyle=prop['chart.text.color'];if(typeof prop['chart.labels.colors']==='object'&&prop['chart.labels.colors']&&prop['chart.labels.colors'][i]){co.fillStyle=prop['chart.labels.colors'][i];}
55
+ RG.text2(this,{font:font,size:text_size,x:x,y:y,text:labels[i],valign:vAlignment,halign:hAlignment,tag:'labels',bold:bold,color:prop['chart.labels.sticks.usecolors']?prop['chart.colors'][i]:'black'});}
56
+ co.fill();}};this.drawLabelsList=function()
57
+ {var segment=this.angles[i],labels=prop['chart.labels'],labels_right=[],labels_left=[],text_font=prop['chart.text.font'],text_size=prop['chart.text.size'],text_color=prop['chart.text.color'],left=[],right=[],centerx=this.centerx,centery=this.centery,radius=this.radius,offset=50
58
+ for(var i=0;i<this.angles.length;++i){var angle=this.angles[i][0]+((this.angles[i][1]-this.angles[i][0])/2),endpoint_inner=RG.getRadiusEndPoint(centerx,centery,angle,radius+5),endpoint_outer=RG.getRadiusEndPoint(centerx,centery,angle,radius+10),explosion=[(typeof prop['chart.exploded']==='number'?prop['chart.exploded']:prop['chart.exploded'][i]),(ma.cos(angle)*(typeof prop['chart.exploded']==='number'?prop['chart.exploded']:prop['chart.exploded'][i])),(ma.sin(angle)*(typeof prop['chart.exploded']==='number'?prop['chart.exploded']:prop['chart.exploded'][i]))]
59
+ if(typeof prop['chart.labels.sticks.colors']==='object'&&prop['chart.labels.sticks.colors']&&prop['chart.labels.sticks.colors'][i]){var color=prop['chart.labels.sticks.colors'][i];}else if(prop['chart.labels.sticks.usecolors']&&prop['chart.colors'][i]){var color=prop['chart.colors'][i];}else{var color=prop['chart.text.color'];}
60
+ if(angle>(-1*RG.HALFPI)&&angle<RG.HALFPI){labels_right.push([i,angle,labels[i]?labels[i]:'',endpoint_inner,endpoint_outer,color,RG.arrayClone(explosion)]);}else{labels_left.push([i,angle,labels[i]?labels[i]:'',endpoint_inner,endpoint_outer,color,RG.arrayClone(explosion)]);}}
61
+ var vspace_right=(ca.height-prop['chart.gutter.top']-prop['chart.gutter.bottom'])/labels_right.length
62
+ for(var i=0,y=(prop['chart.gutter.top']+(vspace_right/2));i<labels_right.length;y+=vspace_right,i++){if(labels_right[i][2]){var x=this.centerx+this.radius+offset,idx=labels_right[i][0],explosionX=labels_right[i][6][0]?labels_right[i][6][1]:0,explosionY=labels_right[i][6][0]?labels_right[i][6][2]:0
63
+ var ret=RG.text2(this,{font:text_font,size:text_size,x:x+explosionX,y:y+explosionY,text:labels_right[i][2],valign:'center',halign:'left',tag:'labels',color:labels_right[i][5]});if(ret&&ret.node){ret.node.__index__=labels_right[i][0];}
64
+ pa2(co,'lc round lw % b m % % l % % l % % l % % s %',prop['chart.labels.sticks.linewidth'],labels_right[i][3][0]+explosionX,labels_right[i][3][1]+explosionY,labels_right[i][4][0]+explosionX,labels_right[i][4][1]+explosionY,this.centerx+this.radius+25+explosionX,ma.round(labels_right[i][4][1]+explosionY),ret.x-5,ret.y+(ret.height/2),labels_right[i][5]);}}
65
+ var vspace_left=(ca.height-prop['chart.gutter.top']-prop['chart.gutter.bottom'])/labels_left.length
66
+ for(var i=(labels_left.length-1),y=(prop['chart.gutter.top']+(vspace_left/2));i>=0;y+=vspace_left,i--){if(labels_left[i][2]){var x=this.centerx-this.radius-offset,idx=labels_left[i][0],explosionX=labels_left[i][6][0]?labels_left[i][6][1]:0,explosionY=labels_left[i][6][0]?labels_left[i][6][2]:0
67
+ var ret=RG.text2(this,{font:text_font,size:text_size,x:x+explosionX,y:y+explosionY,text:labels_left[i][2],valign:'center',halign:'right',tag:'labels',color:labels_left[i][5]});if(ret&&ret.node){ret.node.__index__=labels_left[i][0];}
68
+ pa2(co,'lw % b m % % l % % l % % l % % s %',prop['chart.labels.sticks.linewidth'],labels_left[i][3][0]+explosionX,labels_left[i][3][1]+explosionY,labels_left[i][4][0]+explosionX,labels_left[i][4][1]+explosionY,this.centerx-this.radius-25+explosionX,ma.round(labels_left[i][4][1]+explosionY),ret.x+5+ret.width,ret.y+(ret.height/2),labels_left[i][5]);}}};this.drawSticks=this.DrawSticks=function()
69
+ {var offset=prop['chart.linewidth']/2,exploded=prop['chart.exploded'],sticks=prop['chart.labels.sticks'],colors=prop['chart.colors'],cx=this.centerx,cy=this.centery,radius=this.radius,points=[],linewidth=prop['chart.labels.sticks.linewidth']
70
+ for(var i=0,len=this.angles.length;i<len;++i){var segment=this.angles[i];if(typeof sticks==='object'&&!sticks[i]){continue;}
71
+ var radians=segment[1]-segment[0];co.beginPath();co.strokeStyle=typeof prop['chart.labels.sticks.colors']==='string'?prop['chart.labels.sticks.colors']:(!RG.isNull(prop['chart.labels.sticks.colors'])?prop['chart.labels.sticks.colors'][i]:'gray');co.lineWidth=linewidth;if(typeof prop['chart.labels.sticks.color']==='string'){co.strokeStyle=prop['chart.labels.sticks.color'];}
72
+ if(prop['chart.labels.sticks.usecolors']){co.strokeStyle=prop['chart.colors'][i];}
73
+ var midpoint=(segment[0]+(radians/2));if(typeof exploded==='object'&&exploded[i]){var extra=exploded[i];}else if(typeof exploded==='number'){var extra=exploded;}else{var extra=0;}
74
+ var stickLength=typeof prop['chart.labels.sticks.length']==='object'?prop['chart.labels.sticks.length'][i]:prop['chart.labels.sticks.length'];points[0]=RG.getRadiusEndPoint(cx,cy,midpoint,radius+extra+offset);points[1]=RG.getRadiusEndPoint(cx,cy,midpoint,radius+stickLength+extra-5);points[2]=RG.getRadiusEndPoint(cx,cy,midpoint,radius+stickLength+extra);points[3]=RG.getRadiusEndPoint(cx,cy,midpoint,radius+stickLength+extra);points[3][0]+=(points[3][0]>cx?5:-5);points[4]=[points[2][0]+(points[2][0]>cx?5+prop['chart.labels.sticks.hlength']:-5-prop['chart.labels.sticks.hlength']),points[2][1]];co.moveTo(points[0][0],points[0][1]);co.quadraticCurveTo(points[2][0],points[2][1],points[4][0],points[4][1]);co.stroke();this.coordsSticks[i]=[points[0],points[1],points[2],points[3],points[4]];}};this.getShape=this.getSegment=function(e)
75
+ {RG.FixEventObject(e);var accuracy=arguments[1]?arguments[1]:0;var canvas=ca;var context=co;var mouseCoords=RG.getMouseXY(e);var mouseX=mouseCoords[0];var mouseY=mouseCoords[1];var r=this.radius;var angles=this.angles;var ret=[];for(var i=0,len=angles.length;i<len;++i){co.beginPath();co.strokeStyle='rgba(0,0,0,0)';co.arc(angles[i][2],angles[i][3],this.radius,angles[i][0],angles[i][1],false);if(this.type=='pie'&&prop['chart.variant']=='donut'){co.arc(angles[i][2],angles[i][3],(typeof(prop['chart.variant.donut.width'])=='number'?this.radius-prop['chart.variant.donut.width']:this.radius/2),angles[i][1],angles[i][0],true);}else{co.lineTo(angles[i][2],angles[i][3]);}
76
+ co.closePath();if(!co.isPointInPath(mouseX,mouseY)){continue;}
77
+ ret[0]=angles[i][2];ret[1]=angles[i][3];ret[2]=this.radius;ret[3]=angles[i][0]-RG.TWOPI;ret[4]=angles[i][1];ret[5]=i;if(ret[3]<0)ret[3]+=RG.TWOPI;if(ret[4]>RG.TWOPI)ret[4]-=RG.TWOPI;var tooltip=RG.parseTooltipText?RG.parseTooltipText(prop['chart.tooltips'],ret[5]):null;ret['object']=this;ret['x']=ret[0];ret['y']=ret[1];ret['radius']=ret[2];ret['angle.start']=ret[3];ret['angle.end']=ret[4];ret['index']=ret[5];ret['tooltip']=tooltip;return ret;}
78
+ return null;};this.drawBorders=this.DrawBorders=function()
79
+ {if(prop['chart.linewidth']>0){co.lineWidth=prop['chart.linewidth'];co.strokeStyle=prop['chart.strokestyle'];var r=this.radius;for(var i=0,len=this.angles.length;i<len;++i){var segment=this.angles[i];co.beginPath();co.arc(segment[2],segment[3],r,(segment[0]),(segment[0]+0.001),0);co.arc(segment[2],segment[3],prop['chart.variant']=='donut'?(typeof(prop['chart.variant.donut.width'])=='number'?this.radius-prop['chart.variant.donut.width']:r/2):r,segment[0],segment[0]+0.0001,0);co.closePath();co.stroke();}}};this.getRadius=function()
80
+ {this.graph={width:ca.width-prop['chart.gutter.left']-prop['chart.gutter.right'],height:ca.height-prop['chart.gutter.top']-prop['chart.gutter.bottom']}
81
+ if(typeof(prop['chart.radius'])=='number'){this.radius=prop['chart.radius'];}else{this.radius=Math.min(this.graph.width,this.graph.height)/2;}
82
+ return this.radius;};this.explodeSegment=this.Explode=function(index,size)
83
+ {if(typeof this.exploding==='number'&&this.exploding===index){return;}
84
+ if(!prop['chart.exploded']){prop['chart.exploded']=[];}
85
+ if(typeof(prop['chart.exploded'])=='number'){var original_explode=prop['chart.exploded'];var exploded=prop['chart.exploded'];prop['chart.exploded']=[];for(var i=0,len=this.data.length;i<len;++i){prop['chart.exploded'][i]=exploded;}}
86
+ prop['chart.exploded'][index]=typeof(original_explode)=='number'?original_explode:0;this.exploding=index;var delay=RG.ISIE&&!RG.ISIE10?25:16.666;for(var o=0;o<size;++o){setTimeout(function()
87
+ {prop['chart.exploded'][index]+=1;RG.Clear(ca);RG.RedrawCanvas(ca);},o*delay);}
88
+ var obj=this;setTimeout(function()
89
+ {obj.exploding=null;},size*delay);};this.highlight_segment=function(segment)
90
+ {co.beginPath();co.strokeStyle=prop['chart.highlight.style.twod.stroke'];co.fillStyle=prop['chart.highlight.style.twod.fill'];co.moveTo(segment[0],segment[1]);co.arc(segment[0],segment[1],segment[2],this.angles[segment[5]][0],this.angles[segment[5]][1],0);co.lineTo(segment[0],segment[1]);co.closePath();co.stroke();co.fill();};this.highlight=this.Highlight=function(shape)
91
+ {if(prop['chart.tooltips.highlight']){if(typeof prop['chart.highlight.style']==='function'){(prop['chart.highlight.style'])(shape);}else if(prop['chart.highlight.style']=='3d'){co.lineWidth=1;var extent=2;co.beginPath();RG.NoShadow(this);co.fillStyle='rgba(0,0,0,0)';co.arc(shape['x'],shape['y'],shape['radius'],shape['angle.start'],shape['angle.end'],false);if(prop['chart.variant']=='donut'){co.arc(shape['x'],shape['y'],shape['radius']/5,shape['angle.end'],shape['angle.start'],true);}else{co.lineTo(shape['x'],shape['y']);}
92
+ co.closePath();co.fill();co.beginPath();co.shadowColor='#666';co.shadowBlur=3;co.shadowOffsetX=3;co.shadowOffsetY=3;co.fillStyle=prop['chart.colors'][shape['index']];co.strokeStyle=prop['chart.strokestyle'];co.arc(shape['x']-extent,shape['y']-extent,shape['radius'],shape['angle.start'],shape['angle.end'],false);if(prop['chart.variant']=='donut'){co.arc(shape['x']-extent,shape['y']-extent,shape['radius']/2,shape['angle.end'],shape['angle.start'],true)}else{co.lineTo(shape['x']-extent,shape['y']-extent);}
93
+ co.closePath();co.stroke();co.fill();RG.NoShadow(this);if(prop['chart.border']){co.beginPath();co.strokeStyle=prop['chart.border.color'];co.lineWidth=5;co.arc(shape['x']-extent,shape['y']-extent,shape['radius']-2,shape['angle.start'],shape['angle.end'],false);co.stroke();}}else if(prop['chart.highlight.style']==='outline'){var tooltip=RG.Registry.get('chart.tooltip'),index=tooltip.__index__,coords=this.angles[index],color=this.get('colors')[index]
94
+ width=this.radius/12.5;if(typeof prop['chart.highlight.style.outline.width']==='number'){width=prop['chart.highlight.style.outline.width'];}
95
+ RGraph.path2(co,'ga 0.25 b a % % % % % false a % % % % % true c f % ga 1',coords[2],coords[3],this.radius+2+width,coords[0],coords[1],coords[2],coords[3],this.radius+2,coords[1],coords[0],color);}else{co.beginPath();co.strokeStyle=prop['chart.highlight.style.twod.stroke'];co.fillStyle=prop['chart.highlight.style.twod.fill'];if(prop['chart.variant'].indexOf('donut')>-1){co.arc(shape['x'],shape['y'],shape['radius'],shape['angle.start'],shape['angle.end'],false);co.arc(shape['x'],shape['y'],typeof(prop['chart.variant.donut.width'])=='number'?this.radius-prop['chart.variant.donut.width']:shape['radius']/2,shape['angle.end'],shape['angle.start'],true);}else{co.arc(shape['x'],shape['y'],shape['radius']+1,shape['angle.start'],shape['angle.end'],false);co.lineTo(shape['x'],shape['y']);}
96
+ co.closePath();co.stroke();co.fill();}}};this.getObjectByXY=function(e)
97
+ {if(this.getShape(e)){return this;}};this.drawCenterpin=this.DrawCenterpin=function()
98
+ {if(typeof(prop['chart.centerpin'])=='number'&&prop['chart.centerpin']>0){var cx=this.centerx;var cy=this.centery;co.beginPath();co.strokeStyle=prop['chart.centerpin.stroke']?prop['chart.centerpin.stroke']:prop['chart.strokestyle'];co.fillStyle=prop['chart.centerpin.fill']?prop['chart.centerpin.fill']:prop['chart.strokestyle'];co.moveTo(cx,cy);co.arc(cx,cy,prop['chart.centerpin'],0,RG.TWOPI,false);co.stroke();co.fill();}};this.drawInGraphLabels=this.DrawInGraphLabels=function()
99
+ {var context=co;var cx=this.centerx;var cy=this.centery;var radius=prop['chart.labels.ingraph.radius'];if(radius<=2&&radius>0){radiusFactor=radius;}else{radiusFactor=0.5;}
100
+ if(prop['chart.variant']=='donut'){var r=this.radius*(0.5+(radiusFactor*0.5));if(typeof(prop['chart.variant.donut.width'])=='number'){var r=(this.radius-prop['chart.variant.donut.width'])+(prop['chart.variant.donut.width']/2);}}else{var r=this.radius*radiusFactor;}
101
+ if(radius>2){r=radius;}
102
+ for(var i=0,len=this.angles.length;i<len;++i){if(typeof(prop['chart.exploded'])=='object'&&typeof(prop['chart.exploded'][i])=='number'){var explosion=prop['chart.exploded'][i];}else if(typeof(prop['chart.exploded'])=='number'){var explosion=parseInt(prop['chart.exploded']);}else{var explosion=0;}
103
+ var angleStart=this.angles[i][0];var angleEnd=this.angles[i][1];var angleCenter=((angleEnd-angleStart)/2)+angleStart;var coords=RG.getRadiusEndPoint(this.centerx,this.centery,angleCenter,r+(explosion?explosion:0));var x=coords[0];var y=coords[1];var text=prop['chart.labels.ingraph.specific']&&typeof(prop['chart.labels.ingraph.specific'][i])=='string'?prop['chart.labels.ingraph.specific'][i]:RG.number_format(this,this.data[i],prop['chart.labels.ingraph.units.pre'],prop['chart.labels.ingraph.units.post']);if(text){co.beginPath();var font=typeof prop['chart.labels.ingraph.font']==='string'?prop['chart.labels.ingraph.font']:prop['chart.text.font'];var size=typeof prop['chart.labels.ingraph.size']==='number'?prop['chart.labels.ingraph.size']:prop['chart.text.size']+2;co.fillStyle=prop['chart.labels.ingraph.color']?prop['chart.labels.ingraph.color']:'black';RG.Text2(this,{'font':font,'size':size,'x':x,'y':y,'text':text,'valign':'center','halign':'center','bounding':prop['chart.labels.ingraph.bounding'],'bounding.fill':prop['chart.labels.ingraph.bounding.fill'],'tag':'labels.ingraph'});co.stroke();}}};this.drawCenterLabel=function(label)
104
+ {var font=prop['chart.labels.center.font'],size=prop['chart.labels.center.size'],color=prop['chart.labels.center.color'],unitsPre=prop['chart.labels.center.units.pre'],unitsPost=prop['chart.labels.center.units.post'],bold=prop['chart.labels.center.bold'],italic=prop['chart.labels.center.italic'];RG.text2(this,{color:color,bold:bold,italic:italic,font:font,size:size,x:this.centerx,y:this.centery,halign:'center',valign:'center',text:RG.numberFormat(this,label,unitsPre,unitsPost)});}
105
+ this.getAngle=function(value)
106
+ {if(value>this.total){return null;}
107
+ var angle=(value/this.total)*RG.TWOPI;angle+=prop['chart.origin'];return angle;};this.parseColors=function()
108
+ {if(this.original_colors.length===0){this.original_colors['chart.colors']=RG.arrayClone(prop['chart.colors']);this.original_colors['chart.key.colors']=RG.arrayClone(prop['chart.key.colors']);this.original_colors['chart.strokestyle']=RG.arrayClone(prop['chart.strokestyle']);this.original_colors['chart.highlight.stroke']=RG.arrayClone(prop['chart.highlight.stroke']);this.original_colors['chart.highlight.style.twod.fill']=RG.arrayClone(prop['chart.highlight.style.twod.fill']);this.original_colors['chart.highlight.style.twod.stroke']=RG.arrayClone(prop['chart.highlight.style.twod.stroke']);this.original_colors['chart.ingraph.bounding.fill']=RG.arrayClone(prop['chart.ingraph.bounding.fill']);this.original_colors['chart.ingraph.color']=RG.arrayClone(prop['chart.ingraph.color']);}
109
+ for(var i=0;i<prop['chart.colors'].length;++i){prop['chart.colors'][i]=this.parseSingleColorForGradient(prop['chart.colors'][i]);}
110
+ var keyColors=prop['chart.key.colors'];if(keyColors){for(var i=0;i<keyColors.length;++i){keyColors[i]=this.parseSingleColorForGradient(keyColors[i]);}}
111
+ prop['chart.strokestyle']=this.parseSingleColorForGradient(prop['chart.strokestyle']);prop['chart.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.stroke']);prop['chart.highlight.style.twod.fill']=this.parseSingleColorForGradient(prop['chart.highlight.style.twod.fill']);prop['chart.highlight.style.twod.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.style.twod.stroke']);prop['chart.labels.ingraph.bounding.fill']=this.parseSingleColorForGradient(prop['chart.labels.ingraph.bounding.fill']);prop['chart.labels.ingraph.color']=this.parseSingleColorForGradient(prop['chart.labels.ingraph.color']);};this.reset=function()
112
+ {};this.parseSingleColorForGradient=function(color)
113
+ {if(!color||typeof(color)!='string'){return color;}
114
+ if(color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':');if(prop['chart.variant']=='donut'){var radius_start=typeof(prop['chart.variant.donut.width'])=='number'?this.radius-prop['chart.variant.donut.width']:this.radius/2;}else{var radius_start=0;}
115
+ var grad=co.createRadialGradient(this.centerx,this.centery,radius_start,this.centerx,this.centery,Math.min(ca.width-prop['chart.gutter.left']-prop['chart.gutter.right'],ca.height-prop['chart.gutter.top']-prop['chart.gutter.bottom'])/2);var diff=1/(parts.length-1);grad.addColorStop(0,RG.trim(parts[0]));for(var j=1;j<parts.length;++j){grad.addColorStop(j*diff,RG.trim(parts[j]));}}
116
+ return grad?grad:color;};this.interactiveKeyHighlight=function(index)
117
+ {if(this.angles&&this.angles[index]){var segment=this.angles[index];var x=segment[2];var y=segment[3];var start=segment[0];var end=segment[1];co.strokeStyle=prop['chart.key.interactive.highlight.chart.stroke'];co.fillStyle=prop['chart.key.interactive.highlight.chart.fill'];co.lineWidth=2;co.lineJoin='bevel';co.beginPath();co.moveTo(x,y);co.arc(x,y,this.radius,start,end,false);co.closePath();co.fill();co.stroke();}};this.on=function(type,func)
118
+ {if(type.substr(0,2)!=='on'){type='on'+type;}
119
+ if(typeof this[type]!=='function'){this[type]=func;}else{RG.addCustomEventListener(this,type,func);}
120
+ return this;};this.firstDrawFunc=function()
121
+ {};this.draw3d=function()
122
+ {var scaleX=1.5,depth=prop['chart.variant.threed.depth'],prop_shadow=prop['chart.shadow'],prop_labels=prop['chart.labels'],prop_labelsSticks=prop['chart.labels.sticks']
123
+ this.set({labels:[],labelsSticks:false,strokestyle:'rgba(0,0,0,0)'});this.set({variant:this.get('variant').replace(/3d/,'')});this.context.setTransform(scaleX,0,0,1,(ca.width*(scaleX)-ca.width)* -0.5,0);for(var i=depth;i>0;i-=1){this.set({centeryAdjust:i});if(i===parseInt(depth/2)){this.set({labels:prop_labels,labelsSticks:prop_labelsSticks});}
124
+ if(i===0){this.set({shadow:prop_shadow});}
125
+ this.draw();this.set('shadow',false);if(i<=parseInt(depth/2)){this.set({labels:[],labelsSticks:false});}
126
+ if(i>1){if(prop['chart.variant'].indexOf('donut')!==-1){for(var j=0;j<this.angles.length;++j){pa2(co,['b','a',this.angles[j][2],this.angles[j][3],this.radius+1,this.angles[j][0],this.angles[j][1]*prop['chart.effect.roundrobin.multiplier'],false,'a',this.angles[j][2],this.angles[j][3],this.radius/2,this.angles[j][1]*prop['chart.effect.roundrobin.multiplier'],this.angles[j][0],true,'f','rgba(0,0,0,0.15)']);}}else{for(var j=0;j<this.angles.length;++j){pa2(co,['b','m',this.angles[j][2],this.angles[j][3],'a',this.angles[j][2],this.angles[j][3],this.radius+1,this.angles[j][0],this.angles[j][1]*prop['chart.effect.roundrobin.multiplier'],false,'c','f','rgba(0,0,0,0.15)']);}}}}
127
+ this.set({variant:this.get('variant')+'3d',shadow:prop_shadow,labels:prop_labels,labelsSticks:prop_labelsSticks});return this;};this.explode=function()
128
+ {var obj=this;var opt=arguments[0]?arguments[0]:{};var callback=arguments[1]?arguments[1]:function(){};var frames=opt.frames?opt.frames:30;var frame=0;var maxExplode=Number(typeof opt.radius==='number'?opt.radius:ma.max(ca.width,ca.height));var currentExplode=Number(obj.get('exploded'))||0;var step=(maxExplode-currentExplode)/frames;var iterator=function()
129
+ {obj.set('exploded',currentExplode+(step*frame));RGraph.clear(obj.canvas);RGraph.redrawCanvas(obj.canvas);if(frame++<frames){RGraph.Effects.updateCanvas(iterator);}else{callback(obj);}}
130
+ iterator();return this;};this.grow=function()
131
+ {var obj=this;var canvas=obj.canvas;var opt=arguments[0]?arguments[0]:{};var frames=opt.frames||30;var frame=0;var callback=arguments[1]?arguments[1]:function(){};var radius=obj.getRadius();prop['chart.radius']=0;var iterator=function()
132
+ {obj.set('chart.radius',(frame/frames)*radius);RG.redrawCanvas(ca);if(frame++<frames){RG.Effects.updateCanvas(iterator);}else{RG.redrawCanvas(obj.canvas);callback(obj);}};iterator();return this;};this.roundrobin=this.roundRobin=function()
133
+ {var obj=this,opt=arguments[0]||{},callback=arguments[1]||function(){},frame=0,frames=opt.frames||30,radius=obj.getRadius(),labels=obj.get('labels')
134
+ obj.Set('chart.events',false);obj.Set('chart.labels',[]);var iterator=function()
135
+ {obj.set('effect.roundrobin.multiplier',RG.Effects.getEasingMultiplier(frames,frame));RGraph.redrawCanvas(ca);if(frame++<frames){RGraph.Effects.updateCanvas(iterator);}else{obj.set({events:true,labels:labels});RG.redrawCanvas(obj.canvas);callback(obj);}};iterator();return this;};RG.att(ca);this.implode=function()
136
+ {var obj=this,opt=arguments[0]||{},callback=arguments[1]||function(){},frames=opt.frames||30,frame=0,explodedMax=ma.max(ca.width,ca.height),exploded=explodedMax;function iterator()
137
+ {exploded=explodedMax-((frame/frames)*explodedMax);obj.Set('exploded',exploded);RG.clear(ca);RG.redrawCanvas(ca);if(frame++<frames){RG.Effects.updateCanvas(iterator);}else{RG.clear(obj.canvas);RG.redrawCanvas(obj.canvas);callback(obj);}}
138
+ iterator();return this;};RG.register(this);if(parseConfObjectForOptions){RG.parseObjectStyleConfig(this,conf.options);}};