rgraph-rails 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +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
- };