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,1132 +1,56 @@
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
- RGraph.SVG = RGraph.SVG || {};
15
-
16
- // Module pattern
17
- (function (win, doc, undefined)
18
- {
19
- var RG = RGraph,
20
- ua = navigator.userAgent,
21
- ma = Math,
22
- win = window,
23
- doc = document;
24
-
25
-
26
-
27
- RG.SVG.Pie = function (conf)
28
- {
29
- //
30
- // A setter that the constructor uses (at the end)
31
- // to set all of the properties
32
- //
33
- // @param string name The name of the property to set
34
- // @param string value The value to set the property to
35
- //
36
- this.set = function (name, value)
37
- {
38
- if (arguments.length === 1 && typeof name === 'object') {
39
- for (i in arguments[0]) {
40
- if (typeof i === 'string') {
41
-
42
- var ret = RG.SVG.commonSetter({
43
- object: this,
44
- name: i,
45
- value: arguments[0][i]
46
- });
47
-
48
- name = ret.name;
49
- value = ret.value;
50
-
51
- this.set(name, value);
52
- }
53
- }
54
- } else {
55
-
56
- var ret = RG.SVG.commonSetter({
57
- object: this,
58
- name: name,
59
- value: value
60
- });
61
-
62
- name = ret.name;
63
- value = ret.value;
64
-
65
- this.properties[name] = value;
66
- }
67
-
68
- return this;
69
- };
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
- this.id = conf.id;
79
- this.uid = RG.SVG.createUID();
80
- this.container = document.getElementById(this.id);
81
- this.svg = RG.SVG.createSVG({container: this.container});
82
- this.isRGraph = true;
83
- this.width = Number(this.svg.getAttribute('width'));
84
- this.height = Number(this.svg.getAttribute('height'));
85
- this.data = conf.data;
86
- this.type = 'pie';
87
- this.angles = [];
88
- this.colorsParsed = false;
89
- this.originalColors = {};
90
- this.gradientCounter = 1;
91
- this.nodes = [];
92
- this.shadowNodes = [];
93
-
94
- // Add this object to the ObjectRegistry
95
- RG.SVG.OR.add(this);
96
-
97
- // Set the DIV container to be inline-block
98
- this.container.style.display = 'inline-block';
99
-
100
- this.properties =
101
- {
102
- centerx: null,
103
- centery: null,
104
- radius: null,
105
-
106
- gutterLeft: 35,
107
- gutterRight: 35,
108
- gutterTop: 35,
109
- gutterBottom: 35,
110
-
111
- colors: [
112
- '#f66', '#6f6', '#66f', '#ff6', '#6ff', '#ccc',
113
- 'pink', 'orange', 'cyan', 'maroon', 'olive', 'teal'
114
- ],
115
- strokestyle: 'rgba(0,0,0,0)',
116
-
117
- margin: 3,
118
-
119
- textColor: 'black',
120
- textFont: 'sans-serif',
121
- textSize: 12,
122
- textBold: false,
123
- textItalic: false,
124
- labels: [],
125
- labelsSticks: true,
126
- labelsSticksHlength: 50,
127
-
128
- linewidth: 1,
129
-
130
- tooltips: null,
131
- tooltipsOverride: null,
132
- tooltipsEffect: 'fade',
133
- tooltipsCssClass: 'RGraph_tooltip',
134
- tooltipsEvent: 'click',
135
-
136
- highlightStroke: 'rgba(0,0,0,0)',
137
- highlightFill: 'rgba(255,255,255,0.7)',
138
- highlightLinewidth: 1,
139
-
140
- title: '',
141
- titleSize: 16,
142
- titleX: null,
143
- titleY: null,
144
- titleHalign: 'center',
145
- titleValign: null,
146
- titleColor: 'black',
147
- titleFont: null,
148
- titleBold: false,
149
- titleItalic: false,
150
-
151
- titleSubtitle: '',
152
- titleSubtitleSize: 10,
153
- titleSubtitleX: null,
154
- titleSubtitleY: null,
155
- titleSubtitleHalign: 'center',
156
- titleSubtitleValign: null,
157
- titleSubtitleColor: '#aaa',
158
- titleSubtitleFont: null,
159
- titleSubtitleBold: false,
160
- titleSubtitleItalic: false,
161
-
162
- shadow: false,
163
- shadowOffsetx: 2,
164
- shadowOffsety: 2,
165
- shadowBlur: 2,
166
- shadowOpacity: 0.25,
167
-
168
- exploded: 0,
169
- roundRobinMultiplier: 1,
170
-
171
- donut: false,
172
- donutWidth: 75,
173
-
174
- key: null,
175
- keyColors: null,
176
- keyOffsetx: 0,
177
- keyOffsety: 0,
178
- keyTextOffsetx: 0,
179
- keyTextOffsety: -1,
180
- keyTextSize: null,
181
- keyTextBold: null,
182
- keyTextItalic: null,
183
-
184
- attribution: true,
185
- attributionX: null,
186
- attributionY: null,
187
- attributionHref: null,// Default is set in RGraph.svg.common.core.js
188
- attributionHalign: 'right',
189
- attributionValign: 'bottom',
190
- attributionSize: 7,
191
- attributionColor: 'gray',
192
- attributionFont: 'sans-serif',
193
- attributionItalic: false,
194
- attributionBold: false
195
- };
196
-
197
-
198
-
199
-
200
-
201
- /**
202
- * "Decorate" the object with the generic effects if the effects library has been included
203
- */
204
- if (RG.SVG.FX && typeof RG.SVG.FX.decorate === 'function') {
205
- RG.SVG.FX.decorate(this);
206
- }
207
-
208
-
209
-
210
-
211
- var prop = this.properties;
212
-
213
-
214
-
215
-
216
-
217
-
218
-
219
-
220
- //
221
- // The draw method draws the Bar chart
222
- //
223
- this.draw = function ()
224
- {
225
- // Fire the beforedraw event
226
- RG.SVG.fireCustomEvent(this, 'onbeforedraw');
227
-
228
-
229
-
230
-
231
- // Create the defs tag if necessary
232
- RG.SVG.createDefs(this);
233
-
234
-
235
-
236
-
237
- this.graphWidth = this.width - prop.gutterLeft - prop.gutterRight;
238
- this.graphHeight = this.height - prop.gutterTop - prop.gutterBottom;
239
-
240
-
241
-
242
- // Work out the center point
243
- this.centerx = (this.graphWidth / 2) + prop.gutterLeft;
244
- this.centery = (this.graphHeight / 2) + prop.gutterTop;
245
- this.radius = ma.min(this.graphWidth, this.graphHeight) / 2;
246
-
247
-
248
-
249
- // Allow the user to override the calculated centerx/y/radius
250
- this.centerx = typeof prop.centerx === 'number' ? prop.centerx : this.centerx;
251
- this.centery = typeof prop.centery === 'number' ? prop.centery : this.centery;
252
- this.radius = typeof prop.radius === 'number' ? prop.radius : this.radius;
253
-
254
- //
255
- // Allow the centerx/centery/radius to be a plus/minus
256
- //
257
- if (typeof prop.radius === 'string' && prop.radius.match(/^\+|-\d+$/) ) this.radius += parseFloat(prop.radius);
258
- if (typeof prop.centerx === 'string' && prop.centerx.match(/^\+|-\d+$/) ) this.centerx += parseFloat(prop.centerx);
259
- if (typeof prop.centery === 'string' && prop.centery.match(/^\+|-\d+$/) ) this.centery += parseFloat(prop.centery);
260
-
261
-
262
- // Parse the colors for gradients
263
- // Must be after the cx/cy/r calculations
264
- RG.SVG.resetColorsToOriginalValues({object:this});
265
- this.parseColors();
266
-
267
-
268
- // Go through the data and work out the maximum value
269
- this.max = RG.SVG.arrayMax(this.data);
270
- this.total = RG.SVG.arraySum(this.data);
271
-
272
- // Set the explosion to be an array if it's a number
273
- if (typeof prop.exploded === 'number' && prop.exploded > 0) {
274
- var val = prop.exploded;
275
-
276
- prop.exploded = [];
277
-
278
- for (var i=0; i<this.data.length; ++i) {
279
- prop.exploded[i] = val;
280
- }
281
- }
282
-
283
-
284
-
285
- // Draw the segments
286
- this.drawSegments({shadow: true});
287
-
288
-
289
-
290
- // Draw the title and subtitle
291
- RG.SVG.drawTitle(this);
292
-
293
-
294
-
295
- // Draw the labels
296
- if (prop.labelsSticks) {
297
- this.drawLabelsSticks();
298
- } else {
299
- this.drawLabels();
300
- }
301
-
302
-
303
-
304
-
305
- // Draw the key
306
- if (typeof prop.key !== null && RG.SVG.drawKey) {
307
- RG.SVG.drawKey(this);
308
- } else if (!RGraph.SVG.isNull(prop.key)) {
309
- alert('The drawKey() function does not exist - have you forgotten to include the key library?');
310
- }
311
-
312
-
313
- // Add the attribution link. If you're adding this elsewhere on your page/site
314
- // and you don't want it displayed then there are options available to not
315
- // show it.
316
- RG.SVG.attribution(this);
317
-
318
-
319
- // Add the event listener that clears the highlight if
320
- // there is any. Must be MOUSEDOWN (ie before the click event)
321
- var obj = this;
322
- document.body.addEventListener('mousedown', function (e)
323
- {
324
- RG.SVG.removeHighlight(obj);
325
- }, false);
326
-
327
-
328
-
329
- // Fire the draw event
330
- RG.SVG.fireCustomEvent(this, 'ondraw');
331
-
332
-
333
-
334
- return this;
335
- };
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
- //
345
- // Draws the segments
346
- //
347
- // @param bool Whether or not this is a redraw. If this is a redraw
348
- // shadows are omitted
349
- //
350
- this.drawSegments = function (opt)
351
- {
352
- var start = 0,
353
- end = 0,
354
- angle = 0,
355
- sum = RG.SVG.arraySum(this.data),
356
- segment = 0;
357
-
358
-
359
-
360
-
361
- // Work out the start and end angles for the data
362
- for (var i=0,len=this.data.length; i<len; ++i) {
363
-
364
- var value = this.data[i] * prop.roundRobinMultiplier;
365
-
366
- start = angle;
367
- segment = ((value / sum) * RG.SVG.TRIG.TWOPI);
368
- end = start + segment;
369
-
370
- var explosion = RG.SVG.TRIG.getRadiusEndPoint({
371
- angle: start + (segment / 2),
372
- r: prop.exploded[i]
373
- });
374
-
375
- var explosionX = explosion[1],
376
- explosionY = explosion[0];
377
-
378
-
379
- this.angles[i] = {
380
- start: start,
381
- end: end,
382
- angle: end - start,
383
- halfway: ((end - start) / 2) + start,
384
- cx: this.centerx + (parseFloat(explosionX) || 0),
385
- cy: this.centery - (parseFloat(explosionY) || 0),
386
- radius: this.radius
387
- };
388
-
389
- // Increase the angle at which we start drawing the next segment at
390
- angle += (end - start);
391
- }
392
-
393
-
394
-
395
- if (opt.shadow) {
396
- RG.SVG.setShadow({
397
- object: this,
398
- offsetx: prop.shadowOffsetx,
399
- offsety: prop.shadowOffsety,
400
- blur: prop.shadowBlur,
401
- opacity: prop.shadowOpacity,
402
- id: 'dropShadow'
403
- });
404
- }
405
-
406
-
407
- //
408
- // This loop goes thru the angles that were
409
- // generated above and adds them to the
410
- // scene
411
- //
412
- for (var i=0; i<this.angles.length; ++i) {
413
-
414
- var path = RG.SVG.TRIG.getArcPath({
415
- cx: this.angles[i].cx,
416
- cy: this.angles[i].cy,
417
- r: this.radius,
418
- start: this.angles[i].start,
419
- end: this.angles[i].end
420
- });
421
-
422
-
423
-
424
-
425
-
426
- // Donut
427
- if (prop.donut) {
428
-
429
- var donutWidth = prop.donutWidth;
430
-
431
- var donut_path = RG.SVG.TRIG.getArcPath({
432
- cx: this.angles[i].cx,
433
- cy: this.angles[i].cy,
434
- r: this.radius - donutWidth,
435
- start: this.angles[i].end,
436
- end: this.angles[i].start,
437
- moveto: false,
438
- anticlockwise: true
439
- });
440
-
441
- var xy = RG.SVG.TRIG.getRadiusEndPoint({
442
- angle: this.angles[i].end - RG.SVG.TRIG.HALFPI,
443
- r: this.radius - donutWidth
444
- });
445
-
446
-
447
-
448
-
449
- path = path
450
- + " L {1} {2} ".format(xy[0] + this.angles[i].cx, xy[1] + this.angles[i].cy)
451
- + donut_path
452
- + " Z";
453
-
454
-
455
- } else {
456
-
457
- path = path + " L {1} {2} ".format(
458
- this.angles[i].cx,
459
- this.angles[i].cy
460
- ) + " Z"
461
- }
462
-
463
-
464
-
465
- var arc = RG.SVG.create({
466
- svg: this.svg,
467
- parent: this.svg.all,
468
- type: 'path',
469
- attr: {
470
- d: path,
471
- fill: prop.colors[i],
472
- stroke: prop.strokestyle,
473
- 'stroke-width': prop.linewidth,
474
- 'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[i] : '',
475
- 'data-index': i,
476
- 'data-value': value,
477
- 'data-start-angle': this.angles[i].start,
478
- 'data-end-angle': this.angles[i].end,
479
- 'data-radius': this.radius,
480
- filter: (prop.shadow && opt.shadow) ? 'url(#dropShadow)' : ''
481
- }
482
- });
483
-
484
- // Store a reference to the node
485
- if (prop.shadow && opt.shadow) {
486
- this.shadowNodes[i] = arc;
487
- } else {
488
- this.nodes[i] = arc;
489
- }
490
-
491
- if (prop.tooltips && prop.tooltips[i] && (!opt.shadow || !prop.shadow)) {
492
-
493
- // Make the tooltipsEvent default to click
494
- if (prop.tooltipsEvent !== 'mousemove') {
495
- prop.tooltipsEvent = 'click';
496
- }
497
-
498
- (function (index, obj)
499
- {
500
- arc.addEventListener(prop.tooltipsEvent, function (e)
501
- {
502
- obj.removeHighlight();
503
-
504
- // Show the tooltip
505
- RG.SVG.tooltip({
506
- object: obj,
507
- index: index,
508
- sequentialIndex: index,
509
- text: prop.tooltips[index],
510
- event: e
511
- });
512
-
513
- // Highlight the rect that has been clicked on
514
- obj.highlight(e.target);
515
-
516
- var highlight = RG.SVG.REG.get('highlight');
517
-
518
- if (prop.tooltipsEvent === 'mousemove') {
519
- highlight.style.cursor = 'pointer';
520
- }
521
-
522
- }, false);
523
-
524
- // Install the event listener that changes the
525
- // cursor if necessary
526
- if (prop.tooltipsEvent === 'click') {
527
- arc.addEventListener('mousemove', function (e)
528
- {
529
- e.target.style.cursor = 'pointer';
530
- }, false);
531
- }
532
-
533
- }(i, this));
534
- }
535
- }
536
-
537
- //
538
- // Redraw the segments if necessary so that they're on
539
- // top of any shadow
540
- //
541
- if (prop.shadow && opt.shadow) {
542
- this.redrawSegments();
543
- }
544
- };
545
-
546
-
547
-
548
-
549
-
550
-
551
-
552
-
553
- //
554
- // Redraw the Bars o that the bars appear above any shadow
555
- //
556
- this.redrawSegments = function ()
557
- {
558
- this.drawSegments({shadow: false});
559
- };
560
-
561
-
562
-
563
-
564
-
565
-
566
-
567
-
568
- //
569
- // Draw the labels
570
- //
571
- this.drawLabels = function ()
572
- {
573
- var angles = this.angles,
574
- prop = this.properties,
575
- labels = prop.labels;
576
-
577
- for (var i=0; i<angles.length; ++i) {
578
-
579
- var endpoint = RG.SVG.TRIG.getRadiusEndPoint({
580
- angle: angles[i].halfway - RG.SVG.TRIG.HALFPI,
581
- r: angles[i].radius + 15
582
- });
583
-
584
- var x = endpoint[0] + angles[i].cx,
585
- y = endpoint[1] + angles[i].cy,
586
- valign,
587
- halign;
588
-
589
- // Figure out the valign and halign based on the quadrant
590
- // the the center of the sgement is in.
591
- if (angles[i].halfway > 0 && angles[i].halfway < RG.SVG.TRIG.HALFPI) {
592
- halign = 'left';
593
- valign = 'bottom';
594
- } else if (angles[i].halfway > RG.SVG.TRIG.HALFPI && angles[i].halfway < RG.SVG.TRIG.PI) {
595
- halign = 'left';
596
- valign = 'top';
597
- } else if (angles[i].halfway > RG.SVG.TRIG.PI && angles[i].halfway < (RG.SVG.TRIG.HALFPI + RG.SVG.TRIG.PI)) {
598
- halign = 'right';
599
- valign = 'top';
600
- } else if (angles[i].halfway > (RG.SVG.TRIG.HALFPI + RG.SVG.TRIG.PI) && angles[i].halfway < RG.SVG.TRIG.TWOPI) {
601
- halign = 'right';
602
- valign = 'top';
603
- }
604
-
605
- RG.SVG.text({
606
- object: this,
607
- parent: this.svg.all,
608
- text: typeof labels[i] === 'string' ? labels[i] : '',
609
- font: prop.textFont,
610
- size: prop.textSize,
611
- x: x,
612
- y: y,
613
- valign: valign,
614
- halign: halign,
615
- bold: prop.textBold,
616
- italic: prop.textItalic,
617
- color: prop.textColor
618
- });
619
- }
620
- };
621
-
622
-
623
-
624
-
625
-
626
-
627
-
628
-
629
- //
630
- // This function draws the labels in a list format
631
- //
632
- this.drawLabelsSticks = function ()
633
- {
634
- var labels_right = [],
635
- labels_left = [],
636
- labels_coords = [];
637
-
638
- for (var i=0; i<this.angles.length; ++i) {
639
-
640
- var angle = (this.angles[i].start + ((this.angles[i].end - this.angles[i].start) / 2)) - RGraph.SVG.TRIG.HALFPI, // Midpoint
641
-
642
- endpoint_inner = RG.SVG.TRIG.getRadiusEndPoint({angle: angle, r: this.radius + 5}),
643
- endpoint_outer = RG.SVG.TRIG.getRadiusEndPoint({angle: angle, r: this.radius + 20}),
644
-
645
- explosion = [
646
- (typeof prop.exploded === 'number' ? prop.exploded : prop.exploded[i]),
647
- ma.cos(angle) * (typeof prop.exploded === 'number' ? prop.exploded : prop.exploded[i]),
648
- ma.sin(angle) * (typeof prop.exploded === 'number' ? prop.exploded : prop.exploded[i])
649
- ];
650
-
651
- // Initialise this array
652
- labels_coords[i] = [];
653
-
654
- // Initialise this
655
- var labels = {};
656
-
657
-
658
-
659
-
660
-
661
- // Push the label into the correct array
662
- if (angle > RG.SVG.TRIG.HALFPI) {
663
-
664
- var index = labels_left.length;
665
-
666
- labels_left[index] = [];
667
- labels_left[index].text = prop.labels[i];
668
- labels_left[index].halign = 'right';
669
- labels = labels_left;
670
-
671
- labels_coords[i].halign = 'right';
672
- } else {
673
-
674
- var index = labels_right.length;
675
-
676
- labels_right[index] = [];
677
- labels_right[index].text = prop.labels[i];
678
- labels_right[index].halign = 'right';
679
- labels = labels_right;
680
-
681
- labels_coords[i].halign = 'left';
682
- }
683
-
684
-
685
-
686
-
687
-
688
-
689
-
690
- endpoint_inner[0] += (explosion[1] || 0);
691
- endpoint_inner[1] += (explosion[2] || 0);
692
-
693
- endpoint_outer[0] += (explosion[1] || 0);
694
- endpoint_outer[1] += (explosion[2] || 0);
695
-
696
- var x,y;
697
-
698
- if (labels[index].text) {
699
- var stick = RG.SVG.create({
700
- svg: this.svg,
701
- parent: this.svg.all,
702
- type: 'path',
703
- attr: {
704
- d: 'M {1} {2} L {3} {4}'.format(
705
- this.centerx + endpoint_inner[0],
706
- this.centery + endpoint_inner[1],
707
- this.centerx + endpoint_outer[0],
708
- this.centery + endpoint_outer[1]
709
- ),
710
- stroke: '#999',
711
- fill: 'rgba(0,0,0,0)'
712
- }
713
- });
714
- }
715
-
716
- // The path is altered later so this needs saving
717
- if (stick) {
718
- labels[index].stick = stick;
719
- }
720
-
721
- x = (this.centerx + endpoint_outer[0] + (angle > 1.57 ? -50 : 50));
722
- y = (this.centery + endpoint_outer[1]);
723
-
724
-
725
- labels_coords[i].x = x ;
726
- labels_coords[i].y = y;
727
- labels_coords[i].text = prop.labels[i];
728
- }
729
-
730
- // Calculate the spacing for each side
731
- var vspace_right = (this.height - prop.gutterTop - prop.gutterBottom) / labels_right.length;
732
- var vspace_left = (this.height - prop.gutterTop - prop.gutterBottom) / labels_left.length;
733
-
734
- // Reset these
735
- x = y = 0;
736
-
737
-
738
-
739
-
740
-
741
- // Loop through the RHS labels
742
- for (var i=0; i<labels_right.length; ++i) {
743
- if (labels_right[i] && labels_right[i].text) {
744
-
745
- x = this.centerx + this.radius + 100;
746
- y = prop.gutterTop + (vspace_right * i) + (vspace_right / 2);
747
-
748
-
749
- // Add the label to the scene
750
- RGraph.SVG.text({
751
- object: this,
752
- parent: this.svg.all,
753
- text: typeof labels_right[i].text === 'string' ? labels_right[i].text : '',
754
- font: prop.textFont,
755
- size: prop.textSize,
756
- x: x,
757
- y: y,
758
- valign: 'center',
759
- halign: labels_right[i].text,
760
- bold: prop.textBold,
761
- italic: prop.textItalic,
762
- color: prop.textColor
763
- });
764
-
765
- // Now update the path of the stick
766
- labels_right[i].stick.setAttribute(
767
- 'd',
768
- labels_right[i].stick.getAttribute('d') + ' H {3} L {1} {2} '.format(
769
- x - 5,
770
- y,
771
- this.centerx + this.radius + prop.labelsSticksHlength
772
- )
773
- );
774
- }
775
- }
776
-
777
-
778
-
779
-
780
-
781
- // Loop through the LHS labels
782
- for (var i=0; i<labels_left.length; ++i) {
783
- if (labels_left[i] && labels_left[i].text) {
784
-
785
- x = this.centerx - this.radius - 100;
786
- y = this.height - (prop.gutterTop + (vspace_left * i) + (vspace_left / 2));
787
-
788
-
789
- // Add the label to the scene
790
- RGraph.SVG.text({
791
- object: this,
792
- parent: this.svg.all,
793
- text: typeof labels_left[i].text === 'string' ? labels_left[i].text : '',
794
- font: prop.textFont,
795
- size: prop.textSize,
796
- x: x - 7,
797
- y: y,
798
- valign: 'center',
799
- halign: labels_left[i].halign,
800
- bold: prop.textBold,
801
- italic: prop.textItalic,
802
- color: prop.textColor
803
- });
804
-
805
- // Now update the path of the stick
806
- labels_left[i].stick.setAttribute(
807
- 'd',
808
- labels_left[i].stick.getAttribute('d') + ' H {3} L {1} {2} '.format(
809
- x - 5,
810
- y,
811
- this.centerx - this.radius - prop.labelsSticksHlength
812
- )
813
- );
814
- }
815
- }
816
- };
817
-
818
-
819
-
820
-
821
-
822
-
823
-
824
-
825
- /**
826
- * This function can be used to highlight a segment on the chart
827
- *
828
- * @param object segment The segment to highlight
829
- */
830
- this.highlight = function (segment)
831
- {
832
- var highlight = RG.SVG.create({
833
- svg: this.svg,
834
- parent: this.svg.all,
835
- type: 'path',
836
- attr: {
837
- d: segment.getAttribute('d'),
838
- fill: prop.highlightFill,
839
- stroke: prop.highlightStroke,
840
- 'stroke-width': prop.highlightLinewidth
841
- }
842
- });
843
-
844
- if (prop.tooltipsEvent === 'mousemove') {
845
- highlight.addEventListener('mouseout', function (e)
846
- {
847
- highlight.parentNode.removeChild(highlight);
848
- RG.SVG.hideTooltip();
849
-
850
- RG.SVG.REG.set('highlight', null);
851
- }, false);
852
- }
853
-
854
-
855
- // Store the highlight rect in the registry so
856
- // it can be cleared later
857
- RG.SVG.REG.set('highlight', highlight);
858
- };
859
-
860
-
861
-
862
-
863
-
864
-
865
-
866
-
867
- /**
868
- * This allows for easy specification of gradients
869
- */
870
- this.parseColors = function ()
871
- {
872
- // Save the original colors so that they can be restored when the canvas is reset
873
- if (!Object.keys(this.originalColors).length) {
874
- this.originalColors = {
875
- colors: RG.SVG.arrayClone(prop.colors),
876
- highlightFill: RG.SVG.arrayClone(prop.highlightFill)
877
- }
878
- }
879
-
880
-
881
- // colors
882
- var colors = prop.colors;
883
-
884
- if (colors) {
885
- for (var i=0; i<colors.length; ++i) {
886
- colors[i] = RG.SVG.parseColorRadial({
887
- object: this,
888
- color: colors[i]
889
- });
890
- }
891
- }
892
-
893
- // Highlight fill
894
- prop.highlightFill = RG.SVG.parseColorRadial({
895
- object: this,
896
- color: prop.highlightFill
897
- });
898
- };
899
-
900
-
901
-
902
-
903
-
904
-
905
-
906
-
907
- //
908
- // A roundRobin effect for the Pie chart
909
- //
910
- // @param object Options for the effect
911
- // @param function An optional callback function to call when
912
- // the effect is complete
913
- //
914
- this.roundRobin = function ()
915
- {
916
- var obj = this,
917
- opt = arguments[0] || {},
918
- data = RG.SVG.arrayClone(this.data),
919
- prop = this.properties,
920
- frame = 1,
921
- frames = opt.frames || 30,
922
- callback = typeof opt.callback === 'function' ? opt.callback : function () {},
923
- dataSum = RG.SVG.arraySum(this.data),
924
- textColor = prop.textColor;
925
-
926
- // Set the text color to transparent
927
- this.properties.textColor = 'rgba(0,0,0,0)';
928
-
929
-
930
- // Draw the chart first
931
- obj.draw();
932
-
933
- // Now get the resulting angles
934
- angles = RG.SVG.arrayClone(obj.angles);
935
-
936
-
937
- function iterator ()
938
- {
939
- prop.roundRobinMultiplier = 1 / frames * frame++;
940
-
941
- for (var i=0; i<obj.angles.length; ++i) {
942
-
943
- var value = obj.data[i];
944
-
945
-
946
-
947
- // NB This was an absolute git to work out for some reason.
948
-
949
-
950
-
951
- obj.angles[i].start = angles[i].start * prop.roundRobinMultiplier;
952
- obj.angles[i].end = angles[i].end * prop.roundRobinMultiplier;
953
-
954
- //var segment = (((value * prop.roundRobinMultiplier) / dataSum) * RG.SVG.TRIG.TWOPI);
955
- var segment = ((obj.angles[i].end - obj.angles[i].start) / 2);
956
- var explodedX = ma.cos(obj.angles[i].start + segment - RG.SVG.TRIG.HALFPI) * (prop.exploded[i] || 0);
957
- var explodedY = ma.sin(obj.angles[i].start + segment - RG.SVG.TRIG.HALFPI) * (prop.exploded[i] || 0);
958
-
959
-
960
-
961
- var path = RG.SVG.TRIG.getArcPath({
962
- cx: obj.centerx + explodedX,
963
- cy: obj.centery + explodedY,
964
- r: obj.radius,
965
- start: obj.angles[i].start,
966
- end: obj.angles[i].end
967
- });
968
-
969
-
970
-
971
-
972
-
973
- // Donut
974
- if (prop.donut) {
975
-
976
- var donutWidth = prop.donutWidth;
977
-
978
- var donut_path = RG.SVG.TRIG.getArcPath({
979
- cx: obj.angles[i].cx,
980
- cy: obj.angles[i].cy,
981
- r: obj.radius - donutWidth,
982
- start: obj.angles[i].end,
983
- end: obj.angles[i].start,
984
- moveto: false,
985
- anticlockwise: true
986
- });
987
-
988
- var xy = RG.SVG.TRIG.getRadiusEndPoint({
989
- angle: obj.angles[i].end - RG.SVG.TRIG.HALFPI,
990
- r: obj.radius - donutWidth
991
- });
992
-
993
- path = path
994
- + " L {1} {2} ".format(xy[0] + obj.angles[i].cx, xy[1] + obj.angles[i].cy)
995
- + donut_path
996
- + " Z";
997
-
998
- } else {
999
-
1000
- path = path + " L {1} {2} ".format(
1001
- obj.angles[i].cx,
1002
- obj.angles[i].cy
1003
- ) + " Z"
1004
- }
1005
-
1006
-
1007
-
1008
-
1009
-
1010
-
1011
-
1012
-
1013
-
1014
- path = path + " L {1} {2} Z".format(
1015
- obj.centerx + explodedX,
1016
- obj.centery + explodedY
1017
- );
1018
-
1019
- if (obj.shadowNodes && obj.shadowNodes[i]) {
1020
- obj.shadowNodes[i].setAttribute('d', path);
1021
- }
1022
- obj.nodes[i].setAttribute('d', path);
1023
- }
1024
-
1025
-
1026
- if (frame <= frames) {
1027
- RG.SVG.FX.update(iterator);
1028
- } else {
1029
- prop.textColor = textColor;
1030
-
1031
- RG.SVG.redraw(obj.svg);
1032
-
1033
- callback(obj);
1034
- }
1035
- }
1036
-
1037
- iterator();
1038
-
1039
- return this;
1040
- };
1041
-
1042
-
1043
-
1044
-
1045
-
1046
-
1047
-
1048
-
1049
- /**
1050
- * Using a function to add events makes it easier to facilitate method
1051
- * chaining
1052
- *
1053
- * @param string type The type of even to add
1054
- * @param function func
1055
- */
1056
- this.on = function (type, func)
1057
- {
1058
- if (type.substr(0,2) !== 'on') {
1059
- type = 'on' + type;
1060
- }
1061
-
1062
- RG.SVG.addCustomEventListener(this, type, func);
1063
-
1064
- return this;
1065
- };
1066
-
1067
-
1068
-
1069
-
1070
-
1071
-
1072
-
1073
-
1074
- //
1075
- // Used in chaining. Runs a function there and then - not waiting for
1076
- // the events to fire (eg the onbeforedraw event)
1077
- //
1078
- // @param function func The function to execute
1079
- //
1080
- this.exec = function (func)
1081
- {
1082
- func(this);
1083
-
1084
- return this;
1085
- };
1086
-
1087
-
1088
-
1089
-
1090
-
1091
-
1092
-
1093
-
1094
- //
1095
- // Remove highlight from the chart (tooltips)
1096
- //
1097
- this.removeHighlight = function ()
1098
- {
1099
- var highlight = RG.SVG.REG.get('highlight');
1100
- if (highlight && highlight.parentNode) {
1101
- highlight.parentNode.removeChild(highlight);
1102
- }
1103
-
1104
- RG.SVG.REG.set('highlight', null);
1105
- };
1106
-
1107
-
1108
-
1109
-
1110
-
1111
-
1112
-
1113
-
1114
- //
1115
- // Set the options that the user has provided
1116
- //
1117
- for (i in conf.options) {
1118
- if (typeof i === 'string') {
1119
- this.set(i, conf.options[i]);
1120
- }
1121
- }
1122
- };
1123
-
1124
-
1125
-
1126
- return this;
1127
-
1128
-
1129
-
1130
-
1131
- // End module pattern
1132
- })(window, document);
2
+ RGraph=window.RGraph||{isRGraph:true};RGraph.SVG=RGraph.SVG||{};(function(win,doc,undefined)
3
+ {var RG=RGraph,ua=navigator.userAgent,ma=Math,win=window,doc=document;RG.SVG.Pie=function(conf)
4
+ {this.set=function(name,value)
5
+ {if(arguments.length===1&&typeof name==='object'){for(i in arguments[0]){if(typeof i==='string'){var ret=RG.SVG.commonSetter({object:this,name:i,value:arguments[0][i]});name=ret.name;value=ret.value;this.set(name,value);}}}else{var ret=RG.SVG.commonSetter({object:this,name:name,value:value});name=ret.name;value=ret.value;this.properties[name]=value;if(name==='colors'){this.originalColors=RG.SVG.arrayClone(value);this.colorsParsed=false;}}
6
+ return this;};this.id=conf.id;this.uid=RG.SVG.createUID();this.container=document.getElementById(this.id);this.layers={};this.svg=RG.SVG.createSVG({object:this,container:this.container});this.isRGraph=true;this.width=Number(this.svg.getAttribute('width'));this.height=Number(this.svg.getAttribute('height'));this.data=conf.data;this.type='pie';this.angles=[];this.colorsParsed=false;this.originalColors={};this.gradientCounter=1;this.nodes=[];this.shadowNodes=[];RG.SVG.OR.add(this);this.container.style.display='inline-block';this.properties={centerx:null,centery:null,radius:null,gutterLeft:35,gutterRight:35,gutterTop:35,gutterBottom:35,colors:['#f66','#6f6','#66f','#ff6','#6ff','#ccc','pink','orange','cyan','maroon','olive','teal'],strokestyle:'rgba(0,0,0,0)',margin:3,textColor:'black',textFont:'sans-serif',textSize:12,textBold:false,textItalic:false,labels:[],labelsSticks:true,labelsSticksHlength:50,linewidth:1,tooltips:null,tooltipsOverride:null,tooltipsEffect:'fade',tooltipsCssClass:'RGraph_tooltip',tooltipsEvent:'click',highlightStroke:'rgba(0,0,0,0)',highlightFill:'rgba(255,255,255,0.7)',highlightLinewidth:1,title:'',titleSize:16,titleX:null,titleY:null,titleHalign:'center',titleValign:null,titleColor:'black',titleFont:null,titleBold:false,titleItalic:false,titleSubtitle:'',titleSubtitleSize:10,titleSubtitleX:null,titleSubtitleY:null,titleSubtitleHalign:'center',titleSubtitleValign:null,titleSubtitleColor:'#aaa',titleSubtitleFont:null,titleSubtitleBold:false,titleSubtitleItalic:false,shadow:false,shadowOffsetx:2,shadowOffsety:2,shadowBlur:2,shadowOpacity:0.25,exploded:0,roundRobinMultiplier:1,donut:false,donutWidth:75,key:null,keyColors:null,keyOffsetx:0,keyOffsety:0,keyTextOffsetx:0,keyTextOffsety:-1,keyTextSize:null,keyTextBold:null,keyTextItalic:null};RG.SVG.getGlobals(this);if(RG.SVG.FX&&typeof RG.SVG.FX.decorate==='function'){RG.SVG.FX.decorate(this);}
7
+ var prop=this.properties;this.draw=function()
8
+ {RG.SVG.fireCustomEvent(this,'onbeforedraw');RG.SVG.createDefs(this);this.graphWidth=this.width-prop.gutterLeft-prop.gutterRight;this.graphHeight=this.height-prop.gutterTop-prop.gutterBottom;this.centerx=(this.graphWidth/2)+prop.gutterLeft;this.centery=(this.graphHeight/2)+prop.gutterTop;this.radius=ma.min(this.graphWidth,this.graphHeight)/2;this.centerx=typeof prop.centerx==='number'?prop.centerx:this.centerx;this.centery=typeof prop.centery==='number'?prop.centery:this.centery;this.radius=typeof prop.radius==='number'?prop.radius:this.radius;if(typeof prop.radius==='string'&&prop.radius.match(/^\+|-\d+$/))this.radius+=parseFloat(prop.radius);if(typeof prop.centerx==='string'&&prop.centerx.match(/^\+|-\d+$/))this.centerx+=parseFloat(prop.centerx);if(typeof prop.centery==='string'&&prop.centery.match(/^\+|-\d+$/))this.centery+=parseFloat(prop.centery);RG.SVG.resetColorsToOriginalValues({object:this});this.parseColors();this.max=RG.SVG.arrayMax(this.data);this.total=RG.SVG.arraySum(this.data);if(typeof prop.exploded==='number'&&prop.exploded>0){var val=prop.exploded;prop.exploded=[];for(var i=0;i<this.data.length;++i){prop.exploded[i]=val;}}
9
+ this.drawSegments({shadow:true});RG.SVG.drawTitle(this);if(prop.labelsSticks){this.drawLabelsSticks();}else{this.drawLabels();}
10
+ this.drawIngraphLabels();if(typeof prop.key!==null&&RG.SVG.drawKey){RG.SVG.drawKey(this);}else if(!RGraph.SVG.isNull(prop.key)){alert('The drawKey() function does not exist - have you forgotten to include the key library?');}
11
+ var obj=this;document.body.addEventListener('mousedown',function(e)
12
+ {RG.SVG.removeHighlight(obj);},false);RG.SVG.fireCustomEvent(this,'ondraw');return this;};this.drawSegments=function(opt)
13
+ {var start=0,end=0,angle=0,sum=RG.SVG.arraySum(this.data),segment=0;for(var i=0,len=this.data.length;i<len;++i){var value=this.data[i]*prop.roundRobinMultiplier;start=angle;segment=((value/sum)*RG.SVG.TRIG.TWOPI);end=start+segment;var explosion=RG.SVG.TRIG.getRadiusEndPoint({angle:start+(segment/2),r:prop.exploded[i]});var explosionX=explosion[1],explosionY=explosion[0];this.angles[i]={start:start,end:end,angle:end-start,halfway:((end-start)/2)+start,cx:this.centerx+(parseFloat(explosionX)||0),cy:this.centery-(parseFloat(explosionY)||0),radius:this.radius};angle+=(end-start);}
14
+ if(opt.shadow){RG.SVG.setShadow({object:this,offsetx:prop.shadowOffsetx,offsety:prop.shadowOffsety,blur:prop.shadowBlur,opacity:prop.shadowOpacity,id:'dropShadow'});}
15
+ for(var i=0;i<this.angles.length;++i){var path=RG.SVG.TRIG.getArcPath({cx:this.angles[i].cx,cy:this.angles[i].cy,r:this.radius,start:this.angles[i].start,end:this.angles[i].end});if(prop.donut){var donutWidth=prop.donutWidth;var donut_path=RG.SVG.TRIG.getArcPath({cx:this.angles[i].cx,cy:this.angles[i].cy,r:this.radius-donutWidth,start:this.angles[i].end,end:this.angles[i].start,moveto:false,anticlockwise:true});var xy=RG.SVG.TRIG.getRadiusEndPoint({angle:this.angles[i].end-RG.SVG.TRIG.HALFPI,r:this.radius-donutWidth});path=path
16
+ +" L {1} {2} ".format(xy[0]+this.angles[i].cx,xy[1]+this.angles[i].cy)
17
+ +donut_path
18
+ +" Z";}else{path=path+" L {1} {2} ".format(this.angles[i].cx,this.angles[i].cy)+" Z"}
19
+ var arc=RG.SVG.create({svg:this.svg,parent:this.svg.all,type:'path',attr:{d:path,fill:prop.colors[i],stroke:prop.strokestyle,'stroke-width':prop.linewidth,'data-tooltip':(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips.length)?prop.tooltips[i]:'','data-index':i,'data-value':value,'data-start-angle':this.angles[i].start,'data-end-angle':this.angles[i].end,'data-radius':this.radius,filter:(prop.shadow&&opt.shadow)?'url(#dropShadow)':''}});if(prop.shadow&&opt.shadow){this.shadowNodes[i]=arc;}else{this.nodes[i]=arc;}
20
+ if(prop.tooltips&&prop.tooltips[i]&&(!opt.shadow||!prop.shadow)){if(prop.tooltipsEvent!=='mousemove'){prop.tooltipsEvent='click';}
21
+ (function(index,obj)
22
+ {arc.addEventListener(prop.tooltipsEvent,function(e)
23
+ {obj.removeHighlight();RG.SVG.tooltip({object:obj,index:index,sequentialIndex:index,text:prop.tooltips[index],event:e});obj.highlight(e.target);var highlight=RG.SVG.REG.get('highlight');if(prop.tooltipsEvent==='mousemove'){highlight.style.cursor='pointer';}},false);if(prop.tooltipsEvent==='click'){arc.addEventListener('mousemove',function(e)
24
+ {e.target.style.cursor='pointer';},false);}}(i,this));}}
25
+ if(prop.shadow&&opt.shadow){this.redrawSegments();}};this.redrawSegments=function()
26
+ {this.drawSegments({shadow:false});};this.drawLabels=function()
27
+ {var angles=this.angles,prop=this.properties,labels=prop.labels;for(var i=0;i<angles.length;++i){var endpoint=RG.SVG.TRIG.getRadiusEndPoint({angle:angles[i].halfway-RG.SVG.TRIG.HALFPI,r:angles[i].radius+15});var x=endpoint[0]+angles[i].cx,y=endpoint[1]+angles[i].cy,valign,halign;if(angles[i].halfway>0&&angles[i].halfway<RG.SVG.TRIG.HALFPI){halign='left';valign='bottom';}else if(angles[i].halfway>RG.SVG.TRIG.HALFPI&&angles[i].halfway<RG.SVG.TRIG.PI){halign='left';valign='top';}else if(angles[i].halfway>RG.SVG.TRIG.PI&&angles[i].halfway<(RG.SVG.TRIG.HALFPI+RG.SVG.TRIG.PI)){halign='right';valign='top';}else if(angles[i].halfway>(RG.SVG.TRIG.HALFPI+RG.SVG.TRIG.PI)&&angles[i].halfway<RG.SVG.TRIG.TWOPI){halign='right';valign='top';}
28
+ RG.SVG.text({object:this,parent:this.svg.all,text:typeof labels[i]==='string'?labels[i]:'',font:prop.textFont,size:prop.textSize,x:x,y:y,valign:valign,halign:halign,bold:prop.textBold,italic:prop.textItalic,color:prop.textColor});}};this.drawIngraphLabels=function()
29
+ {if(prop.labelsIngraph){for(var i=0;i<this.angles.length;++i){var halign=prop.labelsIngraphHalign||'center',valign=prop.labelsIngraphValign||'center',font=prop.labelsIngraphFont||prop.textFont,size=prop.labelsIngraphSize||prop.textSize,italic=typeof prop.labelsIngraphItalic==='boolean'?prop.labelsIngraphItalic:prop.textItalic,bold=typeof prop.labelsIngraphBold==='boolean'?prop.labelsIngraphBold:prop.textBold,color=prop.labelsIngraphColor||prop.textColor,bgcolor=prop.labelsIngraphBackground||'transparent',decimals=prop.labelsIngraphDecimals||0,padding=typeof prop.labelsIngraphBackground==='string'?3:0;var xy=RG.SVG.TRIG.getRadiusEndPoint({angle:this.angles[i].halfway-RG.SVG.TRIG.HALFPI,r:this.angles[i].radius*(typeof prop.labelsIngraphRadiusPos==='number'?prop.labelsIngraphRadiusPos:0.5)});if(typeof prop.labelsIngraphSpecific==='object'&&prop.labelsIngraphSpecific){if(typeof prop.labelsIngraphSpecific[i]==='string'){var str=prop.labelsIngraphSpecific[i];}else{var str='';}}else{if(typeof prop.labelsIngraphFormatter==='function'){var str=prop.labelsIngraphFormatter({object:this,number:this.data[i].toFixed(decimals)})}else{var str=RG.SVG.numberFormat({prepend:prop.labelsIngraphUnitsPre,append:prop.labelsIngraphUnitsPost,point:prop.labelsIngraphPoint,thousand:prop.labelsIngraphThousand,num:this.data[i].toFixed(decimals),object:this});}}
30
+ RG.SVG.text({object:this,parent:this.svg.all,x:this.angles[i].cx+xy[0],y:this.angles[i].cy+xy[1],text:str,halign:halign,valign:valign,font:font,size:size,bold:bold,italic:italic,color:color,background:bgcolor,padding:padding});}}};this.drawLabelsSticks=function()
31
+ {var labels_right=[],labels_left=[],labels_coords=[];for(var i=0;i<this.angles.length;++i){var angle=(this.angles[i].start+((this.angles[i].end-this.angles[i].start)/2))-RGraph.SVG.TRIG.HALFPI,endpoint_inner=RG.SVG.TRIG.getRadiusEndPoint({angle:angle,r:this.radius+5}),endpoint_outer=RG.SVG.TRIG.getRadiusEndPoint({angle:angle,r:this.radius+20}),explosion=[(typeof prop.exploded==='number'?prop.exploded:prop.exploded[i]),ma.cos(angle)*(typeof prop.exploded==='number'?prop.exploded:prop.exploded[i]),ma.sin(angle)*(typeof prop.exploded==='number'?prop.exploded:prop.exploded[i])];labels_coords[i]=[];var labels={};if(angle>RG.SVG.TRIG.HALFPI){var index=labels_left.length;labels_left[index]=[];labels_left[index].text=prop.labels[i];labels_left[index].halign='right';labels=labels_left;labels_coords[i].halign='right';}else{var index=labels_right.length;labels_right[index]=[];labels_right[index].text=prop.labels[i];labels_right[index].halign='right';labels=labels_right;labels_coords[i].halign='left';}
32
+ endpoint_inner[0]+=(explosion[1]||0);endpoint_inner[1]+=(explosion[2]||0);endpoint_outer[0]+=(explosion[1]||0);endpoint_outer[1]+=(explosion[2]||0);var x,y;if(labels[index].text){var stick=RG.SVG.create({svg:this.svg,parent:this.svg.all,type:'path',attr:{d:'M {1} {2} L {3} {4}'.format(this.centerx+endpoint_inner[0],this.centery+endpoint_inner[1],this.centerx+endpoint_outer[0],this.centery+endpoint_outer[1]),stroke:'#999',fill:'rgba(0,0,0,0)'}});}
33
+ if(stick){labels[index].stick=stick;}
34
+ x=(this.centerx+endpoint_outer[0]+(angle>1.57?-50:50));y=(this.centery+endpoint_outer[1]);labels_coords[i].x=x;labels_coords[i].y=y;labels_coords[i].text=prop.labels[i];}
35
+ var vspace_right=(this.height-prop.gutterTop-prop.gutterBottom)/labels_right.length;var vspace_left=(this.height-prop.gutterTop-prop.gutterBottom)/labels_left.length;x=y=0;for(var i=0;i<labels_right.length;++i){if(labels_right[i]&&labels_right[i].text){x=this.centerx+this.radius+100;y=prop.gutterTop+(vspace_right*i)+(vspace_right/2);RGraph.SVG.text({object:this,parent:this.svg.all,text:typeof labels_right[i].text==='string'?labels_right[i].text:'',font:prop.textFont,size:prop.textSize,x:x,y:y,valign:'center',halign:labels_right[i].text,bold:prop.textBold,italic:prop.textItalic,color:prop.textColor});labels_right[i].stick.setAttribute('d',labels_right[i].stick.getAttribute('d')+' H {3} L {1} {2} '.format(x-5,y,this.centerx+this.radius+prop.labelsSticksHlength));}}
36
+ for(var i=0;i<labels_left.length;++i){if(labels_left[i]&&labels_left[i].text){x=this.centerx-this.radius-100;y=this.height-(prop.gutterTop+(vspace_left*i)+(vspace_left/2));RGraph.SVG.text({object:this,parent:this.svg.all,text:typeof labels_left[i].text==='string'?labels_left[i].text:'',font:prop.textFont,size:prop.textSize,x:x-7,y:y,valign:'center',halign:labels_left[i].halign,bold:prop.textBold,italic:prop.textItalic,color:prop.textColor});labels_left[i].stick.setAttribute('d',labels_left[i].stick.getAttribute('d')+' H {3} L {1} {2} '.format(x-5,y,this.centerx-this.radius-prop.labelsSticksHlength));}}};this.highlight=function(segment)
37
+ {var highlight=RG.SVG.create({svg:this.svg,parent:this.svg.all,type:'path',attr:{d:segment.getAttribute('d'),fill:prop.highlightFill,stroke:prop.highlightStroke,'stroke-width':prop.highlightLinewidth}});if(prop.tooltipsEvent==='mousemove'){highlight.addEventListener('mouseout',function(e)
38
+ {highlight.parentNode.removeChild(highlight);RG.SVG.hideTooltip();RG.SVG.REG.set('highlight',null);},false);}
39
+ RG.SVG.REG.set('highlight',highlight);};this.parseColors=function()
40
+ {if(!Object.keys(this.originalColors).length){this.originalColors={colors:RG.SVG.arrayClone(prop.colors),highlightFill:RG.SVG.arrayClone(prop.highlightFill)}}
41
+ var colors=prop.colors;if(colors){for(var i=0;i<colors.length;++i){colors[i]=RG.SVG.parseColorRadial({object:this,color:colors[i]});}}
42
+ prop.highlightFill=RG.SVG.parseColorRadial({object:this,color:prop.highlightFill});};this.roundRobin=function()
43
+ {var obj=this,opt=arguments[0]||{},data=RG.SVG.arrayClone(this.data),prop=this.properties,frame=1,frames=opt.frames||30,callback=typeof opt.callback==='function'?opt.callback:function(){},dataSum=RG.SVG.arraySum(this.data),textColor=prop.textColor,ingraph=prop.labelsIngraph;this.properties.textColor='rgba(0,0,0,0)';this.properties.labelsIngraph=false;obj.draw();angles=RG.SVG.arrayClone(obj.angles);function iterator()
44
+ {prop.roundRobinMultiplier=1/frames*frame++;for(var i=0;i<obj.angles.length;++i){var value=obj.data[i];obj.angles[i].start=angles[i].start*prop.roundRobinMultiplier;obj.angles[i].end=angles[i].end*prop.roundRobinMultiplier;var segment=((obj.angles[i].end-obj.angles[i].start)/2);var explodedX=ma.cos(obj.angles[i].start+segment-RG.SVG.TRIG.HALFPI)*(prop.exploded[i]||0);var explodedY=ma.sin(obj.angles[i].start+segment-RG.SVG.TRIG.HALFPI)*(prop.exploded[i]||0);var path=RG.SVG.TRIG.getArcPath({cx:obj.centerx+explodedX,cy:obj.centery+explodedY,r:obj.radius,start:obj.angles[i].start,end:obj.angles[i].end});if(prop.donut){var donutWidth=prop.donutWidth;var donut_path=RG.SVG.TRIG.getArcPath({cx:obj.angles[i].cx,cy:obj.angles[i].cy,r:obj.radius-donutWidth,start:obj.angles[i].end,end:obj.angles[i].start,moveto:false,anticlockwise:true});var xy=RG.SVG.TRIG.getRadiusEndPoint({angle:obj.angles[i].end-RG.SVG.TRIG.HALFPI,r:obj.radius-donutWidth});path=path
45
+ +" L {1} {2} ".format(xy[0]+obj.angles[i].cx,xy[1]+obj.angles[i].cy)
46
+ +donut_path
47
+ +" Z";}else{path=path+" L {1} {2} ".format(obj.angles[i].cx,obj.angles[i].cy)+" Z"}
48
+ path=path+" L {1} {2} Z".format(obj.centerx+explodedX,obj.centery+explodedY);if(obj.shadowNodes&&obj.shadowNodes[i]){obj.shadowNodes[i].setAttribute('d',path);}
49
+ obj.nodes[i].setAttribute('d',path);}
50
+ if(frame<=frames){RG.SVG.FX.update(iterator);}else{prop.textColor=textColor;prop.labelsIngraph=ingraph;RG.SVG.redraw(obj.svg);callback(obj);}}
51
+ iterator();return this;};this.on=function(type,func)
52
+ {if(type.substr(0,2)!=='on'){type='on'+type;}
53
+ RG.SVG.addCustomEventListener(this,type,func);return this;};this.exec=function(func)
54
+ {func(this);return this;};this.removeHighlight=function()
55
+ {var highlight=RG.SVG.REG.get('highlight');if(highlight&&highlight.parentNode){highlight.parentNode.removeChild(highlight);}
56
+ RG.SVG.REG.set('highlight',null);};for(i in conf.options){if(typeof i==='string'){this.set(i,conf.options[i]);}}};return this;})(window,document);