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,1818 +1,67 @@
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.Rose = 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
-
55
- } else {
56
-
57
- var ret = RG.SVG.commonSetter({
58
- object: this,
59
- name: name,
60
- value: value
61
- });
62
-
63
- name = ret.name;
64
- value = ret.value;
65
-
66
- this.properties[name] = value;
67
- }
68
-
69
- return this;
70
- };
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
- this.id = conf.id;
80
- this.uid = RG.SVG.createUID();
81
- this.container = document.getElementById(this.id);
82
- this.svg = RG.SVG.createSVG({container: this.container});
83
- this.isRGraph = true;
84
- this.width = Number(this.svg.getAttribute('width'));
85
- this.height = Number(this.svg.getAttribute('height'));
86
- this.data = RG.SVG.arrayClone(conf.data);
87
- this.originalData = RG.SVG.arrayClone(conf.data);
88
- this.type = 'rose';
89
- this.angles = [];
90
- this.angles2 = [];
91
- this.colorsParsed = false;
92
- this.originalColors = {};
93
- this.gradientCounter = 1;
94
- this.nodes = [];
95
- this.shadowNodes = [];
96
- this.max = 0;
97
- this.redraw = false;
98
- this.highlight_node = null;
99
-
100
- // Add this object to the ObjectRegistry
101
- RG.SVG.OR.add(this);
102
-
103
- // Set the DIV container to be inline-block
104
- this.container.style.display = 'inline-block';
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
- this.properties =
113
- {
114
- centerx: null,
115
- centery: null,
116
- radius: null,
117
-
118
- gutterLeft: 35,
119
- gutterRight: 35,
120
- gutterTop: 35,
121
- gutterBottom: 35,
122
-
123
- backgroundGrid: true,
124
- backgroundGridColor: '#ddd',
125
- backgroundGridRadialsCount: null,
126
- backgroundGridRadialsAngleOffset: 0,
127
- backgroundGridConcentricsCount: 5,
128
- backgroundGridLinewidth: 1,
129
-
130
- strokestyle: 'white',
131
- colors: [
132
- 'red', 'black', 'orange', 'green', '#6ff', '#ccc',
133
- 'pink', 'orange', 'cyan', 'maroon', 'olive', 'teal'
134
- ],
135
- colorsOpacity: 1,
136
-
137
- textColor: 'black',
138
- textFont: 'sans-serif',
139
- textSize: 12,
140
- textBold: false,
141
- textItalic: false,
142
-
143
- labels: [],
144
- labelsFont: null,
145
- labelsSize: null,
146
- labelsColor: null,
147
- labelsBold: null,
148
- labelsItalic: null,
149
- labelsRadialMargin: 10,
150
- labelsAngleOffset: 0,
151
-
152
- scaleVisible: true,
153
- scaleUnitsPre: '',
154
- scaleUnitsPost: '',
155
- scaleMax: null,
156
- scaleMin: 0,
157
- scalePoint: '.',
158
- scaleThousand: ',',
159
- scaleRound: false,
160
- scaleDecimals: 0,
161
- scaleFormatter: null,
162
- scaleBold: null,
163
- scaleItalic: null,
164
- scaleColor: null,
165
- scaleSize: null,
166
- scaleFont: null,
167
- scaleLabelsCount: 5,
168
-
169
- linewidth: 1,
170
-
171
- tooltips: null,
172
- tooltipsOverride: null,
173
- tooltipsEffect: 'fade',
174
- tooltipsCssClass: 'RGraph_tooltip',
175
- tooltipsEvent: 'click',
176
-
177
- highlightStroke: 'rgba(0,0,0,0)',
178
- highlightFill: 'rgba(255,255,255,0.7)',
179
- highlightLinewidth: 1,
180
-
181
- title: '',
182
- titleSize: 16,
183
- titleX: null,
184
- titleY: null,
185
- titleHalign: 'center',
186
- titleValign: null,
187
- titleColor: 'black',
188
- titleFont: null,
189
- titleBold: false,
190
- titleItalic: false,
191
-
192
- titleSubtitle: '',
193
- titleSubtitleSize: 10,
194
- titleSubtitleX: null,
195
- titleSubtitleY: null,
196
- titleSubtitleHalign: 'center',
197
- titleSubtitleValign: null,
198
- titleSubtitleColor: '#aaa',
199
- titleSubtitleFont: null,
200
- titleSubtitleBold: false,
201
- titleSubtitleItalic: false,
202
-
203
- shadow: false,
204
- shadowOffsetx: 2,
205
- shadowOffsety: 2,
206
- shadowBlur: 2,
207
- shadowOpacity: 0.25,
208
-
209
- margin: 0,
210
- exploded: 0,
211
-
212
-
213
- key: null,
214
- keyColors: null,
215
- keyOffsetx: 0,
216
- keyOffsety: 0,
217
- keyTextOffsetx: 0,
218
- keyTextOffsety: -1,
219
- keyTextSize: null,
220
- keyTextBold: null,
221
- keyTextItalic: null,
222
-
223
- attribution: true,
224
- attributionX: null,
225
- attributionY: null,
226
- attributionHref: null,// Default is set in RGraph.svg.common.core.js
227
- attributionHalign: 'right',
228
- attributionValign: 'bottom',
229
- attributionSize: 7,
230
- attributionColor: 'gray',
231
- attributionFont: 'sans-serif',
232
- attributionItalic: false,
233
- attributionBold: false,
234
-
235
- segmentsAngleOffset: 0,
236
- variant: 'normal'
237
- };
238
-
239
-
240
-
241
-
242
-
243
-
244
- /**
245
- * "Decorate" the object with the generic effects if the effects library has been included
246
- */
247
- if (RG.SVG.FX && typeof RG.SVG.FX.decorate === 'function') {
248
- RG.SVG.FX.decorate(this);
249
- }
250
-
251
-
252
-
253
-
254
- var prop = this.properties;
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
- //
264
- // The draw method draws the Bar chart
265
- //
266
- this.draw = function ()
267
- {
268
- // Fire the beforedraw event
269
- RG.SVG.fireCustomEvent(this, 'onbeforedraw');
270
-
271
-
272
-
273
- // Reset the data back to the original values
274
- this.data = RG.SVG.arrayClone(this.originalData);
275
-
276
-
277
-
278
- // Reset the angles array to stop it growing
279
- this.angles = [];
280
-
281
-
282
- // Create the arrays in the angles2 array based on
283
- // the data that we've been passed
284
- for (var i=0; i<this.data.length; ++i) {
285
- this.angles2[i] = [];
286
- }
287
-
288
-
289
-
290
-
291
-
292
- // Create the defs tag if necessary
293
- RG.SVG.createDefs(this);
294
-
295
-
296
-
297
-
298
- this.graphWidth = this.width - prop.gutterLeft - prop.gutterRight;
299
- this.graphHeight = this.height - prop.gutterTop - prop.gutterBottom;
300
-
301
-
302
-
303
- // Work out the center point
304
- this.centerx = (this.graphWidth / 2) + prop.gutterLeft;
305
- this.centery = (this.graphHeight / 2) + prop.gutterTop;
306
- this.radius = ma.min(this.graphWidth, this.graphHeight) / 2;
307
-
308
-
309
-
310
- // Allow the user to override the calculated centerx/y/radius
311
- this.centerx = typeof prop.centerx === 'number' ? prop.centerx : this.centerx;
312
- this.centery = typeof prop.centery === 'number' ? prop.centery : this.centery;
313
- this.radius = typeof prop.radius === 'number' ? prop.radius : this.radius;
314
-
315
- //
316
- // Allow the centerx/centery/radius to be a plus/minus
317
- //
318
- if (typeof prop.radius === 'string' && prop.radius.match(/^\+|-\d+$/) ) this.radius += parseFloat(prop.radius);
319
- if (typeof prop.centerx === 'string' && prop.centerx.match(/^\+|-\d+$/) ) this.centery += parseFloat(prop.centerx);
320
- if (typeof prop.centery === 'string' && prop.centery.match(/^\+|-\d+$/) ) this.centerx += parseFloat(prop.centery);
321
-
322
-
323
-
324
-
325
-
326
- //
327
- // Convert the nargin from strings to a number
328
- //
329
- if (typeof prop.margin === 'string' && prop.margin.match(/([0-9.]+)deg/)) {
330
- prop.margin = RegExp.$1 / (180 / ma.PI);
331
- }
332
-
333
-
334
-
335
-
336
- /**
337
- * Add the data to the .originalData array and work out the max value
338
- *
339
- * 2/5/14 Now also use this loop to ensure that the data pieces
340
- * are numbers
341
- *
342
- * **Is this necessary **
343
- */
344
- //if (RG.SVG.isArray(this.data) && (typeof this.data[0] === 'number' || typeof this.data[0] === 'string')) {
345
- // this.data = [this.data];
346
- //}
347
-
348
- // Convert strings to numbers
349
- for (var i=0; i<this.data.length; ++i) {
350
- if (typeof this.data[i] === 'object') {
351
- for (var j=0; j<this.data[i].length; ++j) {
352
- if (typeof this.data[i][j] === 'string') {
353
- this.data[i][j] = RG.SVG.stringsToNumbers(this.data[i][j]);
354
- }
355
- }
356
- } else if (typeof this.data[i] === 'string') {
357
- this.data[i] = RG.SVG.stringsToNumbers(this.data[i]);
358
- }
359
- }
360
-
361
-
362
-
363
-
364
-
365
-
366
-
367
-
368
-
369
- // Get the max value. This sets the maximum value on the
370
- // this.max variable
371
- this.getMaxValue();
372
-
373
-
374
-
375
-
376
-
377
-
378
-
379
- // Parse the colors for gradients
380
- RG.SVG.resetColorsToOriginalValues({object:this});
381
- this.parseColors();
382
-
383
- //
384
- // Get the scale
385
- //
386
-
387
- this.scale = RG.SVG.getScale({
388
- object: this,
389
- numlabels: typeof prop.scaleLabelsCount === 'number' ? prop.scaleLabelsCount : prop.backgroundGridConcentricCount,
390
- unitsPre: prop.scaleUnitsPre,
391
- unitsPost: prop.scaleUnitsPost,
392
- max: typeof prop.scaleMax === 'number' ? prop.scaleMax : this.max,
393
- min: prop.scaleMin,
394
- point: prop.scalePoint,
395
- round: prop.scaleRound,
396
- thousand: prop.scaleThousand,
397
- decimals: prop.scaleDecimals,
398
- strict: typeof prop.scaleMax === 'number',
399
- formatter: prop.scaleFormatter
400
- });
401
-
402
- this.max = this.scale.max;
403
-
404
-
405
-
406
- // Draw the background 'grid'
407
- this.drawBackground();
408
-
409
-
410
-
411
- // Draw the chart
412
- this.drawRose();
413
-
414
-
415
-
416
-
417
-
418
-
419
- // Draw the labels
420
- this.drawLabels();
421
-
422
-
423
-
424
- // Draw the title and subtitle
425
- RG.SVG.drawTitle(this);
426
-
427
-
428
-
429
-
430
-
431
-
432
- // Draw the key
433
- if (typeof prop.key !== null && RG.SVG.drawKey) {
434
- RG.SVG.drawKey(this);
435
- } else if (!RGraph.SVG.isNull(prop.key)) {
436
- alert('The drawKey() function does not exist - have you forgotten to include the key library?');
437
- }
438
-
439
-
440
-
441
-
442
-
443
- // Add the attribution link. If you're adding this elsewhere on your page/site
444
- // and you don't want it displayed then there are options available to not
445
- // show it.
446
- RG.SVG.attribution(this);
447
-
448
- // Create the shadow definition if needed
449
- if (prop.shadow) {
450
- RG.SVG.setShadow({
451
- object: this,
452
- offsetx: prop.shadowOffsetx,
453
- offsety: prop.shadowOffsety,
454
- blur: prop.shadowBlur,
455
- opacity: prop.shadowOpacity,
456
- id: 'dropShadow'
457
- });
458
- }
459
-
460
-
461
-
462
- // Add the event listener that clears the highlight if
463
- // there is any. Must be MOUSEDOWN (ie before the click event)
464
- var obj = this;
465
- doc.body.addEventListener('mousedown', function (e)
466
- {
467
- obj.hideHighlight(obj);
468
- }, false);
469
-
470
-
471
-
472
- // Fire the draw event
473
- RG.SVG.fireCustomEvent(this, 'ondraw');
474
-
475
-
476
-
477
- return this;
478
- };
479
-
480
-
481
-
482
-
483
-
484
-
485
-
486
-
487
- //
488
- // Draw the background grid
489
- //
490
- this.drawBackground = function ()
491
- {
492
- if (prop.backgroundGrid) {
493
-
494
- // Create the background grid group tag
495
- var grid = RG.SVG.create({
496
- svg: this.svg,
497
- parent: this.svg.all,
498
- type: 'g',
499
- attr: {
500
- className: 'rgraph_radar_grid',
501
- fill: 'rgba(0,0,0,0)',
502
- stroke: prop.backgroundGridColor
503
- }
504
- });
505
-
506
- // Draw the concentric "rings" grid lines that are
507
- // arranged around the centerx/centery along with
508
- // the radials that eminate from the center outwards
509
-
510
- var origin = 0 - (RG.SVG.TRIG.PI / 2),
511
- radials = (typeof prop.backgroundGridRadialsCount === 'number' ? prop.backgroundGridRadialsCount : this.data.length),
512
- concentrics = prop.backgroundGridConcentricsCount,
513
- step = RG.SVG.TRIG.TWOPI / radials;
514
-
515
-
516
-
517
-
518
-
519
- // First draw the radial lines that emanate from the
520
- // center outwards
521
- if (radials > 0) {
522
- // This draws the radials for the non-equi-angular ONLY
523
- if (prop.variant === 'non-equi-angular') {
524
-
525
-
526
-
527
-
528
-
529
-
530
-
531
-
532
-
533
-
534
-
535
-
536
-
537
-
538
- // Number of radials always matches the number of data pieces
539
- var radials = this.data.length;
540
-
541
- // Work out the total of the second part of each data bit
542
- for (var i=0,total=0; i<this.data.length; ++i) {
543
- total += this.data[i][1];
544
- }
545
-
546
- for (var i=0,sum=0; i<this.data.length; ++i) {
547
-
548
- var coords = RG.SVG.TRIG.toCartesian({
549
- cx: this.centerx,
550
- cy: this.centery,
551
- r: this.radius,
552
- angle: origin + ( (sum / total) * RG.SVG.TRIG.TWOPI) + prop.backgroundGridRadialsAngleOffset
553
- });
554
-
555
- var str = 'M {1} {2} L {3} {4}'.format(
556
- this.centerx,
557
- this.centery,
558
- coords.x,
559
- coords.y
560
- );
561
-
562
- RG.SVG.create({
563
- svg: this.svg,
564
- type: 'path',
565
- parent: grid,
566
- attr: {
567
- d: str,
568
- stroke: prop.backgroundGridColor,
569
- 'stroke-width': prop.backgroundGridLinewidth
570
- }
571
- });
572
-
573
- sum += this.data[i][1];
574
- }
575
-
576
-
577
-
578
-
579
-
580
-
581
-
582
-
583
-
584
-
585
-
586
-
587
- // This draws the radials for normal and STACKED Rose charts
588
- } else {
589
- for (var i=0,len=radials; i<len; ++i) {
590
-
591
- var coords = RG.SVG.TRIG.toCartesian({
592
- cx: this.centerx,
593
- cy: this.centery,
594
- r: this.radius,
595
- angle: origin + (i * step) + prop.backgroundGridRadialsAngleOffset
596
- });
597
-
598
- var str = 'M {1} {2} L {3} {4}'.format(
599
- this.centerx,
600
- this.centery,
601
- coords.x,
602
- coords.y
603
- );
604
-
605
- RG.SVG.create({
606
- svg: this.svg,
607
- type: 'path',
608
- parent: grid,
609
- attr: {
610
- d: str,
611
- stroke: prop.backgroundGridColor,
612
- 'stroke-width': prop.backgroundGridLinewidth
613
- }
614
- });
615
- }
616
- }
617
- }
618
-
619
-
620
-
621
-
622
-
623
- // Draw the concentrics
624
- if (concentrics > 0) {
625
-
626
- for (var j=1; j<=concentrics; j++) {
627
-
628
- // Add circle to the scene
629
- RG.SVG.create({
630
- svg: this.svg,
631
- type: 'circle',
632
- parent: grid,
633
- attr: {
634
- cx: this.centerx,
635
- cy: this.centery,
636
- r: this.radius * (j/concentrics),
637
- fill: 'transparent',
638
- stroke: prop.backgroundGridColor,
639
- 'stroke-width': prop.backgroundGridLinewidth
640
- }
641
- });
642
- }
643
- }
644
- }
645
- };
646
-
647
-
648
-
649
-
650
-
651
-
652
-
653
-
654
- //
655
- // Draws the radar
656
- //
657
- this.drawRose = function (opt)
658
- {
659
- // Jump to another function if we're drawing a non-equi-angular chart
660
- if (prop.variant === 'non-equi-angular') {
661
- return this.drawRoseNonEquiAngular(opt);
662
- }
663
-
664
-
665
-
666
-
667
-
668
-
669
- var radians = RG.SVG.TRIG.TWOPI / this.data.length;
670
-
671
- var group = RG.SVG.create({
672
- svg: this.svg,
673
- type:'g',
674
- parent: this.svg.all,
675
- attr: {
676
- id: 'rgraph_rose_segments_' + this.id
677
- }
678
- });
679
-
680
-
681
- // Now loop thru the data
682
- for (var i=0,seq=0; i<this.data.length; ++i,++seq) {
683
-
684
- var radius = (this.data[i] / this.scale.max) * this.radius,
685
- start = (i / this.data.length) * RG.SVG.TRIG.TWOPI,
686
- end = ((i / this.data.length) * RG.SVG.TRIG.TWOPI) + radians;
687
-
688
- // Get the exploded distance
689
- var explosion = this.getExploded({
690
- index: i,
691
- start: start - RG.SVG.TRIG.HALFPI,
692
- end: end - RG.SVG.TRIG.HALFPI
693
- });
694
-
695
-
696
-
697
-
698
-
699
-
700
-
701
-
702
-
703
-
704
-
705
-
706
-
707
-
708
-
709
-
710
-
711
-
712
-
713
- // Is the data piece an array or a number?
714
- if (typeof this.data[i] === 'object' && !RG.SVG.isNull(this.data[i])) {
715
-
716
- // Create a group for the parts of this segment
717
- var segment_group = RG.SVG.create({
718
- svg: this.svg,
719
- type: 'g',
720
- parent: group,
721
- attr: {
722
- id: 'rose_' + this.id + '_segment_group_' + i
723
- }
724
- });
725
-
726
- for (var j=0,sum=0,accRadius=0; j<this.data[i].length; ++j,++seq) {
727
-
728
- sum += this.data[i][j];
729
-
730
- var radius = (sum / this.scale.max) * this.radius;
731
-
732
- // This (I think is the OUTER curve in the segment
733
- var arcPath = RG.SVG.TRIG.getArcPath2({
734
- cx: this.centerx + explosion[0],
735
- cy: this.centery + explosion[1],
736
- r: radius,
737
- start: start + prop.margin + prop.segmentsAngleOffset,
738
- end: end - prop.margin + prop.segmentsAngleOffset,
739
- anticlockwise: false
740
- });
741
-
742
- // The inner most segment
743
- if (j === 0) {
744
- arcPath = '{1} z'.format(
745
- arcPath
746
- );
747
- } else {
748
-
749
- var arcPath2 = RG.SVG.TRIG.getArcPath2({
750
- cx: this.centerx + explosion[0],
751
- cy: this.centery + explosion[1],
752
- r: prevRadius,
753
- start: end - prop.margin + prop.segmentsAngleOffset,
754
- end: start + prop.margin + prop.segmentsAngleOffset,
755
- anticlockwise: true
756
- });
757
- arcPath = '{1} L {2} {3} {4}'.format(
758
- arcPath,
759
- this.centerx + explosion[0],
760
- this.centery + explosion[1],
761
- arcPath2
762
- );
763
- }
764
-
765
- var path = RG.SVG.create({
766
- svg: this.svg,
767
- type: 'path',
768
- parent: segment_group,
769
- attr: {
770
- d: arcPath,
771
- fill: prop.colorsSequential ? prop.colors[seq] : prop.colors[j],
772
- 'fill-opacity': prop.colorsOpacity,
773
- stroke: prop.strokestyle,
774
- 'stroke-width': prop.linewidth,
775
-
776
- 'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[seq] : '',
777
- 'data-index': i,
778
- 'data-centerx': this.centerx + explosion[0],
779
- 'data-centery': this.centery + explosion[1],
780
- 'data-group': i,
781
- 'data-subindex': j,
782
- 'data-value': this.data[i][j],
783
- 'data-start-angle': start,
784
- 'data-end-angle': end,
785
- 'data-radius': radius,
786
- 'data-radius-inner': typeof prevRadius === 'number' ? prevRadius : 0,
787
- 'data-sequential-index': seq
788
- }
789
- });
790
-
791
-
792
- // Install the tooltip listener
793
- if (prop.tooltips && prop.tooltips[seq]) {
794
-
795
- // Make the tooltipsEvent default to click
796
- if (prop.tooltipsEvent !== 'mousemove') {
797
- prop.tooltipsEvent = 'click';
798
- }
799
-
800
- (function (index, group, seq, obj)
801
- {
802
- path.addEventListener(prop.tooltipsEvent, function (e)
803
- {
804
- obj.removeHighlight();
805
-
806
- // Show the tooltip
807
- RG.SVG.tooltip({
808
- object: obj,
809
- group: group,
810
- index: index,
811
- sequentialIndex: seq,
812
- text: prop.tooltips[seq],
813
- event: e
814
- });
815
-
816
- // Highlight the rect that has been clicked on
817
- obj.highlight(e.target);
818
-
819
- var highlight = RG.SVG.REG.get('highlight');
820
-
821
- if (prop.tooltipsEvent === 'mousemove') {
822
- highlight.style.cursor = 'pointer';
823
- }
824
-
825
- }, false);
826
-
827
- // Install the event listener that changes the
828
- // cursor if necessary
829
- if (prop.tooltipsEvent === 'click') {
830
- path.addEventListener('mousemove', function (e)
831
- {
832
- e.target.style.cursor = 'pointer';
833
- }, false);
834
- }
835
-
836
- }(j, i, seq, this));
837
- }
838
-
839
- // Add the segment to the angles and angles2 array
840
- this.angles.push({
841
- object: path,
842
- index: seq,
843
- cx: this.centerx + explosion[0],
844
- cy: this.centery + explosion[1],
845
- start: start,
846
- end: end,
847
- radius: radius,
848
- 'radius-inner': prevRadius,
849
- value: this.data[i][j]
850
- });
851
-
852
- this.angles2[i].push({
853
- object: path,
854
- index: seq,
855
- cx: this.centerx + explosion[0],
856
- cy: this.centery + explosion[1],
857
- start: start,
858
- end: end,
859
- radius: radius,
860
- 'radius-inner': prevRadius,
861
- value: this.data[i][j]
862
- });
863
-
864
- var prevRadius = radius;
865
- }
866
-
867
-
868
-
869
-
870
-
871
-
872
-
873
-
874
-
875
-
876
- seq--;
877
-
878
-
879
-
880
-
881
-
882
-
883
-
884
-
885
-
886
-
887
-
888
-
889
-
890
- // A regular number
891
- } else {
892
-
893
- var arcPath = RG.SVG.TRIG.getArcPath2({
894
- cx: this.centerx + explosion[0],
895
- cy: this.centery + explosion[1],
896
- r: radius,
897
- start: start + prop.margin + prop.segmentsAngleOffset,
898
- end: end - prop.margin + prop.segmentsAngleOffset,
899
- anticlockwise: false
900
- });
901
-
902
- var path = RG.SVG.create({
903
- svg: this.svg,
904
- type: 'path',
905
- parent: group,
906
- attr: {
907
- d: '{1} z'.format(
908
- arcPath
909
- ),
910
- fill: prop.colorsSequential ? prop.colors[i] : prop.colors[0],
911
- 'fill-opacity': prop.colorsOpacity,
912
- stroke: prop.strokestyle,
913
- 'stroke-width': prop.linewidth,
914
-
915
- 'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[i] : '',
916
- 'data-index': i,
917
- 'data-centerx': this.centerx + explosion[0],
918
- 'data-centery': this.centery + explosion[1],
919
- 'data-value': this.data[i],
920
- 'data-start-angle': start,
921
- 'data-end-angle': end,
922
- 'data-radius': radius,
923
- 'data-sequential': seq
924
- }
925
- });
926
-
927
- // Add the segment to the angles array
928
- this.angles.push({
929
- object: path,
930
- index: i,
931
- cx: this.centerx + explosion[0],
932
- cy: this.centery + explosion[1],
933
- start: start,
934
- end: end,
935
- radius: radius,
936
- value: this.data[i]
937
- });
938
-
939
- this.angles2[i].push({
940
- object: path,
941
- index: seq,
942
- cx: this.centerx + explosion[0],
943
- cy: this.centery + explosion[1],
944
- start: start,
945
- end: end,
946
- radius: radius,
947
- 'radius-inner': prevRadius,
948
- value: this.data[i][j]
949
- });
950
-
951
-
952
-
953
-
954
- if (prop.tooltips && prop.tooltips[i]) {
955
-
956
- // Make the tooltipsEvent default to click
957
- if (prop.tooltipsEvent !== 'mousemove') {
958
- prop.tooltipsEvent = 'click';
959
- }
960
-
961
- (function (index, obj)
962
- {
963
- path.addEventListener(prop.tooltipsEvent, function (e)
964
- {
965
- obj.removeHighlight();
966
-
967
- // Show the tooltip
968
- RG.SVG.tooltip({
969
- object: obj,
970
- index: index,
971
- group: index,
972
- sequentialIndex: index,
973
- text: prop.tooltips[index],
974
- event: e
975
- });
976
-
977
- // Highlight the rect that has been clicked on
978
- obj.highlight(e.target);
979
-
980
- var highlight = RG.SVG.REG.get('highlight');
981
-
982
- if (prop.tooltipsEvent === 'mousemove') {
983
- highlight.style.cursor = 'pointer';
984
- }
985
-
986
- }, false);
987
-
988
- // Install the event listener that changes the
989
- // cursor if necessary
990
- if (prop.tooltipsEvent === 'click') {
991
- path.addEventListener('mousemove', function (e)
992
- {
993
- e.target.style.cursor = 'pointer';
994
- }, false);
995
- }
996
-
997
- }(i, this));
998
- }
999
- }
1000
- }
1001
- };
1002
-
1003
-
1004
-
1005
-
1006
-
1007
-
1008
-
1009
-
1010
- //
1011
- // Draws the radar, but only the non-equi-angular variant
1012
- //
1013
- this.drawRoseNonEquiAngular = function (opt)
1014
- {
1015
- var group = RG.SVG.create({
1016
- svg: this.svg,
1017
- type:'g',
1018
- parent: this.svg.all,
1019
- attr: {
1020
- id: 'rgraph_rose_segments_' + this.id
1021
- }
1022
- });
1023
-
1024
- //Loop through the data summing the second data-pieces
1025
- for (var i=0,total=0; i<this.data.length; ++i) {
1026
- total += parseFloat(this.data[i][1]);
1027
- }
1028
-
1029
-
1030
-
1031
-
1032
-
1033
-
1034
-
1035
-
1036
-
1037
-
1038
-
1039
- // The initial angles
1040
- var start = 0;
1041
-
1042
-
1043
-
1044
-
1045
- // Now loop thru the data
1046
- for (var i=0,seq=0; i<this.data.length; ++i,++seq) {
1047
-
1048
- var radians = (this.data[i][1] / total) * RG.SVG.TRIG.TWOPI,
1049
- end = start + radians;
1050
-
1051
- // Get the exploded distance
1052
- var explosion = this.getExploded({
1053
- index: i,
1054
- start: start - RG.SVG.TRIG.HALFPI,
1055
- end: end - RG.SVG.TRIG.HALFPI
1056
- });
1057
-
1058
-
1059
-
1060
-
1061
-
1062
-
1063
-
1064
-
1065
-
1066
-
1067
-
1068
-
1069
-
1070
-
1071
-
1072
- // A stacked non-equi-angular segment
1073
- if (typeof this.data[i][0] === 'object' && !RG.SVG.isNull(this.data[i][0])) {
1074
-
1075
-
1076
-
1077
- // Loop thru the set of values for this segment
1078
- for (var j=0,sum=0; j<this.data[i][0].length; ++j,++seq) {
1079
-
1080
- sum += this.data[i][0][j];
1081
-
1082
- // First segment in the stack or not?
1083
- if (j === 0) {
1084
-
1085
- var prevRadius = 0,
1086
- radius = (sum / this.scale.max) * this.radius;
1087
-
1088
- var arcPath = RG.SVG.TRIG.getArcPath2({
1089
- cx: this.centerx + explosion[0],
1090
- cy: this.centery + explosion[1],
1091
- r: radius,
1092
- start: start + prop.margin + prop.segmentsAngleOffset,
1093
- end: end - prop.margin + prop.segmentsAngleOffset,
1094
- anticlockwise: false
1095
- });
1096
-
1097
- var arcPath2 = '';
1098
-
1099
- } else {
1100
-
1101
- var prevRadius = radius, // The previous iterations radius
1102
- radius = (sum / this.scale.max) * this.radius;
1103
-
1104
- var arcPath = RG.SVG.TRIG.getArcPath2({
1105
- cx: this.centerx + explosion[0],
1106
- cy: this.centery + explosion[1],
1107
- r: radius,
1108
- start: start + prop.margin + prop.segmentsAngleOffset,
1109
- end: end - prop.margin + prop.segmentsAngleOffset,
1110
- anticlockwise: false
1111
- });
1112
-
1113
- var arcPath2 = RG.SVG.TRIG.getArcPath2({
1114
- cx: this.centerx + explosion[0],
1115
- cy: this.centery + explosion[1],
1116
- r: prevRadius,
1117
- start: end - prop.margin + prop.segmentsAngleOffset,
1118
- end: start + prop.margin + prop.segmentsAngleOffset,
1119
- anticlockwise: true
1120
- });
1121
- }
1122
-
1123
- var path = RG.SVG.create({
1124
- svg: this.svg,
1125
- type: 'path',
1126
- parent: group,
1127
- attr: {
1128
- d: '{1} {2} z'.format(
1129
- arcPath,
1130
- arcPath2
1131
- ),
1132
- fill: prop.colorsSequential ? prop.colors[seq] : prop.colors[j],
1133
- 'fill-opacity': prop.colorsOpacity,
1134
- stroke: prop.strokestyle,
1135
- 'stroke-width': prop.linewidth,
1136
- 'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[i] : '',
1137
- 'data-centerx': this.centerx + explosion[0],
1138
- 'data-centery': this.centery + explosion[1],
1139
- 'data-index': '[{1},{2}]'.format(i, j),
1140
- 'data-value': this.data[i][0][j],
1141
- 'data-start-angle': start,
1142
- 'data-end-angle': end,
1143
- 'data-radius': radius,
1144
- 'data-radius-inner': prevRadius,
1145
- 'data-sequential': seq
1146
- }
1147
- });
1148
-
1149
-
1150
-
1151
- // Add the segment to the angles array
1152
- this.angles.push({
1153
- object: path,
1154
- index: i,
1155
- cx: this.centerx + explosion[0],
1156
- cy: this.centery + explosion[1],
1157
- start: start,
1158
- end: end,
1159
- radius: radius,
1160
- 'radius-inner': prevRadius,
1161
- value: this.data[i][0]
1162
- });
1163
-
1164
- this.angles2[i].push({
1165
- object: path,
1166
- index: seq,
1167
- cx: this.centerx + explosion[0],
1168
- cy: this.centery + explosion[1],
1169
- start: start,
1170
- end: end,
1171
- radius: radius,
1172
- 'radius-inner': prevRadius,
1173
- value: this.data[i][j]
1174
- });
1175
-
1176
-
1177
-
1178
-
1179
- // Install tooltips listeners
1180
- if (prop.tooltips && prop.tooltips[seq]) {
1181
-
1182
- // Make the tooltipsEvent default to click
1183
- if (prop.tooltipsEvent !== 'mousemove') {
1184
- prop.tooltipsEvent = 'click';
1185
- }
1186
-
1187
- (function (index,group,seq,obj)
1188
- {
1189
- path.addEventListener(prop.tooltipsEvent, function (e)
1190
- {
1191
- obj.removeHighlight();
1192
-
1193
- // Show the tooltip
1194
- RG.SVG.tooltip({
1195
- object: obj,
1196
- index: index,
1197
- group: group,
1198
- sequentialIndex: seq,
1199
- text: prop.tooltips[seq],
1200
- event: e
1201
- });
1202
-
1203
- // Highlight the rect that has been clicked on
1204
- obj.highlight(e.target);
1205
-
1206
- var highlight = RG.SVG.REG.get('highlight');
1207
-
1208
- if (prop.tooltipsEvent === 'mousemove') {
1209
- highlight.style.cursor = 'pointer';
1210
- }
1211
-
1212
- }, false);
1213
-
1214
- // Install the event listener that changes the
1215
- // cursor if necessary
1216
- if (prop.tooltipsEvent === 'click') {
1217
- path.addEventListener('mousemove', function (e)
1218
- {
1219
- e.target.style.cursor = 'pointer';
1220
- }, false);
1221
- }
1222
-
1223
- }(j, i, seq, this));
1224
- }
1225
- var prevRadius = radius;
1226
- }
1227
- seq--
1228
-
1229
-
1230
-
1231
-
1232
-
1233
-
1234
-
1235
-
1236
-
1237
-
1238
-
1239
-
1240
-
1241
-
1242
-
1243
-
1244
-
1245
-
1246
-
1247
-
1248
- // A regular non-equi-angular segment
1249
- } else {
1250
- var radius = (this.data[i][0] / this.scale.max) * this.radius;
1251
-
1252
- var arcPath = RG.SVG.TRIG.getArcPath2({
1253
- cx: this.centerx + explosion[0],
1254
- cy: this.centery + explosion[1],
1255
- r: radius,
1256
- start: start + prop.margin + prop.segmentsAngleOffset,
1257
- end: end - prop.margin + prop.segmentsAngleOffset,
1258
- anticlockwise: false
1259
- });
1260
-
1261
- var path = RG.SVG.create({
1262
- svg: this.svg,
1263
- type: 'path',
1264
- parent: group,
1265
- attr: {
1266
- d: '{1} z'.format(
1267
- arcPath
1268
- ),
1269
- fill: prop.colorsSequential ? prop.colors[i] : prop.colors[0],
1270
- 'fill-opacity': prop.colorsOpacity,
1271
- stroke: prop.strokestyle,
1272
- 'stroke-width': prop.linewidth,
1273
-
1274
- 'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[i] : '',
1275
- 'data-centerx': this.centerx + explosion[0],
1276
- 'data-centery': this.centery + explosion[1],
1277
- 'data-index': i,
1278
- 'data-value': this.data[i],
1279
- 'data-start-angle': start,
1280
- 'data-end-angle': end,
1281
- 'data-radius': radius,
1282
- 'data-sequential': seq
1283
- }
1284
- });
1285
-
1286
- // Add the segment to the angles array
1287
- this.angles.push({
1288
- object: path,
1289
- index: i,
1290
- cx: this.centerx + explosion[0],
1291
- cy: this.centery + explosion[1],
1292
- start: start,
1293
- end: end,
1294
- radius: radius,
1295
- value: this.data[i][0]
1296
- });
1297
-
1298
- this.angles2[i].push({
1299
- object: path,
1300
- index: seq,
1301
- cx: this.centerx + explosion[0],
1302
- cy: this.centery + explosion[1],
1303
- start: start,
1304
- end: end,
1305
- radius: radius,
1306
- 'radius-inner': 0,
1307
- value: this.data[i][j]
1308
- });
1309
-
1310
-
1311
-
1312
-
1313
- if (prop.tooltips && prop.tooltips[i]) {
1314
-
1315
- // Make the tooltipsEvent default to click
1316
- if (prop.tooltipsEvent !== 'mousemove') {
1317
- prop.tooltipsEvent = 'click';
1318
- }
1319
-
1320
- (function (index, group, seq, obj)
1321
- {
1322
- path.addEventListener(prop.tooltipsEvent, function (e)
1323
- {
1324
- obj.removeHighlight();
1325
-
1326
- // Show the tooltip
1327
- RG.SVG.tooltip({
1328
- object: obj,
1329
- index: index,
1330
- group: index,
1331
- sequentialIndex: seq,
1332
- text: prop.tooltips[index],
1333
- event: e
1334
- });
1335
-
1336
- // Highlight the rect that has been clicked on
1337
- obj.highlight(e.target);
1338
-
1339
- var highlight = RG.SVG.REG.get('highlight');
1340
-
1341
- if (prop.tooltipsEvent === 'mousemove') {
1342
- highlight.style.cursor = 'pointer';
1343
- }
1344
-
1345
- }, false);
1346
-
1347
- // Install the event listener that changes the
1348
- // cursor if necessary
1349
- if (prop.tooltipsEvent === 'click') {
1350
- path.addEventListener('mousemove', function (e)
1351
- {
1352
- e.target.style.cursor = 'pointer';
1353
- }, false);
1354
- }
1355
-
1356
- }(i, i, seq, this));
1357
- }
1358
- }
1359
-
1360
-
1361
- // Increment the start angle for the next iteration of the loop
1362
- start += radians;
1363
- }
1364
- };
1365
-
1366
-
1367
-
1368
-
1369
-
1370
-
1371
-
1372
-
1373
- //
1374
- // Redraws the chart if required
1375
- //
1376
- this.redrawRose = function ()
1377
- {
1378
- };
1379
-
1380
-
1381
-
1382
-
1383
-
1384
-
1385
-
1386
-
1387
- //
1388
- // Draw the labels
1389
- //
1390
- this.drawLabels = function ()
1391
- {
1392
- // Draw the scale if required
1393
- if (prop.scaleVisible) {
1394
- for (var i=0; i<this.scale.labels.length; ++i) {
1395
-
1396
- var x = this.centerx;
1397
- var y = this.centery - (this.radius / this.scale.labels.length * (i+1) );
1398
-
1399
-
1400
- RG.SVG.text({
1401
- object: this,
1402
- svg: this.svg,
1403
- parent: this.svg.all,
1404
- text: this.scale.labels[i],
1405
- size: prop.scaleSize || prop.textSize - 2,
1406
- x: x,
1407
- y: y,
1408
- halign: 'center',
1409
- valign: 'center',
1410
- background: 'rgba(255,255,255,0.7)',
1411
- padding:2,
1412
- color: prop.scaleColor || prop.textColor,
1413
- bold: typeof prop.scaleBold === 'boolean' ? prop.scaleBold : prop.textBold,
1414
- italic: typeof prop.scaleItalic === 'boolean' ? prop.scaleItalic : prop.textItalic,
1415
- font: prop.scaleFont || prop.textFont
1416
- });
1417
- }
1418
-
1419
- // Draw the zero label
1420
- var str = RG.SVG.numberFormat({
1421
- object: this,
1422
- num: this.scale.min.toFixed(prop.scaleDecimals),
1423
- prepend: prop.scaleUnitsPre,
1424
- append: prop.scaleUnitsPost,
1425
- point: prop.scalePoint,
1426
- thousand: prop.scaleThousand,
1427
- formatter: prop.scaleFormatter
1428
- });
1429
-
1430
-
1431
- RG.SVG.text({
1432
- object: this,
1433
- svg: this.svg,
1434
- parent: this.svg.all,
1435
- text: str,
1436
- size: prop.scaleSize || prop.textSize - 2,
1437
- x: this.centerx,
1438
- y: this.centery,
1439
- halign: 'center',
1440
- valign: 'center',
1441
- background: 'rgba(255,255,255,0.7)',
1442
- padding:2,
1443
- color: prop.scaleColor || prop.textColor,
1444
- bold: typeof prop.scaleBold === 'boolean' ? prop.scaleBold : prop.textBold,
1445
- italic: typeof prop.scaleItalic === 'boolean' ? prop.scaleItalic : prop.textItalic,
1446
- font: prop.scaleFont || prop.textFont
1447
- });
1448
- }
1449
-
1450
-
1451
-
1452
-
1453
-
1454
-
1455
-
1456
- // Used further down
1457
- var halign;
1458
-
1459
- // Set a default size for the labels
1460
- if (typeof prop.labelsSize !== 'number') {
1461
- prop.labelsSize = prop.textSize + 4;
1462
- }
1463
-
1464
-
1465
-
1466
- // Draw the circular labels if necessary
1467
- for (var i=0; i<prop.labels.length; ++i) {
1468
-
1469
- if (prop.variant === 'non-equi-angular') {
1470
- var angle = ((this.angles2[i][0].end - this.angles2[i][0].start) / 2) + this.angles2[i][0].start - RG.SVG.TRIG.HALFPI;
1471
- } else {
1472
- var angle = (((RG.SVG.TRIG.TWOPI / prop.labels.length)) * i) - RG.SVG.TRIG.HALFPI + prop.labelsAngleOffset + ((this.angles2[i][0].end - this.angles2[i][0].start) / 2);
1473
- }
1474
-
1475
- var endpoint = RG.SVG.TRIG.getRadiusEndPoint({
1476
- r: this.radius + prop.labelsRadialMargin,
1477
- angle: angle
1478
- });
1479
-
1480
- // Accommodate the explosion for the label
1481
- var explosion = this.getExploded({
1482
- index: i,
1483
- start: this.angles2[i][0].start - RG.SVG.TRIG.HALFPI,
1484
- end: this.angles2[i][0].end - RG.SVG.TRIG.HALFPI
1485
- });
1486
-
1487
- endpoint[0] += this.centerx + explosion[0];
1488
- endpoint[1] += this.centery + explosion[1];
1489
-
1490
-
1491
- // Do the alignment based on which quadrant the label is in
1492
- if (ma.round(endpoint[0]) > this.centerx) {
1493
- halign = 'left';
1494
- } else if (ma.round(endpoint[0]) === this.centerx) {
1495
- halign = 'center';
1496
- } else {
1497
- halign = 'right';
1498
- }
1499
-
1500
-
1501
-
1502
-
1503
-
1504
- RG.SVG.text({
1505
- object: this,
1506
- svg: this.svg,
1507
- parent: this.svg.all,
1508
- text: typeof prop.labels[i] === 'string' ? prop.labels[i] : '',
1509
- size: prop.labelsSize,
1510
- x: endpoint[0],
1511
- y: endpoint[1],
1512
- halign: halign,
1513
- valign: 'center',
1514
- background: 'rgba(255,255,255,0.7)',
1515
- padding:2,
1516
- color: prop.labelsColor || prop.textColor,
1517
- bold: typeof prop.labelsBold === 'boolean' ? prop.labelsBold : prop.textBold,
1518
- italic: typeof prop.labelsItalic === 'boolean' ? prop.labelsItalic : prop.textItalic,
1519
- font: prop.labelsFont || prop.textFont
1520
- });
1521
- }
1522
- };
1523
-
1524
-
1525
-
1526
-
1527
-
1528
-
1529
-
1530
-
1531
- /**
1532
- * This function can be used to highlight a segment on the chart
1533
- *
1534
- * @param object circle The circle to highlight
1535
- */
1536
- this.highlight = function (path)
1537
- {
1538
- var path = path.getAttribute('d');
1539
-
1540
- var highlight = RG.SVG.create({
1541
- svg: this.svg,
1542
- parent: this.svg.all,
1543
- type: 'path',
1544
- attr: {
1545
- d: path,
1546
- fill: prop.highlightFill,
1547
- stroke: prop.highlightStroke,
1548
- 'stroke-width': prop.highlightLinewidth
1549
- }
1550
- });
1551
-
1552
-
1553
- if (prop.tooltipsEvent === 'mousemove') {
1554
- highlight.addEventListener('mouseout', function (e)
1555
- {
1556
- highlight.parentNode.removeChild(highlight);
1557
- RG.SVG.hideTooltip();
1558
-
1559
- RG.SVG.REG.set('highlight', null);
1560
- }, false);
1561
- }
1562
-
1563
-
1564
- // Store the highlight rect in the registry so
1565
- // it can be cleared later
1566
- RG.SVG.REG.set('highlight', highlight);
1567
- };
1568
-
1569
-
1570
-
1571
-
1572
-
1573
-
1574
-
1575
-
1576
- /**
1577
- * This allows for easy specification of gradients
1578
- */
1579
- this.parseColors = function ()
1580
- {
1581
- // Save the original colors so that they can be restored when the canvas is reset
1582
- if (!Object.keys(this.originalColors).length) {
1583
- this.originalColors = {
1584
- colors: RG.SVG.arrayClone(prop.colors),
1585
- highlightFill: RG.SVG.arrayClone(prop.highlightFill)
1586
- }
1587
- }
1588
-
1589
-
1590
- // colors
1591
- var colors = prop.colors;
1592
-
1593
- if (colors) {
1594
- for (var i=0; i<colors.length; ++i) {
1595
- colors[i] = RG.SVG.parseColorRadial({
1596
- object: this,
1597
- color: colors[i]
1598
- });
1599
- }
1600
- }
1601
-
1602
- // Highlight fill
1603
- prop.highlightFill = RG.SVG.parseColorRadial({
1604
- object: this,
1605
- color: prop.highlightFill
1606
- });
1607
- };
1608
-
1609
-
1610
-
1611
-
1612
-
1613
-
1614
-
1615
-
1616
- //
1617
- // Get the maximum value
1618
- //
1619
- this.getMaxValue = function ()
1620
- {
1621
- var max = 0;
1622
-
1623
- if (prop.variant === 'non-equi-angular') {
1624
- for (var i=0; i<this.data.length; ++i) {
1625
- if (!RG.SVG.isNull(this.data[i])) {
1626
- if (typeof this.data[i][0] === 'number') {
1627
- max = ma.max(max, this.data[i][0]);
1628
- } else if (typeof this.data[i][0] === 'object'){
1629
- max = ma.max(max, RG.SVG.arraySum(this.data[i][0]));
1630
- }
1631
- }
1632
- }
1633
- } else {
1634
- for (var i=0; i<this.data.length; ++i) {
1635
- if (!RG.SVG.isNull(this.data[i])) {
1636
- if (typeof this.data[i] === 'number') {
1637
- max = ma.max(max, this.data[i]);
1638
- } else if (typeof this.data[i] === 'object') {
1639
- max = ma.max(max, RG.SVG.arraySum(this.data[i]));
1640
- }
1641
- }
1642
- }
1643
- }
1644
-
1645
- this.max = max;
1646
- };
1647
-
1648
-
1649
-
1650
-
1651
-
1652
-
1653
-
1654
-
1655
- //
1656
- // Gets the radius of a value
1657
- //
1658
- //@param number The value to get the radius for
1659
- //
1660
- this.getRadius = function (value)
1661
- {
1662
- return ( (value - prop.scaleMin) / (this.scale.max - prop.scaleMin) ) * this.radius;
1663
- };
1664
-
1665
-
1666
-
1667
-
1668
-
1669
-
1670
-
1671
-
1672
- //
1673
- // A roundRobin effect for the Pie chart
1674
- //
1675
- // @param object Options for the effect
1676
- // @param function An optional callback function to call when
1677
- // the effect is complete
1678
- //
1679
- this.roundRobin = function ()
1680
- {
1681
- };
1682
-
1683
-
1684
-
1685
-
1686
-
1687
-
1688
-
1689
-
1690
- /**
1691
- * Using a function to add events makes it easier to facilitate method
1692
- * chaining
1693
- *
1694
- * @param string type The type of even to add
1695
- * @param function func
1696
- */
1697
- this.on = function (type, func)
1698
- {
1699
- if (type.substr(0,2) !== 'on') {
1700
- type = 'on' + type;
1701
- }
1702
-
1703
- RG.SVG.addCustomEventListener(this, type, func);
1704
-
1705
- return this;
1706
- };
1707
-
1708
-
1709
-
1710
-
1711
-
1712
-
1713
-
1714
-
1715
- //
1716
- // Used in chaining. Runs a function there and then - not waiting for
1717
- // the events to fire (eg the onbeforedraw event)
1718
- //
1719
- // @param function func The function to execute
1720
- //
1721
- this.exec = function (func)
1722
- {
1723
- func(this);
1724
-
1725
- return this;
1726
- };
1727
-
1728
-
1729
-
1730
-
1731
-
1732
-
1733
-
1734
-
1735
- //
1736
- // Removes the tooltip highlight from the chart
1737
- //
1738
- this.removeHighlight =
1739
- this.hideHighlight = function ()
1740
- {
1741
- var highlight = RG.SVG.REG.get('highlight');
1742
-
1743
- if (highlight && this.highlight_node) {
1744
- this.highlight_node.setAttribute('fill','transparent');
1745
- this.highlight_node.setAttribute('stroke','transparent');
1746
-
1747
- RG.SVG.REG.set('highlight', null);
1748
- }
1749
- };
1750
-
1751
-
1752
-
1753
-
1754
-
1755
-
1756
-
1757
-
1758
- //
1759
- // Returns the exploded X/Y for a given explosion
1760
- //
1761
- //TODO Needs updating to current coding style, including converting
1762
- // arguments to an object
1763
- //
1764
- this.getExploded = function (opt)
1765
- {
1766
- var index = opt.index,
1767
- start = opt.start,
1768
- end = opt.end,
1769
- exploded = prop.exploded,
1770
- explodedX,
1771
- explodedY;
1772
-
1773
- /**
1774
- * Retrieve any exploded - the exploded can be an array of numbers or a single number
1775
- * (which is applied to all segments)
1776
- */
1777
- if (typeof exploded === 'object' && typeof exploded[index] === 'number') {
1778
- explodedX = ma.cos(((end - start) / 2) + start) * exploded[index];
1779
- explodedY = (ma.sin(((end - start) / 2) + start) * exploded[index]);
1780
-
1781
- } else if (typeof exploded === 'number') {
1782
- explodedX = ma.cos(((end - start) / 2) + start) * exploded;
1783
- explodedY = ma.sin(((end - start) / 2) + start) * exploded;
1784
-
1785
- } else {
1786
- explodedX = 0;
1787
- explodedY = 0;
1788
- }
1789
-
1790
- return [explodedX, explodedY];
1791
- };
1792
-
1793
-
1794
-
1795
-
1796
-
1797
-
1798
-
1799
-
1800
- //
1801
- // Set the options that the user has provided
1802
- //
1803
- for (i in conf.options) {
1804
- if (typeof i === 'string') {
1805
- this.set(i, conf.options[i]);
1806
- }
1807
- }
1808
- };
1809
-
1810
-
1811
-
1812
- return this;
1813
-
1814
-
1815
-
1816
-
1817
- // End module pattern
1818
- })(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.Rose=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=RG.SVG.arrayClone(conf.data);this.originalData=RG.SVG.arrayClone(conf.data);this.type='rose';this.angles=[];this.angles2=[];this.colorsParsed=false;this.originalColors={};this.gradientCounter=1;this.nodes=[];this.shadowNodes=[];this.max=0;this.redraw=false;this.highlight_node=null;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,backgroundGrid:true,backgroundGridColor:'#ddd',backgroundGridRadialsCount:null,backgroundGridRadialsAngleOffset:0,backgroundGridConcentricsCount:5,backgroundGridLinewidth:1,strokestyle:'white',colors:['red','black','orange','green','#6ff','#ccc','pink','orange','cyan','maroon','olive','teal'],colorsOpacity:1,textColor:'black',textFont:'sans-serif',textSize:12,textBold:false,textItalic:false,labels:[],labelsFont:null,labelsSize:null,labelsColor:null,labelsBold:null,labelsItalic:null,labelsRadialMargin:10,labelsAngleOffset:0,scaleVisible:true,scaleUnitsPre:'',scaleUnitsPost:'',scaleMax:null,scaleMin:0,scalePoint:'.',scaleThousand:',',scaleRound:false,scaleDecimals:0,scaleFormatter:null,scaleBold:null,scaleItalic:null,scaleColor:null,scaleSize:null,scaleFont:null,scaleLabelsCount:5,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,margin:0,exploded:0,key:null,keyColors:null,keyOffsetx:0,keyOffsety:0,keyTextOffsetx:0,keyTextOffsety:-1,keyTextSize:null,keyTextBold:null,keyTextItalic:null,segmentsAngleOffset:0,variant:'normal'};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');this.data=RG.SVG.arrayClone(this.originalData);this.angles=[];for(var i=0;i<this.data.length;++i){this.angles2[i]=[];}
9
+ 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.centery+=parseFloat(prop.centerx);if(typeof prop.centery==='string'&&prop.centery.match(/^\+|-\d+$/))this.centerx+=parseFloat(prop.centery);if(typeof prop.margin==='string'&&prop.margin.match(/([0-9.]+)deg/)){prop.margin=RegExp.$1/(180/ma.PI);}
10
+ for(var i=0;i<this.data.length;++i){if(typeof this.data[i]==='object'){for(var j=0;j<this.data[i].length;++j){if(typeof this.data[i][j]==='string'){this.data[i][j]=RG.SVG.stringsToNumbers(this.data[i][j]);}}}else if(typeof this.data[i]==='string'){this.data[i]=RG.SVG.stringsToNumbers(this.data[i]);}}
11
+ this.getMaxValue();RG.SVG.resetColorsToOriginalValues({object:this});this.parseColors();this.scale=RG.SVG.getScale({object:this,numlabels:typeof prop.scaleLabelsCount==='number'?prop.scaleLabelsCount:prop.backgroundGridConcentricCount,unitsPre:prop.scaleUnitsPre,unitsPost:prop.scaleUnitsPost,max:typeof prop.scaleMax==='number'?prop.scaleMax:this.max,min:prop.scaleMin,point:prop.scalePoint,round:prop.scaleRound,thousand:prop.scaleThousand,decimals:prop.scaleDecimals,strict:typeof prop.scaleMax==='number',formatter:prop.scaleFormatter});this.max=this.scale.max;this.drawBackground();this.drawRose();this.drawLabels();RG.SVG.drawTitle(this);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?');}
12
+ RG.SVG.attribution(this);if(prop.shadow){RG.SVG.setShadow({object:this,offsetx:prop.shadowOffsetx,offsety:prop.shadowOffsety,blur:prop.shadowBlur,opacity:prop.shadowOpacity,id:'dropShadow'});}
13
+ var obj=this;doc.body.addEventListener('mousedown',function(e)
14
+ {obj.hideHighlight(obj);},false);RG.SVG.fireCustomEvent(this,'ondraw');return this;};this.drawBackground=function()
15
+ {if(prop.backgroundGrid){var grid=RG.SVG.create({svg:this.svg,parent:this.svg.all,type:'g',attr:{className:'rgraph_radar_grid',fill:'rgba(0,0,0,0)',stroke:prop.backgroundGridColor}});var origin=0-(RG.SVG.TRIG.PI/2),radials=(typeof prop.backgroundGridRadialsCount==='number'?prop.backgroundGridRadialsCount:this.data.length),concentrics=prop.backgroundGridConcentricsCount,step=RG.SVG.TRIG.TWOPI/radials;if(radials>0){if(prop.variant==='non-equi-angular'){var radials=this.data.length;for(var i=0,total=0;i<this.data.length;++i){total+=this.data[i][1];}
16
+ for(var i=0,sum=0;i<this.data.length;++i){var coords=RG.SVG.TRIG.toCartesian({cx:this.centerx,cy:this.centery,r:this.radius,angle:origin+((sum/total)*RG.SVG.TRIG.TWOPI)+prop.backgroundGridRadialsAngleOffset});var str='M {1} {2} L {3} {4}'.format(this.centerx,this.centery,coords.x,coords.y);RG.SVG.create({svg:this.svg,type:'path',parent:grid,attr:{d:str,stroke:prop.backgroundGridColor,'stroke-width':prop.backgroundGridLinewidth}});sum+=this.data[i][1];}}else{for(var i=0,len=radials;i<len;++i){var coords=RG.SVG.TRIG.toCartesian({cx:this.centerx,cy:this.centery,r:this.radius,angle:origin+(i*step)+prop.backgroundGridRadialsAngleOffset});var str='M {1} {2} L {3} {4}'.format(this.centerx,this.centery,coords.x,coords.y);RG.SVG.create({svg:this.svg,type:'path',parent:grid,attr:{d:str,stroke:prop.backgroundGridColor,'stroke-width':prop.backgroundGridLinewidth}});}}}
17
+ if(concentrics>0){for(var j=1;j<=concentrics;j++){RG.SVG.create({svg:this.svg,type:'circle',parent:grid,attr:{cx:this.centerx,cy:this.centery,r:this.radius*(j/concentrics),fill:'transparent',stroke:prop.backgroundGridColor,'stroke-width':prop.backgroundGridLinewidth}});}}}};this.drawRose=function(opt)
18
+ {if(prop.variant==='non-equi-angular'){return this.drawRoseNonEquiAngular(opt);}
19
+ var radians=RG.SVG.TRIG.TWOPI/this.data.length;var group=RG.SVG.create({svg:this.svg,type:'g',parent:this.svg.all,attr:{id:'rgraph_rose_segments_'+this.id}});for(var i=0,seq=0;i<this.data.length;++i,++seq){var radius=(this.data[i]/this.scale.max)*this.radius,start=(i/this.data.length)*RG.SVG.TRIG.TWOPI,end=((i/this.data.length)*RG.SVG.TRIG.TWOPI)+radians;var explosion=this.getExploded({index:i,start:start-RG.SVG.TRIG.HALFPI,end:end-RG.SVG.TRIG.HALFPI});if(typeof this.data[i]==='object'&&!RG.SVG.isNull(this.data[i])){var segment_group=RG.SVG.create({svg:this.svg,type:'g',parent:group,attr:{id:'rose_'+this.id+'_segment_group_'+i}});for(var j=0,sum=0,accRadius=0;j<this.data[i].length;++j,++seq){sum+=this.data[i][j];var radius=(sum/this.scale.max)*this.radius;var arcPath=RG.SVG.TRIG.getArcPath2({cx:this.centerx+explosion[0],cy:this.centery+explosion[1],r:radius,start:start+prop.margin+prop.segmentsAngleOffset,end:end-prop.margin+prop.segmentsAngleOffset,anticlockwise:false});if(j===0){arcPath='{1} z'.format(arcPath);}else{var arcPath2=RG.SVG.TRIG.getArcPath2({cx:this.centerx+explosion[0],cy:this.centery+explosion[1],r:prevRadius,start:end-prop.margin+prop.segmentsAngleOffset,end:start+prop.margin+prop.segmentsAngleOffset,anticlockwise:true});arcPath='{1} L {2} {3} {4}'.format(arcPath,this.centerx+explosion[0],this.centery+explosion[1],arcPath2);}
20
+ var path=RG.SVG.create({svg:this.svg,type:'path',parent:segment_group,attr:{d:arcPath,fill:prop.colorsSequential?prop.colors[seq]:prop.colors[j],'fill-opacity':prop.colorsOpacity,stroke:prop.strokestyle,'stroke-width':prop.linewidth,'data-tooltip':(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips.length)?prop.tooltips[seq]:'','data-index':i,'data-centerx':this.centerx+explosion[0],'data-centery':this.centery+explosion[1],'data-group':i,'data-subindex':j,'data-value':this.data[i][j],'data-start-angle':start,'data-end-angle':end,'data-radius':radius,'data-radius-inner':typeof prevRadius==='number'?prevRadius:0,'data-sequential-index':seq}});if(prop.tooltips&&prop.tooltips[seq]){if(prop.tooltipsEvent!=='mousemove'){prop.tooltipsEvent='click';}
21
+ (function(index,group,seq,obj)
22
+ {path.addEventListener(prop.tooltipsEvent,function(e)
23
+ {obj.removeHighlight();RG.SVG.tooltip({object:obj,group:group,index:index,sequentialIndex:seq,text:prop.tooltips[seq],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'){path.addEventListener('mousemove',function(e)
24
+ {e.target.style.cursor='pointer';},false);}}(j,i,seq,this));}
25
+ this.angles.push({object:path,index:seq,cx:this.centerx+explosion[0],cy:this.centery+explosion[1],start:start,end:end,radius:radius,'radius-inner':prevRadius,value:this.data[i][j]});this.angles2[i].push({object:path,index:seq,cx:this.centerx+explosion[0],cy:this.centery+explosion[1],start:start,end:end,radius:radius,'radius-inner':prevRadius,value:this.data[i][j]});var prevRadius=radius;}
26
+ seq--;}else{var arcPath=RG.SVG.TRIG.getArcPath2({cx:this.centerx+explosion[0],cy:this.centery+explosion[1],r:radius,start:start+prop.margin+prop.segmentsAngleOffset,end:end-prop.margin+prop.segmentsAngleOffset,anticlockwise:false});var path=RG.SVG.create({svg:this.svg,type:'path',parent:group,attr:{d:'{1} z'.format(arcPath),fill:prop.colorsSequential?prop.colors[i]:prop.colors[0],'fill-opacity':prop.colorsOpacity,stroke:prop.strokestyle,'stroke-width':prop.linewidth,'data-tooltip':(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips.length)?prop.tooltips[i]:'','data-index':i,'data-centerx':this.centerx+explosion[0],'data-centery':this.centery+explosion[1],'data-value':this.data[i],'data-start-angle':start,'data-end-angle':end,'data-radius':radius,'data-sequential':seq}});this.angles.push({object:path,index:i,cx:this.centerx+explosion[0],cy:this.centery+explosion[1],start:start,end:end,radius:radius,value:this.data[i]});this.angles2[i].push({object:path,index:seq,cx:this.centerx+explosion[0],cy:this.centery+explosion[1],start:start,end:end,radius:radius,'radius-inner':prevRadius,value:this.data[i][j]});if(prop.tooltips&&prop.tooltips[i]){if(prop.tooltipsEvent!=='mousemove'){prop.tooltipsEvent='click';}
27
+ (function(index,obj)
28
+ {path.addEventListener(prop.tooltipsEvent,function(e)
29
+ {obj.removeHighlight();RG.SVG.tooltip({object:obj,index:index,group: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'){path.addEventListener('mousemove',function(e)
30
+ {e.target.style.cursor='pointer';},false);}}(i,this));}}}};this.drawRoseNonEquiAngular=function(opt)
31
+ {var group=RG.SVG.create({svg:this.svg,type:'g',parent:this.svg.all,attr:{id:'rgraph_rose_segments_'+this.id}});for(var i=0,total=0;i<this.data.length;++i){total+=parseFloat(this.data[i][1]);}
32
+ var start=0;for(var i=0,seq=0;i<this.data.length;++i,++seq){var radians=(this.data[i][1]/total)*RG.SVG.TRIG.TWOPI,end=start+radians;var explosion=this.getExploded({index:i,start:start-RG.SVG.TRIG.HALFPI,end:end-RG.SVG.TRIG.HALFPI});if(typeof this.data[i][0]==='object'&&!RG.SVG.isNull(this.data[i][0])){for(var j=0,sum=0;j<this.data[i][0].length;++j,++seq){sum+=this.data[i][0][j];if(j===0){var prevRadius=0,radius=(sum/this.scale.max)*this.radius;var arcPath=RG.SVG.TRIG.getArcPath2({cx:this.centerx+explosion[0],cy:this.centery+explosion[1],r:radius,start:start+prop.margin+prop.segmentsAngleOffset,end:end-prop.margin+prop.segmentsAngleOffset,anticlockwise:false});var arcPath2='';}else{var prevRadius=radius,radius=(sum/this.scale.max)*this.radius;var arcPath=RG.SVG.TRIG.getArcPath2({cx:this.centerx+explosion[0],cy:this.centery+explosion[1],r:radius,start:start+prop.margin+prop.segmentsAngleOffset,end:end-prop.margin+prop.segmentsAngleOffset,anticlockwise:false});var arcPath2=RG.SVG.TRIG.getArcPath2({cx:this.centerx+explosion[0],cy:this.centery+explosion[1],r:prevRadius,start:end-prop.margin+prop.segmentsAngleOffset,end:start+prop.margin+prop.segmentsAngleOffset,anticlockwise:true});}
33
+ var path=RG.SVG.create({svg:this.svg,type:'path',parent:group,attr:{d:'{1} {2} z'.format(arcPath,arcPath2),fill:prop.colorsSequential?prop.colors[seq]:prop.colors[j],'fill-opacity':prop.colorsOpacity,stroke:prop.strokestyle,'stroke-width':prop.linewidth,'data-tooltip':(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips.length)?prop.tooltips[i]:'','data-centerx':this.centerx+explosion[0],'data-centery':this.centery+explosion[1],'data-index':'[{1},{2}]'.format(i,j),'data-value':this.data[i][0][j],'data-start-angle':start,'data-end-angle':end,'data-radius':radius,'data-radius-inner':prevRadius,'data-sequential':seq}});this.angles.push({object:path,index:i,cx:this.centerx+explosion[0],cy:this.centery+explosion[1],start:start,end:end,radius:radius,'radius-inner':prevRadius,value:this.data[i][0]});this.angles2[i].push({object:path,index:seq,cx:this.centerx+explosion[0],cy:this.centery+explosion[1],start:start,end:end,radius:radius,'radius-inner':prevRadius,value:this.data[i][j]});if(prop.tooltips&&prop.tooltips[seq]){if(prop.tooltipsEvent!=='mousemove'){prop.tooltipsEvent='click';}
34
+ (function(index,group,seq,obj)
35
+ {path.addEventListener(prop.tooltipsEvent,function(e)
36
+ {obj.removeHighlight();RG.SVG.tooltip({object:obj,index:index,group:group,sequentialIndex:seq,text:prop.tooltips[seq],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'){path.addEventListener('mousemove',function(e)
37
+ {e.target.style.cursor='pointer';},false);}}(j,i,seq,this));}
38
+ var prevRadius=radius;}
39
+ seq--}else{var radius=(this.data[i][0]/this.scale.max)*this.radius;var arcPath=RG.SVG.TRIG.getArcPath2({cx:this.centerx+explosion[0],cy:this.centery+explosion[1],r:radius,start:start+prop.margin+prop.segmentsAngleOffset,end:end-prop.margin+prop.segmentsAngleOffset,anticlockwise:false});var path=RG.SVG.create({svg:this.svg,type:'path',parent:group,attr:{d:'{1} z'.format(arcPath),fill:prop.colorsSequential?prop.colors[i]:prop.colors[0],'fill-opacity':prop.colorsOpacity,stroke:prop.strokestyle,'stroke-width':prop.linewidth,'data-tooltip':(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips.length)?prop.tooltips[i]:'','data-centerx':this.centerx+explosion[0],'data-centery':this.centery+explosion[1],'data-index':i,'data-value':this.data[i],'data-start-angle':start,'data-end-angle':end,'data-radius':radius,'data-sequential':seq}});this.angles.push({object:path,index:i,cx:this.centerx+explosion[0],cy:this.centery+explosion[1],start:start,end:end,radius:radius,value:this.data[i][0]});this.angles2[i].push({object:path,index:seq,cx:this.centerx+explosion[0],cy:this.centery+explosion[1],start:start,end:end,radius:radius,'radius-inner':0,value:this.data[i][j]});if(prop.tooltips&&prop.tooltips[i]){if(prop.tooltipsEvent!=='mousemove'){prop.tooltipsEvent='click';}
40
+ (function(index,group,seq,obj)
41
+ {path.addEventListener(prop.tooltipsEvent,function(e)
42
+ {obj.removeHighlight();RG.SVG.tooltip({object:obj,index:index,group:index,sequentialIndex:seq,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'){path.addEventListener('mousemove',function(e)
43
+ {e.target.style.cursor='pointer';},false);}}(i,i,seq,this));}}
44
+ start+=radians;}};this.redrawRose=function()
45
+ {};this.drawLabels=function()
46
+ {if(prop.scaleVisible){for(var i=0;i<this.scale.labels.length;++i){var x=this.centerx;var y=this.centery-(this.radius/this.scale.labels.length*(i+1));RG.SVG.text({object:this,svg:this.svg,parent:this.svg.all,text:this.scale.labels[i],size:prop.scaleSize||prop.textSize-2,x:x,y:y,halign:'center',valign:'center',background:'rgba(255,255,255,0.7)',padding:2,color:prop.scaleColor||prop.textColor,bold:typeof prop.scaleBold==='boolean'?prop.scaleBold:prop.textBold,italic:typeof prop.scaleItalic==='boolean'?prop.scaleItalic:prop.textItalic,font:prop.scaleFont||prop.textFont});}
47
+ var str=RG.SVG.numberFormat({object:this,num:this.scale.min.toFixed(prop.scaleDecimals),prepend:prop.scaleUnitsPre,append:prop.scaleUnitsPost,point:prop.scalePoint,thousand:prop.scaleThousand,formatter:prop.scaleFormatter});RG.SVG.text({object:this,svg:this.svg,parent:this.svg.all,text:str,size:prop.scaleSize||prop.textSize-2,x:this.centerx,y:this.centery,halign:'center',valign:'center',background:'rgba(255,255,255,0.7)',padding:2,color:prop.scaleColor||prop.textColor,bold:typeof prop.scaleBold==='boolean'?prop.scaleBold:prop.textBold,italic:typeof prop.scaleItalic==='boolean'?prop.scaleItalic:prop.textItalic,font:prop.scaleFont||prop.textFont});}
48
+ var halign;if(typeof prop.labelsSize!=='number'){prop.labelsSize=prop.textSize+4;}
49
+ for(var i=0;i<prop.labels.length;++i){if(prop.variant==='non-equi-angular'){var angle=((this.angles2[i][0].end-this.angles2[i][0].start)/2)+this.angles2[i][0].start-RG.SVG.TRIG.HALFPI;}else{var angle=(((RG.SVG.TRIG.TWOPI/prop.labels.length))*i)-RG.SVG.TRIG.HALFPI+prop.labelsAngleOffset+((this.angles2[i][0].end-this.angles2[i][0].start)/2);}
50
+ var endpoint=RG.SVG.TRIG.getRadiusEndPoint({r:this.radius+prop.labelsRadialMargin,angle:angle});var explosion=this.getExploded({index:i,start:this.angles2[i][0].start-RG.SVG.TRIG.HALFPI,end:this.angles2[i][0].end-RG.SVG.TRIG.HALFPI});endpoint[0]+=this.centerx+explosion[0];endpoint[1]+=this.centery+explosion[1];if(ma.round(endpoint[0])>this.centerx){halign='left';}else if(ma.round(endpoint[0])===this.centerx){halign='center';}else{halign='right';}
51
+ RG.SVG.text({object:this,svg:this.svg,parent:this.svg.all,text:typeof prop.labels[i]==='string'?prop.labels[i]:'',size:prop.labelsSize,x:endpoint[0],y:endpoint[1],halign:halign,valign:'center',background:'rgba(255,255,255,0.7)',padding:2,color:prop.labelsColor||prop.textColor,bold:typeof prop.labelsBold==='boolean'?prop.labelsBold:prop.textBold,italic:typeof prop.labelsItalic==='boolean'?prop.labelsItalic:prop.textItalic,font:prop.labelsFont||prop.textFont});}};this.highlight=function(path)
52
+ {var path=path.getAttribute('d');var highlight=RG.SVG.create({svg:this.svg,parent:this.svg.all,type:'path',attr:{d:path,fill:prop.highlightFill,stroke:prop.highlightStroke,'stroke-width':prop.highlightLinewidth}});if(prop.tooltipsEvent==='mousemove'){highlight.addEventListener('mouseout',function(e)
53
+ {highlight.parentNode.removeChild(highlight);RG.SVG.hideTooltip();RG.SVG.REG.set('highlight',null);},false);}
54
+ RG.SVG.REG.set('highlight',highlight);};this.parseColors=function()
55
+ {if(!Object.keys(this.originalColors).length){this.originalColors={colors:RG.SVG.arrayClone(prop.colors),highlightFill:RG.SVG.arrayClone(prop.highlightFill)}}
56
+ var colors=prop.colors;if(colors){for(var i=0;i<colors.length;++i){colors[i]=RG.SVG.parseColorRadial({object:this,color:colors[i]});}}
57
+ prop.highlightFill=RG.SVG.parseColorRadial({object:this,color:prop.highlightFill});};this.getMaxValue=function()
58
+ {var max=0;if(prop.variant==='non-equi-angular'){for(var i=0;i<this.data.length;++i){if(!RG.SVG.isNull(this.data[i])){if(typeof this.data[i][0]==='number'){max=ma.max(max,this.data[i][0]);}else if(typeof this.data[i][0]==='object'){max=ma.max(max,RG.SVG.arraySum(this.data[i][0]));}}}}else{for(var i=0;i<this.data.length;++i){if(!RG.SVG.isNull(this.data[i])){if(typeof this.data[i]==='number'){max=ma.max(max,this.data[i]);}else if(typeof this.data[i]==='object'){max=ma.max(max,RG.SVG.arraySum(this.data[i]));}}}}
59
+ this.max=max;};this.getRadius=function(value)
60
+ {return((value-prop.scaleMin)/(this.scale.max-prop.scaleMin))*this.radius;};this.roundRobin=function()
61
+ {};this.on=function(type,func)
62
+ {if(type.substr(0,2)!=='on'){type='on'+type;}
63
+ RG.SVG.addCustomEventListener(this,type,func);return this;};this.exec=function(func)
64
+ {func(this);return this;};this.removeHighlight=this.hideHighlight=function()
65
+ {var highlight=RG.SVG.REG.get('highlight');if(highlight&&this.highlight_node){this.highlight_node.setAttribute('fill','transparent');this.highlight_node.setAttribute('stroke','transparent');RG.SVG.REG.set('highlight',null);}};this.getExploded=function(opt)
66
+ {var index=opt.index,start=opt.start,end=opt.end,exploded=prop.exploded,explodedX,explodedY;if(typeof exploded==='object'&&typeof exploded[index]==='number'){explodedX=ma.cos(((end-start)/2)+start)*exploded[index];explodedY=(ma.sin(((end-start)/2)+start)*exploded[index]);}else if(typeof exploded==='number'){explodedX=ma.cos(((end-start)/2)+start)*exploded;explodedY=ma.sin(((end-start)/2)+start)*exploded;}else{explodedX=0;explodedY=0;}
67
+ return[explodedX,explodedY];};for(i in conf.options){if(typeof i==='string'){this.set(i,conf.options[i]);}}};return this;})(window,document);