rgraph-rails 1.0.5 → 1.0.6

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 +8 -8
  2. data/.travis.yml +0 -1
  3. data/README.md +3 -3
  4. data/lib/rgraph-rails/version.rb +1 -1
  5. data/vendor/assets/javascripts/RGraph.bar.js +239 -3764
  6. data/vendor/assets/javascripts/RGraph.bipolar.js +115 -1986
  7. data/vendor/assets/javascripts/RGraph.common.annotate.js +35 -399
  8. data/vendor/assets/javascripts/RGraph.common.context.js +30 -600
  9. data/vendor/assets/javascripts/RGraph.common.core.js +403 -5187
  10. data/vendor/assets/javascripts/RGraph.common.csv.js +19 -275
  11. data/vendor/assets/javascripts/RGraph.common.deprecated.js +35 -454
  12. data/vendor/assets/javascripts/RGraph.common.dynamic.js +84 -1189
  13. data/vendor/assets/javascripts/RGraph.common.effects.js +90 -1548
  14. data/vendor/assets/javascripts/RGraph.common.key.js +54 -755
  15. data/vendor/assets/javascripts/RGraph.common.resizing.js +37 -567
  16. data/vendor/assets/javascripts/RGraph.common.sheets.js +29 -356
  17. data/vendor/assets/javascripts/RGraph.common.tooltips.js +32 -614
  18. data/vendor/assets/javascripts/RGraph.common.zoom.js +14 -223
  19. data/vendor/assets/javascripts/RGraph.cornergauge.js +71 -0
  20. data/vendor/assets/javascripts/RGraph.drawing.background.js +35 -620
  21. data/vendor/assets/javascripts/RGraph.drawing.circle.js +35 -576
  22. data/vendor/assets/javascripts/RGraph.drawing.image.js +52 -807
  23. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +41 -717
  24. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +37 -668
  25. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +36 -563
  26. data/vendor/assets/javascripts/RGraph.drawing.poly.js +40 -608
  27. data/vendor/assets/javascripts/RGraph.drawing.rect.js +35 -597
  28. data/vendor/assets/javascripts/RGraph.drawing.text.js +34 -642
  29. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +50 -809
  30. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +51 -856
  31. data/vendor/assets/javascripts/RGraph.fuel.js +58 -964
  32. data/vendor/assets/javascripts/RGraph.funnel.js +55 -984
  33. data/vendor/assets/javascripts/RGraph.gantt.js +75 -1241
  34. data/vendor/assets/javascripts/RGraph.gauge.js +87 -1397
  35. data/vendor/assets/javascripts/RGraph.hbar.js +143 -2376
  36. data/vendor/assets/javascripts/RGraph.hprogress.js +80 -1397
  37. data/vendor/assets/javascripts/RGraph.line.js +241 -4162
  38. data/vendor/assets/javascripts/RGraph.meter.js +74 -1278
  39. metadata +3 -30
  40. data/vendor/assets/images/bg.png +0 -0
  41. data/vendor/assets/images/bullet.png +0 -0
  42. data/vendor/assets/images/facebook-large.png +0 -0
  43. data/vendor/assets/images/google-plus-large.png +0 -0
  44. data/vendor/assets/images/logo.png +0 -0
  45. data/vendor/assets/images/meter-image-sd-needle.png +0 -0
  46. data/vendor/assets/images/meter-image-sd.png +0 -0
  47. data/vendor/assets/images/meter-sketch-needle.png +0 -0
  48. data/vendor/assets/images/meter-sketch.png +0 -0
  49. data/vendor/assets/images/odometer-background.png +0 -0
  50. data/vendor/assets/images/rgraph.jpg +0 -0
  51. data/vendor/assets/images/title.png +0 -0
  52. data/vendor/assets/images/twitter-large.png +0 -0
  53. data/vendor/assets/javascripts/RGraph.modaldialog.js +0 -301
  54. data/vendor/assets/javascripts/RGraph.odo.js +0 -1265
  55. data/vendor/assets/javascripts/RGraph.pie.js +0 -2272
  56. data/vendor/assets/javascripts/RGraph.radar.js +0 -1847
  57. data/vendor/assets/javascripts/RGraph.rose.js +0 -1877
  58. data/vendor/assets/javascripts/RGraph.rscatter.js +0 -1425
  59. data/vendor/assets/javascripts/RGraph.scatter.js +0 -2970
  60. data/vendor/assets/javascripts/RGraph.semicircularprogress.js +0 -1015
  61. data/vendor/assets/javascripts/RGraph.thermometer.js +0 -1129
  62. data/vendor/assets/javascripts/RGraph.vprogress.js +0 -1452
  63. data/vendor/assets/javascripts/RGraph.waterfall.js +0 -1252
  64. data/vendor/assets/javascripts/financial-data.js +0 -1067
  65. data/vendor/assets/stylesheets/ModalDialog.css +0 -90
  66. data/vendor/assets/stylesheets/animations.css +0 -3347
  67. data/vendor/assets/stylesheets/website.css +0 -446
@@ -1,1877 +0,0 @@
1
- // version: 2016-06-04
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 dual licensed under the Open Source GPL (General Public License) |
9
- * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just 99 GBP and you can |
11
- * | read about it here: |
12
- * | http://www.rgraph.net/license |
13
- * o--------------------------------------------------------------------------------o
14
- */
15
-
16
- RGraph = window.RGraph || {isRGraph: true};
17
- RGraph.Effects = RGraph.Effects || {};
18
- RGraph.Effects.Rose = RGraph.Effects.Rose || {};
19
-
20
- /**
21
- * The rose chart constuctor
22
- *
23
- * @param object canvas
24
- * @param array data
25
- */
26
- RGraph.Rose = function (conf)
27
- {
28
- /**
29
- * Allow for object config style
30
- */
31
- if ( typeof conf === 'object'
32
- && typeof conf.data === 'object'
33
- && typeof conf.id === 'string') {
34
-
35
- var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
36
-
37
- } else {
38
-
39
- var conf = {id: conf};
40
- conf.data = arguments[1];
41
- }
42
-
43
-
44
-
45
-
46
- this.id = conf.id;
47
- this.canvas = document.getElementById(this.id);
48
- this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null;
49
- this.data = conf.data;
50
- this.canvas.__object__ = this;
51
- this.type = 'rose';
52
- this.isRGraph = true;
53
- this.uid = RGraph.CreateUID();
54
- this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
55
- this.colorsParsed = false;
56
- this.coordsText = [];
57
- this.original_colors = [];
58
- this.firstDraw = true; // After the first draw this will be false
59
-
60
- this.centerx = 0;
61
- this.centery = 0;
62
- this.radius = 0;
63
- this.max = 0;
64
- this.angles = [];
65
- this.angles2 = [];
66
-
67
- this.properties =
68
- {
69
- 'chart.background.axes': true,
70
- 'chart.background.axes.color': 'black',
71
- 'chart.background.grid': true,
72
- 'chart.background.grid.color': '#ccc',
73
- 'chart.background.grid.size': null,
74
- 'chart.background.grid.radials':null,
75
- 'chart.background.grid.count': 5,
76
- 'chart.centerx': null,
77
- 'chart.centery': null,
78
- 'chart.radius': null,
79
- 'chart.angles.start': 0,
80
- 'chart.colors': ['rgba(255,0,0,0.5)', 'rgba(255,255,0,0.5)', 'rgba(0,255,255,0.5)', 'rgb(0,255,0)', 'gray', 'blue', 'rgb(255,128,255)','green', 'pink', 'gray', 'aqua'],
81
- 'chart.linewidth': 1,
82
- 'chart.colors.sequential': false,
83
- 'chart.colors.alpha': null,
84
- 'chart.margin': 0,
85
- 'chart.strokestyle': '#aaa',
86
- 'chart.gutter.left': 25,
87
- 'chart.gutter.right': 25,
88
- 'chart.gutter.top': 25,
89
- 'chart.gutter.bottom': 25,
90
- 'chart.title': '',
91
- 'chart.title.background': null,
92
- 'chart.title.hpos': null,
93
- 'chart.title.vpos': null,
94
- 'chart.title.bold': true,
95
- 'chart.title.font': null,
96
- 'chart.title.x': null,
97
- 'chart.title.y': null,
98
- 'chart.title.halign': null,
99
- 'chart.title.valign': null,
100
- 'chart.labels': null,
101
- 'chart.labels.color': null,
102
- 'chart.labels.position': 'center',
103
- 'chart.labels.axes': 'nsew',
104
- 'chart.labels.boxed': false,
105
- 'chart.labels.offset': 0,
106
- 'chart.text.color': 'black',
107
- 'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
108
- 'chart.text.size': 12,
109
- 'chart.text.accessible': true,
110
- 'chart.text.accessible.overflow': 'visible',
111
- 'chart.text.accessible.pointerevents': false,
112
- 'chart.key': null,
113
- 'chart.key.background': 'white',
114
- 'chart.key.position': 'graph',
115
- 'chart.key.halign': 'right',
116
- 'chart.key.shadow': false,
117
- 'chart.key.shadow.color': '#666',
118
- 'chart.key.shadow.blur': 3,
119
- 'chart.key.shadow.offsetx': 2,
120
- 'chart.key.shadow.offsety': 2,
121
- 'chart.key.position.gutter.boxed': false,
122
- 'chart.key.position.x': null,
123
- 'chart.key.position.y': null,
124
- 'chart.key.color.shape': 'square',
125
- 'chart.key.rounded': true,
126
- 'chart.key.linewidth': 1,
127
- 'chart.key.colors': null,
128
- 'chart.key.interactive': false,
129
- 'chart.key.interactive.highlight.chart.stroke': 'black',
130
- 'chart.key.interactive.highlight.chart.fill': 'rgba(255,255,255,0.7)',
131
- 'chart.key.interactive.highlight.label': 'rgba(255,0,0,0.2)',
132
- 'chart.key.text.color': 'black',
133
- 'chart.contextmenu': null,
134
- 'chart.tooltips': null,
135
- 'chart.tooltips.event': 'onclick',
136
- 'chart.tooltips.effect': 'fade',
137
- 'chart.tooltips.css.class': 'RGraph_tooltip',
138
- 'chart.tooltips.highlight': true,
139
- 'chart.highlight.stroke': 'rgba(0,0,0,0)',
140
- 'chart.highlight.fill': 'rgba(255,255,255,0.7)',
141
- 'chart.annotatable': false,
142
- 'chart.annotate.color': 'black',
143
- 'chart.zoom.factor': 1.5,
144
- 'chart.zoom.fade.in': true,
145
- 'chart.zoom.fade.out': true,
146
- 'chart.zoom.hdir': 'right',
147
- 'chart.zoom.vdir': 'down',
148
- 'chart.zoom.frames': 25,
149
- 'chart.zoom.delay': 16.666,
150
- 'chart.zoom.shadow': true,
151
- 'chart.zoom.background': true,
152
- 'chart.zoom.action': 'zoom',
153
- 'chart.resizable': false,
154
- 'chart.resize.handle.adjust': [0,0],
155
- 'chart.resize.handle.background': null,
156
- 'chart.adjustable': false,
157
- 'chart.ymax': null,
158
- 'chart.ymin': 0,
159
- 'chart.scale.decimals': null,
160
- 'chart.scale.point': '.',
161
- 'chart.scale.thousand': ',',
162
- 'chart.variant': 'stacked',
163
- 'chart.variant.threed.depth': 10,
164
- 'chart.exploded': 0,
165
- 'chart.events.mousemove': null,
166
- 'chart.events.click': null,
167
- 'chart.animation.roundrobin.factor': 1,
168
- 'chart.animation.roundrobin.radius': true,
169
- 'chart.animation.grow.multiplier': 1,
170
- 'chart.labels.count': 5,
171
- 'chart.segment.highlight': false,
172
- 'chart.segment.highlight.count': null,
173
- 'chart.segment.highlight.fill': 'rgba(0,255,0,0.5)',
174
- 'chart.segment.highlight.stroke': 'rgba(0,0,0,0)',
175
- 'chart.clearto': 'rgba(0,0,0,0)'
176
- }
177
-
178
-
179
-
180
- // Go through the data converting it to numbers
181
- for (var i=0; i<this.data.length; ++i) {
182
- if (typeof this.data[i] === 'string') {
183
- this.data[i] = parseFloat(this.data[i]);
184
- } else if (typeof this.data[i] === 'object') {
185
- for (var j=0; j<this.data[i].length; ++j) {
186
- if (typeof this.data[i][j] === 'string') {
187
- this.data[i][j] = parseFloat(this.data[i][j]);
188
- }
189
- }
190
- }
191
- }
192
-
193
-
194
-
195
-
196
- /**
197
- * Create the $ objects. In the case of non-equi-angular rose charts it actually creates too many $ objects,
198
- * but it doesn't matter.
199
- */
200
- var linear_data = RGraph.arrayLinearize(this.data);
201
- for (var i=0; i<linear_data.length; ++i) {
202
- this["$" + i] = {}
203
- }
204
-
205
-
206
- /**
207
- * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
208
- * done already
209
- */
210
- if (!this.canvas.__rgraph_aa_translated__) {
211
- this.context.translate(0.5,0.5);
212
-
213
- this.canvas.__rgraph_aa_translated__ = true;
214
- }
215
-
216
-
217
-
218
-
219
- // Short variable names
220
- var RG = RGraph,
221
- ca = this.canvas,
222
- co = ca.getContext('2d'),
223
- prop = this.properties,
224
- pa2 = RG.path2,
225
- win = window,
226
- doc = document,
227
- ma = Math
228
-
229
-
230
-
231
- /**
232
- * "Decorate" the object with the generic effects if the effects library has been included
233
- */
234
- if (RG.Effects && typeof RG.Effects.decorate === 'function') {
235
- RG.Effects.decorate(this);
236
- }
237
-
238
-
239
-
240
-
241
- /**
242
- * A simple setter
243
- *
244
- * @param string name The name of the property to set
245
- * @param string value The value of the property
246
- */
247
- this.set =
248
- this.Set = function (name)
249
- {
250
- var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
251
-
252
- /**
253
- * the number of arguments is only one and it's an
254
- * object - parse it for configuration data and return.
255
- */
256
- if (arguments.length === 1 && typeof name === 'object') {
257
- RG.parseObjectStyleConfig(this, name);
258
- return this;
259
- }
260
-
261
-
262
- /**
263
- * This should be done first - prepend the propertyy name with "chart." if necessary
264
- */
265
- if (name.substr(0,6) != 'chart.') {
266
- name = 'chart.' + name;
267
- }
268
-
269
-
270
-
271
-
272
- // Convert uppercase letters to dot+lower case letter
273
- while(name.match(/([A-Z])/)) {
274
- name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
275
- }
276
-
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
- // A little BC...
286
- if (name === 'chart.background.grid.spokes') name = 'chart.background.grid.radials';
287
-
288
-
289
-
290
- //
291
- // Change chart.segments.highlight* to chart.segment.highlight (no plural)
292
- //
293
- if (name === 'chart.segments.highlight') name = 'chart.segment.highlight';
294
- if (name === 'chart.segments.highlight.fill') name = 'chart.segment.highlight.fill';
295
- if (name === 'chart.segments.highlight.stroke') name = 'chart.segment.highlight.stroke';
296
-
297
- prop[name.toLowerCase()] = value;
298
-
299
-
300
- return this;
301
- };
302
-
303
-
304
-
305
-
306
- /**
307
- * A simple getter
308
- *
309
- * @param string name The name of the property to get
310
- */
311
- this.get =
312
- this.Get = function (name)
313
- {
314
- /**
315
- * This should be done first - prepend the property name with "chart." if necessary
316
- */
317
- if (name.substr(0,6) != 'chart.') {
318
- name = 'chart.' + name;
319
- }
320
-
321
- // Convert uppercase letters to dot+lower case letter
322
- name = name.replace(/([A-Z])/g, function (str)
323
- {
324
- return '.' + String(RegExp.$1).toLowerCase()
325
- });
326
-
327
- return prop[name.toLowerCase()];
328
- };
329
-
330
-
331
-
332
-
333
- /**
334
- * This method draws the rose chart
335
- */
336
- this.draw =
337
- this.Draw = function ()
338
- {
339
-
340
- /**
341
- * Fire the onbeforedraw event
342
- */
343
- RG.fireCustomEvent(this, 'onbeforedraw');
344
-
345
-
346
-
347
- /**
348
- * This doesn't affect the chart, but is used for compatibility
349
- */
350
- this.gutterLeft = prop['chart.gutter.left'];
351
- this.gutterRight = prop['chart.gutter.right'];
352
- this.gutterTop = prop['chart.gutter.top'];
353
- this.gutterBottom = prop['chart.gutter.bottom'];
354
-
355
- // Calculate the radius
356
- this.radius = (ma.min(ca.width - this.gutterLeft - this.gutterRight, ca.height - this.gutterTop - this.gutterBottom) / 2);
357
- this.centerx = ((ca.width - this.gutterLeft - this.gutterRight) / 2) + this.gutterLeft;
358
- this.centery = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
359
- this.angles = [];
360
- this.angles2 = [];
361
- this.total = 0;
362
- this.startRadians = prop['chart.angles.start'];
363
- this.coordsText = [];
364
-
365
- /**
366
- * Change the centerx marginally if the key is defined
367
- */
368
- if (prop['chart.key'] && prop['chart.key'].length > 0 && prop['chart.key'].length >= 3) {
369
- this.centerx = this.centerx - this.gutterRight + 5;
370
- }
371
-
372
-
373
-
374
- // User specified radius, centerx and centery
375
- if (typeof prop['chart.centerx'] == 'number') this.centerx = prop['chart.centerx'];
376
- if (typeof prop['chart.centery'] == 'number') this.centery = prop['chart.centery'];
377
- if (typeof prop['chart.radius'] == 'number') this.radius = prop['chart.radius'];
378
-
379
- /**
380
- * Parse the colors for gradients. Its down here so that the center X/Y can be used
381
- */
382
- if (!this.colorsParsed) {
383
-
384
- this.parseColors();
385
-
386
- // Don't want to do this again
387
- this.colorsParsed = true;
388
- }
389
-
390
-
391
-
392
- // 3D variant
393
- if (prop['chart.variant'].indexOf('3d') !== -1) {
394
-
395
- var scaleX = 1.5;
396
-
397
- this.context.setTransform(
398
- scaleX,
399
- 0,
400
- 0,
401
- 1,
402
- (ca.width * scaleX - ca.width) * -0.5,
403
- 0
404
- );
405
- }
406
-
407
-
408
-
409
-
410
-
411
- this.drawBackground();
412
-
413
-
414
-
415
-
416
-
417
- // If a 3D variant draw the depth
418
- if (prop['chart.variant'].indexOf('3d') !== -1) {
419
-
420
- RG.setShadow(this,'rgba(0,0,0,0.35)',0,15,25);
421
-
422
- for (var i=prop['chart.variant.threed.depth']; i>0; i-=1) {
423
-
424
- this.centery -= 1;
425
- this.drawRose({storeAngles: false});
426
-
427
- RG.setShadow(this,'rgba(0,0,0,0)',0,0,0);
428
-
429
-
430
- // Make the segments darker
431
- for (var j=0,len=this.angles.length; j<len; j+=1) {
432
-
433
- var a = this.angles[j];
434
-
435
- pa2(co, [
436
- 'b',
437
- 'm', a[4], a[5],
438
- 'a', a[4], a[5], a[3] + 1.5, a[0] - 0.01, a[1] + 0.01, false,
439
- 'c',
440
- 'f', 'rgba(0,0,0,0.1)'
441
- ]);
442
- }
443
- }
444
- }
445
-
446
- this.drawRose();
447
- this.drawLabels();
448
-
449
- /**
450
- * Set the strokestyle to transparent because of a strange double stroke bug
451
- *
452
- * DO NOT REMOVE
453
- */
454
- co.strokeStyle = 'rgba(0,0,0,0)'
455
-
456
-
457
- /**
458
- * Setup the context menu if required
459
- */
460
- if (prop['chart.contextmenu']) {
461
- RG.ShowContext(this);
462
- }
463
-
464
-
465
- /**
466
- * This function enables resizing
467
- */
468
- if (prop['chart.resizable']) {
469
- RG.AllowResizing(this);
470
- }
471
-
472
-
473
- /**
474
- * This function enables adjusting
475
- */
476
- if (prop['chart.adjustable']) {
477
- RG.AllowAdjusting(this);
478
- }
479
-
480
-
481
- /**
482
- * This installs the event listeners
483
- */
484
- RG.InstallEventListeners(this);
485
-
486
-
487
-
488
-
489
-
490
- //
491
- // Allow the segments to be highlighted
492
- //
493
- if (prop['chart.segment.highlight']) {
494
-
495
- // Check to see if the dynamic library has been included
496
- if (!RG.allowSegmentHighlight) {
497
- alert('[WARNING] The segment highlight function does not exist - have you included the dynamic library?');
498
- }
499
-
500
- RG.allowSegmentHighlight({
501
- object: this,
502
- count: typeof prop['chart.segment.highlight.count'] === 'number' ? prop['chart.segment.highlight.count'] : this.data.length,
503
- fill: prop['chart.segment.highlight.fill'],
504
- stroke: prop['chart.segment.highlight.stroke']
505
- });
506
- }
507
-
508
-
509
-
510
- /**
511
- * Fire the onfirstdraw event
512
- */
513
- if (this.firstDraw) {
514
- RG.fireCustomEvent(this, 'onfirstdraw');
515
- this.firstDraw = false;
516
- this.firstDrawFunc();
517
- }
518
-
519
-
520
-
521
- /**
522
- * Fire the RGraph ondraw event
523
- */
524
- RG.FireCustomEvent(this, 'ondraw');
525
-
526
- return this;
527
- };
528
-
529
-
530
-
531
-
532
- /**
533
- * This method draws the rose charts background
534
- */
535
- this.drawBackground =
536
- this.DrawBackground = function ()
537
- {
538
- co.lineWidth = 1;
539
-
540
-
541
- // Draw the background grey circles/spokes
542
- if (prop['chart.background.grid']) {
543
- if (typeof(prop['chart.background.grid.count']) == 'number') {
544
- prop['chart.background.grid.size'] = this.radius / prop['chart.background.grid.count'];
545
- }
546
-
547
- co.beginPath();
548
- co.strokeStyle = prop['chart.background.grid.color'];
549
-
550
- // Radius must be greater than 0 for Opera to work
551
- for (var i=prop['chart.background.grid.size']; i<=this.radius; i+=prop['chart.background.grid.size']) {
552
-
553
- // Hmmm... This is questionable
554
- co.moveTo(this.centerx + i, this.centery);
555
-
556
- // Radius must be greater than 0 for Opera to work
557
- co.arc(this.centerx,
558
- this.centery,
559
- i,
560
- 0,
561
- RG.TWOPI,
562
- false);
563
- }
564
- co.stroke();
565
-
566
-
567
-
568
-
569
-
570
-
571
- // Draw the background lines that go from the center outwards
572
- co.beginPath();
573
- if (typeof prop['chart.background.grid.radials'] !== 'number') {
574
- prop['chart.background.grid.radials'] = this.data.length
575
- }
576
-
577
- var num = (360 / prop['chart.background.grid.radials']);
578
-
579
- for (var i=num; i<=360; i+=num) {
580
-
581
- // Radius must be greater than 0 for Opera to work
582
- co.arc(this.centerx,
583
- this.centery,
584
- this.radius,
585
- ((i / (180 / RG.PI)) - RG.HALFPI) + this.startRadians,
586
- (((i + 0.0001) / (180 / RG.PI)) - RG.HALFPI) + this.startRadians,
587
- false);
588
-
589
- co.lineTo(this.centerx, this.centery);
590
- }
591
- co.stroke();
592
- }
593
-
594
-
595
-
596
- if (prop['chart.background.axes']) {
597
- co.beginPath();
598
- co.strokeStyle = prop['chart.background.axes.color'];
599
-
600
- // Draw the X axis
601
- co.moveTo(this.centerx - this.radius, Math.round(this.centery) );
602
- co.lineTo(this.centerx + this.radius, Math.round(this.centery) );
603
-
604
- // Draw the X ends
605
- co.moveTo(Math.round(this.centerx - this.radius), this.centery - 5);
606
- co.lineTo(Math.round(this.centerx - this.radius), this.centery + 5);
607
- co.moveTo(Math.round(this.centerx + this.radius), this.centery - 5);
608
- co.lineTo(Math.round(this.centerx + this.radius), this.centery + 5);
609
-
610
- // Draw the X check marks
611
- for (var i=(this.centerx - this.radius); i<(this.centerx + this.radius); i+=(this.radius / 5)) {
612
- co.moveTo(Math.round(i), this.centery - 3);
613
- co.lineTo(Math.round(i), this.centery + 3.5);
614
- }
615
-
616
- // Draw the Y check marks
617
- for (var i=(this.centery - this.radius); i<(this.centery + this.radius); i+=(this.radius / 5)) {
618
- co.moveTo(this.centerx - 3, Math.round(i));
619
- co.lineTo(this.centerx + 3, Math.round(i));
620
- }
621
-
622
- // Draw the Y axis
623
- co.moveTo(ma.round(this.centerx), this.centery - this.radius);
624
- co.lineTo(ma.round(this.centerx), this.centery + this.radius);
625
-
626
- // Draw the Y ends
627
- co.moveTo(this.centerx - 5, ma.round(this.centery - this.radius));
628
- co.lineTo(this.centerx + 5, ma.round(this.centery - this.radius));
629
-
630
- co.moveTo(this.centerx - 5, ma.round(this.centery + this.radius));
631
- co.lineTo(this.centerx + 5, ma.round(this.centery + this.radius));
632
-
633
- // Stroke it
634
- co.closePath();
635
- co.stroke();
636
- }
637
- };
638
-
639
-
640
-
641
-
642
- /**
643
- * This method draws the data on the graph
644
- */
645
- this.drawRose =
646
- this.DrawRose = function ()
647
- {
648
- var max = 0,
649
- data = this.data,
650
- margin = RG.degrees2Radians(prop['chart.margin']),
651
- opt = arguments[0] || {}
652
-
653
- co.lineWidth = prop['chart.linewidth'];
654
-
655
- // Work out the maximum value and the sum
656
- if (RG.isNull(prop['chart.ymax'])) {
657
-
658
- // Work out the max
659
- for (var i=0; i<data.length; ++i) {
660
- if (typeof data[i] == 'number') {
661
- max = ma.max(max, data[i]);
662
- } else if (typeof data[i] == 'object' && prop['chart.variant'].indexOf('non-equi-angular') !== -1) {
663
- max = ma.max(max, data[i][0]);
664
-
665
- // Fallback is stacked
666
- } else {
667
- max = ma.max(max, RG.arraySum(data[i]));
668
- }
669
- }
670
-
671
- this.scale2 = RG.getScale2(this, {
672
- 'max':max,
673
- 'min':0,
674
- 'scale.thousand':prop['chart.scale.thousand'],
675
- 'scale.point':prop['chart.scale.point'],
676
- 'scale.decimals':prop['chart.scale.decimals'],
677
- 'ylabels.count':prop['chart.labels.count'],
678
- 'scale.round':prop['chart.scale.round'],
679
- 'units.pre': prop['chart.units.pre'],
680
- 'units.post': prop['chart.units.post']
681
- });
682
- this.max = this.scale2.max;
683
-
684
- } else {
685
-
686
- var ymax = prop['chart.ymax'];
687
-
688
-
689
-
690
- this.scale2 = RG.getScale2(this, {
691
- 'max':ymax,
692
- 'strict':true,
693
- 'scale.thousand':prop['chart.scale.thousand'],
694
- 'scale.point':prop['chart.scale.point'],
695
- 'scale.decimals':prop['chart.scale.decimals'],
696
- 'ylabels.count':prop['chart.labels.count'],
697
- 'scale.round':prop['chart.scale.round'],
698
- 'units.pre': prop['chart.units.pre'],
699
- 'units.post': prop['chart.units.post']
700
- });
701
- this.max = this.scale2.max
702
- }
703
-
704
- this.sum = RG.array_sum(data);
705
-
706
- // Move to the centre
707
- co.moveTo(this.centerx, this.centery);
708
-
709
- co.stroke(); // Stroke the background so it stays grey
710
-
711
- // Transparency
712
- if (prop['chart.colors.alpha']) {
713
- co.globalAlpha = prop['chart.colors.alpha'];
714
- }
715
-
716
- var sequentialIndex = 0;
717
-
718
- /*******************************************************
719
- * A non-equi-angular Rose chart
720
- *******************************************************/
721
- if (typeof(prop['chart.variant']) == 'string' && prop['chart.variant'].indexOf('non-equi-angular') !== -1) {
722
-
723
- var total=0;
724
- for (var i=0; i<data.length; ++i) {
725
- total += data[i][1];
726
- }
727
-
728
-
729
- for (var i=0; i<this.data.length; ++i) {
730
-
731
- var segmentRadians = ((this.data[i][1] / total) * RG.TWOPI);
732
- var radius = ((this.data[i][0] - prop['chart.ymin']) / (this.max - prop['chart.ymin'])) * this.radius;
733
- radius = radius * prop['chart.animation.grow.multiplier'];
734
-
735
- co.strokeStyle = prop['chart.strokestyle'];
736
- co.fillStyle = prop['chart.colors'][0];
737
-
738
- if (prop['chart.colors.sequential']) {
739
- co.fillStyle = prop['chart.colors'][i];
740
- }
741
-
742
- co.beginPath(); // Begin the segment
743
-
744
- var startAngle = (this.startRadians * prop['chart.animation.roundrobin.factor']) - RG.HALFPI + margin;
745
- var endAngle = ((this.startRadians + segmentRadians) * prop['chart.animation.roundrobin.factor']) - RG.HALFPI - margin;
746
-
747
- var exploded = this.getexploded(i, startAngle, endAngle, prop['chart.exploded']);
748
- var explodedX = exploded[0];
749
- var explodedY = exploded[1];
750
-
751
-
752
- co.arc(
753
- this.centerx + explodedX,
754
- this.centery + explodedY,
755
- prop['chart.animation.roundrobin.radius'] ? radius * prop['chart.animation.roundrobin.factor'] : radius,
756
- startAngle,
757
- endAngle,
758
- 0
759
- );
760
- co.lineTo(this.centerx + explodedX, this.centery + explodedY);
761
- co.closePath(); // End the segment
762
-
763
- co.stroke();
764
- co.fill();
765
-
766
- // Store the start and end angles
767
-
768
- this.angles[i] = [
769
- startAngle,
770
- endAngle,
771
- 0,
772
- radius,
773
- this.centerx + explodedX,
774
- this.centery + explodedY
775
- ];
776
-
777
- sequentialIndex++;
778
- this.startRadians += segmentRadians;
779
- }
780
- } else {
781
-
782
- var sequentialColorIndex = 0;
783
-
784
- /*******************************************************
785
- * Draw regular segments here
786
- *******************************************************/
787
- for (var i=0; i<this.data.length; ++i) {
788
-
789
- var segmentRadians = (1 / this.data.length) * RG.TWOPI;
790
-
791
- if (typeof this.data[i] == 'number') {
792
- co.beginPath(); // Begin the segment
793
-
794
- co.strokeStyle = prop['chart.strokestyle'];
795
- co.fillStyle = prop['chart.colors'][0];
796
-
797
- /*******************************************************
798
- * This allows sequential colors
799
- *******************************************************/
800
- if (prop['chart.colors.sequential']) {
801
- co.fillStyle = prop['chart.colors'][i];
802
- }
803
-
804
- var radius = ((this.data[i] - prop['chart.ymin']) / (this.max - prop['chart.ymin'])) * this.radius;
805
- radius = radius * prop['chart.animation.grow.multiplier'];
806
-
807
- var startAngle = (this.startRadians * prop['chart.animation.roundrobin.factor']) - RG.HALFPI + margin;
808
- var endAngle = (this.startRadians * prop['chart.animation.roundrobin.factor']) + (segmentRadians * prop['chart.animation.roundrobin.factor']) - RG.HALFPI - margin;
809
-
810
- var exploded = this.getexploded(i, startAngle, endAngle, prop['chart.exploded']);
811
- var explodedX = exploded[0];
812
- var explodedY = exploded[1];
813
-
814
- co.arc(this.centerx + explodedX,
815
- this.centery + explodedY,
816
- prop['chart.animation.roundrobin.radius'] ? radius * prop['chart.animation.roundrobin.factor'] : radius,
817
- startAngle,
818
- endAngle,
819
- 0);
820
- co.lineTo(this.centerx + explodedX, this.centery + explodedY);
821
- co.closePath(); // End the segment
822
- co.stroke();
823
- co.fill();
824
-
825
- // This skirts a double-stroke bug
826
- co.beginPath();
827
-
828
- if (endAngle == 0) {
829
- //endAngle = RG.TWOPI;
830
- }
831
-
832
- // Store the start and end angles
833
- this.angles[i] = [
834
- startAngle,
835
- endAngle,
836
- 0,
837
- radius * prop['chart.animation.roundrobin.factor'],
838
- this.centerx + explodedX,
839
- this.centery + explodedY
840
- ];
841
-
842
- sequentialIndex++;
843
-
844
- /*******************************************************
845
- * Draw a stacked segment
846
- *******************************************************/
847
- } else if (typeof(this.data[i]) == 'object') {
848
-
849
- var margin = prop['chart.margin'] / (180 / RG.PI);
850
-
851
-
852
- // Initialise the angles2 array
853
- if (!this.angles2[i]) {
854
- this.angles2[i] = [];
855
- }
856
-
857
-
858
- for (var j=0; j<this.data[i].length; ++j) {
859
-
860
- var startAngle = (this.startRadians * prop['chart.animation.roundrobin.factor']) - RG.HALFPI + margin;
861
- var endAngle = (this.startRadians * prop['chart.animation.roundrobin.factor'])+ (segmentRadians * prop['chart.animation.roundrobin.factor']) - RG.HALFPI - margin;
862
-
863
- var exploded = this.getexploded(i, startAngle, endAngle, prop['chart.exploded']);
864
- var explodedX = exploded[0];
865
- var explodedY = exploded[1];
866
-
867
- co.strokeStyle = prop['chart.strokestyle'];
868
- co.fillStyle = prop['chart.colors'][j];
869
-
870
- // This facilitates sequential color support
871
- if (prop['chart.colors.sequential']) {
872
- co.fillStyle = prop['chart.colors'][sequentialColorIndex++];
873
- }
874
-
875
- if (j == 0) {
876
- co.beginPath(); // Begin the segment
877
- var startRadius = 0;
878
- var endRadius = ((this.data[i][j] - prop['chart.ymin']) / (this.max - prop['chart.ymin'])) * this.radius;
879
- endRadius = endRadius * prop['chart.animation.grow.multiplier'];
880
-
881
- co.arc(this.centerx + explodedX,
882
- this.centery + explodedY,
883
- prop['chart.animation.roundrobin.radius'] ? endRadius * prop['chart.animation.roundrobin.factor'] : endRadius,
884
- startAngle,
885
- endAngle,
886
- 0);
887
- co.lineTo(this.centerx + explodedX, this.centery + explodedY);
888
- co.closePath(); // End the segment
889
- co.stroke();
890
- co.fill();
891
-
892
- this.angles[sequentialIndex++] = [
893
- startAngle,
894
- endAngle,
895
- 0,
896
- endRadius * prop['chart.animation.roundrobin.factor'],
897
- this.centerx + explodedX,
898
- this.centery + explodedY
899
- ];
900
-
901
- this.angles2[i][j] = [
902
- startAngle,
903
- endAngle,
904
- 0,
905
- endRadius * prop['chart.animation.roundrobin.factor'],
906
- this.centerx + explodedX,
907
- this.centery + explodedY
908
- ];
909
-
910
- } else {
911
-
912
- co.beginPath(); // Begin the segment
913
-
914
- var startRadius = endRadius; // This comes from the prior iteration of this loop
915
- var endRadius = (((this.data[i][j] - prop['chart.ymin']) / (this.max - prop['chart.ymin'])) * this.radius) + startRadius;
916
- endRadius = endRadius * prop['chart.animation.grow.multiplier'];
917
-
918
- co.arc(this.centerx + explodedX,
919
- this.centery + explodedY,
920
- startRadius * prop['chart.animation.roundrobin.factor'],
921
- startAngle,
922
- endAngle,
923
- 0);
924
-
925
- co.arc(this.centerx + explodedX,
926
- this.centery + explodedY,
927
- endRadius * prop['chart.animation.roundrobin.factor'],
928
- endAngle,
929
- startAngle,
930
- true);
931
-
932
- co.closePath(); // End the segment
933
- co.stroke();
934
- co.fill();
935
-
936
-
937
- this.angles[sequentialIndex++] = [
938
- startAngle,
939
- endAngle,
940
- startRadius * prop['chart.animation.roundrobin.factor'],
941
- endRadius * prop['chart.animation.roundrobin.factor'],
942
- this.centerx + explodedX,
943
- this.centery + explodedY
944
- ];
945
-
946
- this.angles2[i][j] = [
947
- startAngle,
948
- endAngle,
949
- startRadius * prop['chart.animation.roundrobin.factor'],
950
- endRadius * prop['chart.animation.roundrobin.factor'],
951
- this.centerx + explodedX,
952
- this.centery + explodedY
953
- ];
954
- }
955
- }
956
- }
957
-
958
- this.startRadians += segmentRadians;
959
- }
960
- }
961
-
962
- // Turn off the transparency
963
- if (prop['chart.colors.alpha']) {
964
- co.globalAlpha = 1;
965
- }
966
-
967
- // Draw the title if any has been set
968
- if (prop['chart.title']) {
969
- RG.drawTitle(
970
- this,
971
- prop['chart.title'],
972
- (ca.height / 2) - this.radius,
973
- this.centerx,
974
- prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2
975
- );
976
- }
977
- };
978
-
979
-
980
-
981
-
982
- /**
983
- * Unsuprisingly, draws the labels
984
- */
985
- this.drawLabels =
986
- this.DrawLabels = function ()
987
- {
988
- co.lineWidth = 1;
989
- var key = prop['chart.key'];
990
-
991
- if (key && key.length) {
992
- RG.DrawKey(this, key, prop['chart.colors']);
993
- }
994
-
995
- // Set the color to black
996
- co.fillStyle = prop['chart.text.color'];
997
- co.strokeStyle = 'black';
998
-
999
- var radius = this.radius,
1000
- font = prop['chart.text.font'],
1001
- size = prop['chart.text.size'],
1002
- axes = prop['chart.labels.axes'].toLowerCase(),
1003
- decimals = prop['chart.scale.decimals'],
1004
- units_pre = prop['chart.units.pre'],
1005
- units_post = prop['chart.units.post'],
1006
- centerx = this.centerx,
1007
- centery = this.centery + (prop['chart.variant'].indexOf('3d') !== -1 ? prop['chart.variant.threed.depth'] : 0);
1008
-
1009
- // Draw any circular labels
1010
- if (typeof prop['chart.labels'] == 'object' && prop['chart.labels']) {
1011
- this.DrawCircularLabels(co, prop['chart.labels'], font, size, radius + 10);
1012
- }
1013
-
1014
-
1015
- // Size can be specified seperately for the scale now
1016
- if (typeof(prop['chart.text.size.scale']) == 'number') {
1017
- size = prop['chart.text.size.scale'];
1018
- }
1019
-
1020
-
1021
- var color = 'rgba(255,255,255,0.8)';
1022
-
1023
- // The "North" axis labels
1024
- if (axes.indexOf('n') > -1) {
1025
- for (var i=0; i<prop['chart.labels.count']; ++i) {
1026
- RG.text2(this, {
1027
- 'font':font,
1028
- 'size':size,
1029
- 'x':centerx - 10,
1030
- 'y':centery - (radius * ((i+1) / prop['chart.labels.count'])),
1031
- 'text':this.scale2.labels[i],
1032
- 'valign':'center',
1033
- 'halign':'right',
1034
- 'bounding':true,
1035
- 'bounding.fill':color,
1036
- 'bounding.stroke':prop['chart.labels.boxed'] ? 'black' : 'rgba(0,0,0,0)',
1037
- 'tag': 'scale'
1038
- });
1039
- }
1040
- }
1041
-
1042
- // The "South" axis labels
1043
- if (axes.indexOf('s') > -1) {
1044
- for (var i=0; i<prop['chart.labels.count']; ++i) {
1045
- RG.Text2(this, {
1046
- 'font':font,
1047
- 'size':size,
1048
- 'x':centerx - 10,
1049
- 'y':centery + (radius * ((i+1) / prop['chart.labels.count'])),
1050
- 'text':this.scale2.labels[i],
1051
- 'valign':'center',
1052
- 'halign':'right',
1053
- 'bounding':true,
1054
- 'bounding.fill':color,
1055
- 'bounding.stroke':prop['chart.labels.boxed'] ? 'black' : 'rgba(0,0,0,0)',
1056
- 'tag': 'scale'
1057
- });
1058
- }
1059
- }
1060
-
1061
- // The "East" axis labels
1062
- if (axes.indexOf('e') > -1) {
1063
- for (var i=0; i<prop['chart.labels.count']; ++i) {
1064
- RG.Text2(this, {
1065
- 'font':font,
1066
- 'size':size,
1067
- 'x':centerx + (radius * ((i+1) / prop['chart.labels.count'])),
1068
- 'y':centery + 10,
1069
- 'text':this.scale2.labels[i],
1070
- 'valign':'top',
1071
- 'halign':'center',
1072
- 'bounding':true,
1073
- 'bounding.fill':color,
1074
- 'bounding.stroke':prop['chart.labels.boxed'] ? 'black' : 'rgba(0,0,0,0)',
1075
- 'tag': 'scale'
1076
- });
1077
- }
1078
- }
1079
-
1080
- // The "West" axis labels
1081
- if (axes.indexOf('w') > -1) {
1082
- for (var i=0; i<prop['chart.labels.count']; ++i) {
1083
- RG.Text2(this, {
1084
- 'font':font,
1085
- 'size':size,
1086
- 'x':centerx - (radius * ((i+1) / prop['chart.labels.count'])),
1087
- 'y':centery + 10,
1088
- 'text':this.scale2.labels[i],
1089
- 'valign':'top',
1090
- 'halign':'center',
1091
- 'bounding':true,
1092
- 'bounding.fill':color,
1093
- 'bounding.stroke':prop['chart.labels.boxed'] ? 'black' : 'rgba(0,0,0,0)',
1094
- 'tag': 'scale'
1095
- });
1096
- }
1097
- }
1098
-
1099
- if (RG.trim(axes).length > 0) {
1100
- RG.Text2(this, {
1101
- 'font':font,
1102
- 'size':size,
1103
- 'x':centerx,
1104
- 'y':centery,
1105
- 'text':typeof(prop['chart.ymin']) == 'number' ? RG.number_format(this, Number(prop['chart.ymin']).toFixed(prop['chart.scale.decimals']), units_pre, units_post) : '0',
1106
- 'valign':'center',
1107
- 'halign':'center',
1108
- 'bounding':true,
1109
- 'bounding.fill':color,
1110
- 'bounding.stroke':prop['chart.labels.boxed'] ? 'black' : 'rgba(0,0,0,0)',
1111
- 'tag': 'scale'
1112
- });
1113
- }
1114
- };
1115
-
1116
-
1117
-
1118
-
1119
- /**
1120
- * Draws the circular labels that go around the charts
1121
- *
1122
- * @param labels array The labels that go around the chart
1123
- */
1124
- this.drawCircularLabels =
1125
- this.DrawCircularLabels = function (co, labels, font, size, radius)
1126
- {
1127
- var variant = prop['chart.variant'],
1128
- position = prop['chart.labels.position'],
1129
- radius = radius + 5 + prop['chart.labels.offset'],
1130
- centerx = this.centerx,
1131
- centery = this.centery + (prop['chart.variant'].indexOf('3d') !== -1 ? prop['chart.variant.threed.depth'] : 0),
1132
- labelsColor = prop['chart.labels.color'] || prop['chart.text.color']
1133
-
1134
- for (var i=0; i<labels.length; ++i) {
1135
- if (typeof(variant) == 'string' && variant.indexOf('non-equi-angular') !== -1) {
1136
- var a = Number(this.angles[i][0]) + ((this.angles[i][1] - this.angles[i][0]) / 2);
1137
- } else {
1138
- var a = (RG.TWOPI / labels.length) * (i + 1) - (RG.TWOPI / (labels.length * 2));
1139
- var a = a - RG.HALFPI + (prop['chart.labels.position'] == 'edge' ? ((RG.TWOPI / labels.length) / 2) : 0);
1140
- }
1141
-
1142
- var x = centerx + (ma.cos(a) * radius);
1143
- var y = centery + (ma.sin(a) * radius);
1144
-
1145
- // Horizontal alignment
1146
- if (x > centerx) {
1147
- halign = 'left';
1148
- } else if (Math.round(x) == centerx) {
1149
- halign = 'center';
1150
- } else {
1151
- halign = 'right';
1152
- }
1153
-
1154
- RG.text2(this, {
1155
- 'color': labelsColor,
1156
- 'font':font,
1157
- 'size':size,
1158
- 'x':x,
1159
- 'y':y,
1160
- 'text':String(labels[i]),
1161
- 'halign':halign,
1162
- 'valign':'center',
1163
- 'tag': 'labels'
1164
- });
1165
- }
1166
- };
1167
-
1168
-
1169
-
1170
-
1171
-
1172
-
1173
-
1174
-
1175
-
1176
-
1177
-
1178
-
1179
-
1180
-
1181
-
1182
-
1183
-
1184
-
1185
-
1186
-
1187
-
1188
-
1189
-
1190
-
1191
-
1192
-
1193
- /**
1194
- * This function is for use with circular graph types, eg the Pie or Rose. Pass it your event object
1195
- * and it will pass you back the corresponding segment details as an array:
1196
- *
1197
- * [x, y, r, startAngle, endAngle]
1198
- *
1199
- * Angles are measured in degrees, and are measured from the "east" axis (just like the canvas).
1200
- *
1201
- * @param object e Your event object
1202
- * @param object Options (OPTIONAL):
1203
- * radius - whether to take into account
1204
- * the radius of the segment
1205
- */
1206
- this.getShape =
1207
- this.getSegment = function (e)
1208
- {
1209
- RG.fixEventObject(e);
1210
-
1211
- var angles = this.angles;
1212
- var ret = [];
1213
- var opt = arguments[1] ? arguments[1] : {radius: true};
1214
-
1215
- /**
1216
- * Go through all of the angles checking each one
1217
- */
1218
- for (var i=0; i<angles.length ; ++i) {
1219
-
1220
- var angleStart = angles[i][0];
1221
- var angleEnd = angles[i][1];
1222
- var radiusStart = opt.radius === false ? 0 : angles[i][2];
1223
- var radiusEnd = opt.radius === false ? this.radius : angles[i][3];
1224
- var centerX = angles[i][4];
1225
- var centerY = angles[i][5];// - (prop['chart.variant'].indexOf('3d') !== -1 ? prop['chart.variant.threed.depth'] : 0);
1226
- var mouseXY = RG.getMouseXY(e);
1227
- var mouseX = mouseXY[0] - centerX;
1228
- var mouseY = mouseXY[1] - centerY;
1229
-
1230
- // New click testing (the 0.01 is there because Opera doesn't like 0 as the radius)
1231
- co.beginPath();
1232
- co.arc(centerX, centerY, radiusStart ? radiusStart : 0.01, angleStart, angleEnd, false);
1233
- co.arc(centerX, centerY, radiusEnd, angleEnd, angleStart, true);
1234
- co.closePath();
1235
-
1236
- // No stroke() or fill()
1237
-
1238
-
1239
- if (co.isPointInPath(mouseXY[0], mouseXY[1])) {
1240
-
1241
- angles[i][6] = i;
1242
-
1243
- if (RG.parseTooltipText) {
1244
- var tooltip = RG.parseTooltipText(prop['chart.tooltips'], angles[i][6]);
1245
- }
1246
-
1247
- // Add the textual keys
1248
- angles[i]['object'] = this;
1249
- angles[i]['x'] = angles[i][4];
1250
- angles[i]['y'] = angles[i][5];
1251
- angles[i]['angle.start'] = angles[i][0];
1252
- angles[i]['angle.end'] = angles[i][1];
1253
- angles[i]['radius.start'] = angles[i][2];
1254
- angles[i]['radius.end'] = angles[i][3];
1255
- angles[i]['index'] = angles[i][6];
1256
- angles[i]['tooltip'] = tooltip ? tooltip : null;
1257
-
1258
- return angles[i];
1259
- }
1260
- }
1261
-
1262
- return null;
1263
- };
1264
-
1265
-
1266
-
1267
-
1268
-
1269
-
1270
-
1271
-
1272
-
1273
-
1274
-
1275
-
1276
-
1277
-
1278
-
1279
-
1280
-
1281
-
1282
-
1283
-
1284
-
1285
-
1286
-
1287
-
1288
- /**
1289
- * Returns any exploded for a particular segment
1290
- */
1291
- this.getExploded =
1292
- this.getexploded = function (index, startAngle, endAngle, exploded)
1293
- {
1294
- var explodedx, explodedy;
1295
-
1296
- /**
1297
- * Retrieve any exploded - the exploded can be an array of numbers or a single number
1298
- * (which is applied to all segments)
1299
- */
1300
- if (typeof(exploded) == 'object' && typeof(exploded[index]) == 'number') {
1301
- explodedx = Math.cos(((endAngle - startAngle) / 2) + startAngle) * exploded[index];
1302
- explodedy = Math.sin(((endAngle - startAngle) / 2) + startAngle) * exploded[index];
1303
-
1304
- } else if (typeof(exploded) == 'number') {
1305
- explodedx = Math.cos(((endAngle - startAngle) / 2) + startAngle) * exploded;
1306
- explodedy = Math.sin(((endAngle - startAngle) / 2) + startAngle) * exploded;
1307
-
1308
- } else {
1309
- explodedx = 0;
1310
- explodedy = 0;
1311
- }
1312
-
1313
- return [explodedx, explodedy];
1314
- };
1315
-
1316
-
1317
-
1318
-
1319
- /**
1320
- * This function facilitates the installation of tooltip event listeners if
1321
- * tooltips are defined.
1322
- */
1323
- this.allowTooltips =
1324
- this.AllowTooltips = function ()
1325
- {
1326
- // Preload any tooltip images that are used in the tooltips
1327
- RG.PreLoadTooltipImages(this);
1328
-
1329
-
1330
- /**
1331
- * This installs the window mousedown event listener that lears any
1332
- * highlight that may be visible.
1333
- */
1334
- RG.InstallWindowMousedownTooltipListener(this);
1335
-
1336
-
1337
- /**
1338
- * This installs the canvas mousemove event listener. This function
1339
- * controls the pointer shape.
1340
- */
1341
- RG.InstallCanvasMousemoveTooltipListener(this);
1342
-
1343
-
1344
- /**
1345
- * This installs the canvas mouseup event listener. This is the
1346
- * function that actually shows the appropriate tooltip (if any).
1347
- */
1348
- RG.InstallCanvasMouseupTooltipListener(this);
1349
- };
1350
-
1351
-
1352
-
1353
-
1354
- /**
1355
- * Each object type has its own Highlight() function which highlights the appropriate shape
1356
- *
1357
- * @param object shape The shape to highlight
1358
- */
1359
- this.highlight =
1360
- this.Highlight = function (shape)
1361
- {
1362
- if (prop['chart.tooltips.highlight']) {
1363
-
1364
-
1365
- if (typeof prop['chart.highlight.style'] === 'function'){
1366
- (prop['chart.highlight.style'])(shape);
1367
- return;
1368
- }
1369
-
1370
-
1371
- // Add the new segment highlight
1372
- co.beginPath();
1373
-
1374
- co.strokeStyle = prop['chart.highlight.stroke'];
1375
- co.fillStyle = prop['chart.highlight.fill'];
1376
-
1377
- co.arc(
1378
- shape['x'],
1379
- shape['y'],//- (prop['chart.variant'].indexOf('3d') !== -1 ? prop['chart.variant.threed.depth'] : 0),
1380
- shape['radius.end'],
1381
- shape['angle.start'],
1382
- shape['angle.end'],
1383
- false
1384
- );
1385
-
1386
- if (shape['radius.start'] > 0) {
1387
- co.arc(
1388
- shape['x'],
1389
- shape['y'],
1390
- shape['radius.start'],
1391
- shape['angle.end'],
1392
- shape['angle.start'],
1393
- true
1394
- );
1395
- } else {
1396
- co.lineTo(
1397
- shape['x'],
1398
- shape['y']
1399
- );
1400
- }
1401
- co.closePath();
1402
-
1403
- co.stroke();
1404
- co.fill();
1405
- }
1406
- };
1407
-
1408
-
1409
-
1410
-
1411
- /**
1412
- * The getObjectByXY() worker method. Don't call this call:
1413
- *
1414
- * RGraph.ObjectRegistry.getObjectByXY(e)
1415
- *
1416
- * @param object e The event object
1417
- */
1418
- this.getObjectByXY = function (e)
1419
- {
1420
- var mouseXY = RGraph.getMouseXY(e);
1421
-
1422
- // Work out the radius
1423
- var radius = RG.getHypLength(this.centerx, this.centery, mouseXY[0], mouseXY[1]);
1424
-
1425
- // Account for the 3D stretching effect
1426
- if (prop['chart.variant'].indexOf('3d') !== -1) {
1427
- radius /= -1;
1428
- }
1429
-
1430
- if (
1431
- mouseXY[0] > (this.centerx - this.radius)
1432
- && mouseXY[0] < (this.centerx + this.radius)
1433
- && mouseXY[1] > (this.centery - this.radius)
1434
- && mouseXY[1] < (this.centery + this.radius)
1435
- && radius <= this.radius
1436
- ) {
1437
-
1438
- return this;
1439
- }
1440
- };
1441
-
1442
-
1443
-
1444
-
1445
- /**
1446
- * This function positions a tooltip when it is displayed
1447
- *
1448
- * @param obj object The chart object
1449
- * @param int x The X coordinate specified for the tooltip
1450
- * @param int y The Y coordinate specified for the tooltip
1451
- * @param objec tooltip The tooltips DIV element
1452
- */
1453
- this.positionTooltip = function (obj, x, y, tooltip, idx)
1454
- {
1455
- var centerX = this.angles[idx][4],
1456
- centerY = this.angles[idx][5] - (prop['chart.variant'].indexOf('3d') !== -1 ? prop['chart.variant.threed.depth'] : 0),
1457
- radiusStart = this.angles[idx][2],
1458
- radiusEnd = this.angles[idx][3],
1459
- coordX = this.angles[idx][4],
1460
- coordY = this.angles[idx][5] - (prop['chart.variant'].indexOf('3d') !== -1 ? prop['chart.variant.threed.depth'] : 0),
1461
- angleStart = this.angles[idx][0],
1462
- angleEnd = this.angles[idx][1],
1463
- radius = ((radiusEnd - radiusStart) / 2) + radiusStart,
1464
- angleCenter = ((angleEnd - angleStart) / 2) + angleStart,
1465
- canvasXY = RG.getCanvasXY(this.canvas),
1466
- mouseXY = RG.getMouseXY(window.event),
1467
- gutterLeft = this.gutterLeft,
1468
- gutterTop = this.gutterTop,
1469
- width = tooltip.offsetWidth,
1470
- height = tooltip.offsetHeight
1471
-
1472
-
1473
- // Set the top position
1474
- tooltip.style.left = 0;
1475
- tooltip.style.top = window.event.pageY - height - 5 + 'px';
1476
-
1477
- // By default any overflow is hidden
1478
- tooltip.style.overflow = '';
1479
-
1480
- // Reposition the tooltip if at the edges:
1481
-
1482
- // LEFT edge
1483
- if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
1484
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
1485
-
1486
- // RIGHT edge
1487
- } else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
1488
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
1489
-
1490
- // Default positioning - CENTERED
1491
- } else {
1492
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
1493
- }
1494
- };
1495
-
1496
-
1497
-
1498
-
1499
- /**
1500
- * This method gives you the relevant radius for a particular value
1501
- *
1502
- * @param number value The relevant value to get the radius for
1503
- */
1504
- this.getRadius = function (value)
1505
- {
1506
- // Range checking (the Rose minimum is always 0)
1507
- if (value < 0 || value > this.max) {
1508
- return null;
1509
- }
1510
-
1511
- var r = (value / this.max) * this.radius;
1512
-
1513
- return r;
1514
- };
1515
-
1516
-
1517
-
1518
-
1519
- /**
1520
- * This allows for easy specification of gradients
1521
- */
1522
- this.parseColors = function ()
1523
- {
1524
- // Save the original colors so that they can be restored when the canvas is reset
1525
- if (this.original_colors.length === 0) {
1526
- this.original_colors['chart.colors'] = RG.array_clone(prop['chart.colors']);
1527
- this.original_colors['chart.key.colors'] = RG.array_clone(prop['chart.key.colors']);
1528
- this.original_colors['chart.text.color'] = RG.array_clone(prop['chart.text.color']);
1529
- this.original_colors['chart.title.color'] = RG.array_clone(prop['chart.title.color']);
1530
- this.original_colors['chart.highlight.stroke'] = RG.array_clone(prop['chart.highlight.stroke']);
1531
- this.original_colors['chart.highlight.fill'] = RG.array_clone(prop['chart.highlight.fill']);
1532
- }
1533
-
1534
-
1535
-
1536
-
1537
-
1538
-
1539
-
1540
-
1541
-
1542
-
1543
- for (var i=0; i<prop['chart.colors'].length; ++i) {
1544
- prop['chart.colors'][i] = this.parseSingleColorForGradient(prop['chart.colors'][i]);
1545
- }
1546
-
1547
- /**
1548
- * Key colors
1549
- */
1550
- if (!RG.is_null(prop['chart.key.colors'])) {
1551
- for (var i=0; i<prop['chart.key.colors'].length; ++i) {
1552
- prop['chart.key.colors'][i] = this.parseSingleColorForGradient(prop['chart.key.colors'][i]);
1553
- }
1554
- }
1555
-
1556
- prop['chart.text.color'] = this.parseSingleColorForGradient(prop['chart.text.color']);
1557
- prop['chart.title.color'] = this.parseSingleColorForGradient(prop['chart.title.color']);
1558
- prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
1559
- prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
1560
- prop['chart.segment.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.segment.highlight.stroke']);
1561
- prop['chart.segment.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.segment.highlight.fill']);
1562
- };
1563
-
1564
-
1565
-
1566
-
1567
- /**
1568
- * Use this function to reset the object to the post-constructor state. Eg reset colors if
1569
- * need be etc
1570
- */
1571
- this.reset = function ()
1572
- {
1573
- };
1574
-
1575
-
1576
-
1577
-
1578
- /**
1579
- * This parses a single color value
1580
- */
1581
- this.parseSingleColorForGradient = function (color)
1582
- {
1583
- if (!color || typeof(color) != 'string') {
1584
- return color;
1585
- }
1586
-
1587
- if (color.match(/^gradient\((.*)\)$/i)) {
1588
-
1589
- var parts = RegExp.$1.split(':');
1590
-
1591
- // Create the gradient
1592
- //var grad = context.createLinearGradient(0,0,canvas.width,0);
1593
- var grad = co.createRadialGradient(this.centerx, this.centery, 0, this.centerx, this.centery, this.radius);
1594
-
1595
- var diff = 1 / (parts.length - 1);
1596
-
1597
- grad.addColorStop(0, RG.trim(parts[0]));
1598
-
1599
- for (var j=1; j<parts.length; ++j) {
1600
- grad.addColorStop(j * diff, RG.trim(parts[j]));
1601
- }
1602
- }
1603
-
1604
- return grad ? grad : color;
1605
- };
1606
-
1607
-
1608
-
1609
-
1610
- /**
1611
- * This function handles highlighting an entire data-series for the interactive
1612
- * key
1613
- *
1614
- * @param int index The index of the data series to be highlighted
1615
- */
1616
- this.interactiveKeyHighlight = function (index)
1617
- {
1618
- var segments = this.angles2;
1619
-
1620
- for (var i=0; i<this.angles2.length; i+=1) {
1621
- co.beginPath();
1622
- co.lineWidth = 2;
1623
- co.fillStyle = prop['chart.key.interactive.highlight.chart.fill'];
1624
- co.strokeStyle = prop['chart.key.interactive.highlight.chart.stroke'];
1625
- co.arc(segments[i][index][4], segments[i][index][5], segments[i][index][2], segments[i][index][0], segments[i][index][1], false);
1626
- co.arc(segments[i][index][4], segments[i][index][5], segments[i][index][3], segments[i][index][1], segments[i][index][0], true);
1627
- co.closePath();
1628
- co.fill();
1629
- co.stroke();
1630
- }
1631
-
1632
- return/*
1633
- if (segments) {
1634
- for (var i=0; i<segments.length; i+=1) {
1635
-
1636
- }
1637
- }
1638
- */
1639
- };
1640
-
1641
-
1642
-
1643
-
1644
- /**
1645
- * Using a function to add events makes it easier to facilitate method chaining
1646
- *
1647
- * @param string type The type of even to add
1648
- * @param function func
1649
- */
1650
- this.on = function (type, func)
1651
- {
1652
- if (type.substr(0,2) !== 'on') {
1653
- type = 'on' + type;
1654
- }
1655
-
1656
- this[type] = func;
1657
-
1658
- return this;
1659
- };
1660
-
1661
-
1662
-
1663
-
1664
- /**
1665
- * This function runs once only
1666
- * (put at the end of the file (before any effects))
1667
- */
1668
- this.firstDrawFunc = function ()
1669
- {
1670
- };
1671
-
1672
-
1673
-
1674
-
1675
- /**
1676
- * Rose chart explode
1677
- *
1678
- * Explodes the Rose chart - gradually incrementing the size of the chart.explode property
1679
- *
1680
- * @param object Optional options for the effect. You can pass in frames here - such as:
1681
- * myRose.roundRobin({frames: 60}; function () {alert('Done!');})
1682
- * @param function A callback function which is called when the effect is finished
1683
- */
1684
- this.explode = function ()
1685
- {
1686
- var obj = this;
1687
- var opt = arguments[0] || {};
1688
- var callback = arguments[1] || function (){};
1689
- var frames = opt.frames ? opt.frames : 30;
1690
- var frame = 0;
1691
- var explodedMax = ma.max(ca.width, ca.height);
1692
- var exploded = Number(this.Get('exploded'));
1693
-
1694
-
1695
-
1696
-
1697
- function iterator ()
1698
- {
1699
- exploded = (frame / frames) * explodedMax;
1700
-
1701
- // Set the new value
1702
- obj.Set('exploded', exploded);
1703
-
1704
- RG.clear(ca);
1705
- RG.redrawCanvas(ca);
1706
-
1707
- if (frame++ < frames) {
1708
- RG.Effects.updateCanvas(iterator);
1709
- } else {
1710
- callback(obj);
1711
- }
1712
- }
1713
-
1714
-
1715
-
1716
-
1717
- iterator();
1718
-
1719
- return this;
1720
- };
1721
-
1722
-
1723
-
1724
-
1725
- /**
1726
- * RoundRobin
1727
- *
1728
- * This effect is similar to the Pie chart RoundRobin effect
1729
- *
1730
- * @param object Optional options for the effect. You can pass in frames here - such as:
1731
- * myRose.roundRobin({frames: 60}; function () {alert('Done!');})
1732
- * @param function A callback function which is called when the effect is finished
1733
- */
1734
- this.roundrobin =
1735
- this.roundRobin = function ()
1736
- {
1737
- var obj = this;
1738
- var opt = arguments[0] || {}
1739
- var frames = opt.frames || 30;
1740
- var frame = 0;
1741
- var original_margin = prop['chart.margin'];
1742
- var margin = (360 / this.data.length) / 2;
1743
- var callback = arguments[1] || function () {};
1744
-
1745
- this.Set('chart.margin', margin);
1746
- this.Set('chart.animation.roundrobin.factor', 0);
1747
-
1748
- function iterator ()
1749
- {
1750
- RG.clear(obj.canvas);
1751
- RG.redrawCanvas(obj.canvas);
1752
-
1753
- if (frame++ < frames) {
1754
- obj.set('animation.roundrobin.factor', frame / frames);
1755
- obj.set('margin', (frame / frames) * original_margin);
1756
- RG.Effects.updateCanvas(iterator);
1757
- } else {
1758
- obj.set('animation.roundrobin.factor', 1);
1759
- obj.set('margin', original_margin);
1760
-
1761
- callback(obj);
1762
- }
1763
- }
1764
-
1765
- iterator();
1766
-
1767
- return this;
1768
- };
1769
-
1770
-
1771
-
1772
-
1773
- /**
1774
- * Rose chart implode
1775
- *
1776
- * Implodes the Rose chart - gradually decreasing the size of the chart.explode property. It starts at the largest of
1777
- * the canvas width./height
1778
- *
1779
- * @param object Optional options for the effect. You can pass in frames here - such as:
1780
- * myRose.implode({frames: 60}; function () {alert('Done!');})
1781
- * @param function A callback function which is called when the effect is finished
1782
- */
1783
- this.implode = function ()
1784
- {
1785
- var obj = this;
1786
- var opt = arguments[0] || {};
1787
- var callback = arguments[1] || function (){};
1788
- var frames = opt.frames || 30;
1789
- var frame = 0;
1790
- var explodedMax = ma.max(ca.width, ca.height);
1791
- var exploded = explodedMax;
1792
-
1793
-
1794
-
1795
- function iterator ()
1796
- {
1797
- exploded = explodedMax - ((frame / frames) * explodedMax);
1798
-
1799
- // Set the new value
1800
- obj.Set('exploded', exploded);
1801
-
1802
- RG.clear(ca);
1803
- RG.redrawCanvas(ca);
1804
-
1805
- if (frame++ < frames) {
1806
- RG.Effects.updateCanvas(iterator);
1807
- } else {
1808
- RG.clear(obj.canvas);
1809
- RG.redrawCanvas(obj.canvas);
1810
- callback(obj);
1811
- }
1812
- }
1813
-
1814
- iterator();
1815
-
1816
- return this;
1817
- };
1818
-
1819
-
1820
-
1821
-
1822
- /**
1823
- * Rose chart Grow
1824
- *
1825
- * This effect gradually increases the size of the Rose chart
1826
- *
1827
- * @param object Optional options for the effect. You can pass in frames here - such as:
1828
- * myRose.grow({frames: 60}; function () {alert('Done!');})
1829
- * @param function A callback function which is called when the effect is finished
1830
- */
1831
- this.grow = function ()
1832
- {
1833
- var obj = this;
1834
- var opt = arguments[0] || {};
1835
- var callback = arguments[1] || function (){};
1836
- var frames = opt.frames || 30;
1837
- var frame = 0;
1838
-
1839
- function iterator ()
1840
- {
1841
- obj.Set('animation.grow.multiplier', frame / frames);
1842
-
1843
- RG.clear(ca);
1844
- RG.redrawCanvas(ca);
1845
-
1846
- if (frame < frames) {
1847
- frame++;
1848
- RG.Effects.updateCanvas(iterator);
1849
- } else {
1850
- callback(obj);
1851
- }
1852
- }
1853
-
1854
- iterator();
1855
-
1856
- return this;
1857
- };
1858
-
1859
-
1860
-
1861
-
1862
- /**
1863
- * Register this object
1864
- */
1865
- RG.Register(this);
1866
-
1867
-
1868
-
1869
-
1870
- /**
1871
- * This is the 'end' of the constructor so if the first argument
1872
- * contains configuration data - handle that.
1873
- */
1874
- if (parseConfObjectForOptions) {
1875
- RG.parseObjectStyleConfig(this, conf.options);
1876
- }
1877
- };