rgraph-rails 4.62 → 4.64

Sign up to get free protection for your applications and to get access to all the features.
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);