rgraph-rails 1.0.1

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 (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/CODE_OF_CONDUCT.md +13 -0
  6. data/Gemfile +4 -0
  7. data/README.md +73 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +7 -0
  11. data/lib/rgraph-rails/version.rb +3 -0
  12. data/lib/rgraph-rails.rb +8 -0
  13. data/license.txt +19 -0
  14. data/rgraph-rails.gemspec +26 -0
  15. data/vendor/assets/images/bg.png +0 -0
  16. data/vendor/assets/images/bullet.png +0 -0
  17. data/vendor/assets/images/facebook-large.png +0 -0
  18. data/vendor/assets/images/google-plus-large.png +0 -0
  19. data/vendor/assets/images/logo.png +0 -0
  20. data/vendor/assets/images/meter-image-sd-needle.png +0 -0
  21. data/vendor/assets/images/meter-image-sd.png +0 -0
  22. data/vendor/assets/images/meter-sketch-needle.png +0 -0
  23. data/vendor/assets/images/meter-sketch.png +0 -0
  24. data/vendor/assets/images/odometer-background.png +0 -0
  25. data/vendor/assets/images/rgraph.jpg +0 -0
  26. data/vendor/assets/images/title.png +0 -0
  27. data/vendor/assets/images/twitter-large.png +0 -0
  28. data/vendor/assets/javascripts/RGraph.bar.js +3246 -0
  29. data/vendor/assets/javascripts/RGraph.bipolar.js +2003 -0
  30. data/vendor/assets/javascripts/RGraph.common.annotate.js +399 -0
  31. data/vendor/assets/javascripts/RGraph.common.context.js +600 -0
  32. data/vendor/assets/javascripts/RGraph.common.core.js +4751 -0
  33. data/vendor/assets/javascripts/RGraph.common.csv.js +275 -0
  34. data/vendor/assets/javascripts/RGraph.common.deprecated.js +454 -0
  35. data/vendor/assets/javascripts/RGraph.common.dynamic.js +1194 -0
  36. data/vendor/assets/javascripts/RGraph.common.effects.js +1524 -0
  37. data/vendor/assets/javascripts/RGraph.common.key.js +735 -0
  38. data/vendor/assets/javascripts/RGraph.common.resizing.js +550 -0
  39. data/vendor/assets/javascripts/RGraph.common.tooltips.js +605 -0
  40. data/vendor/assets/javascripts/RGraph.common.zoom.js +223 -0
  41. data/vendor/assets/javascripts/RGraph.drawing.background.js +636 -0
  42. data/vendor/assets/javascripts/RGraph.drawing.circle.js +579 -0
  43. data/vendor/assets/javascripts/RGraph.drawing.image.js +810 -0
  44. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +710 -0
  45. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +672 -0
  46. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +568 -0
  47. data/vendor/assets/javascripts/RGraph.drawing.poly.js +623 -0
  48. data/vendor/assets/javascripts/RGraph.drawing.rect.js +603 -0
  49. data/vendor/assets/javascripts/RGraph.drawing.text.js +648 -0
  50. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +815 -0
  51. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +860 -0
  52. data/vendor/assets/javascripts/RGraph.fuel.js +965 -0
  53. data/vendor/assets/javascripts/RGraph.funnel.js +988 -0
  54. data/vendor/assets/javascripts/RGraph.gantt.js +1242 -0
  55. data/vendor/assets/javascripts/RGraph.gauge.js +1391 -0
  56. data/vendor/assets/javascripts/RGraph.hbar.js +1794 -0
  57. data/vendor/assets/javascripts/RGraph.hprogress.js +1307 -0
  58. data/vendor/assets/javascripts/RGraph.line.js +3940 -0
  59. data/vendor/assets/javascripts/RGraph.meter.js +1242 -0
  60. data/vendor/assets/javascripts/RGraph.modaldialog.js +292 -0
  61. data/vendor/assets/javascripts/RGraph.odo.js +1265 -0
  62. data/vendor/assets/javascripts/RGraph.pie.js +1979 -0
  63. data/vendor/assets/javascripts/RGraph.radar.js +1840 -0
  64. data/vendor/assets/javascripts/RGraph.rose.js +1860 -0
  65. data/vendor/assets/javascripts/RGraph.rscatter.js +1332 -0
  66. data/vendor/assets/javascripts/RGraph.scatter.js +3029 -0
  67. data/vendor/assets/javascripts/RGraph.thermometer.js +1131 -0
  68. data/vendor/assets/javascripts/RGraph.vprogress.js +1326 -0
  69. data/vendor/assets/javascripts/RGraph.waterfall.js +1252 -0
  70. data/vendor/assets/javascripts/financial-data.js +1067 -0
  71. data/vendor/assets/stylesheets/ModalDialog.css +90 -0
  72. data/vendor/assets/stylesheets/animations.css +3347 -0
  73. data/vendor/assets/stylesheets/website.css +402 -0
  74. metadata +175 -0
@@ -0,0 +1,1332 @@
1
+ // version: 2015-11-02
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
+
18
+ /**
19
+ * The chart constuctor
20
+ *
21
+ * @param object canvas
22
+ * @param array data
23
+ */
24
+ RGraph.RScatter =
25
+ RGraph.Rscatter = function (conf)
26
+ {
27
+ /**
28
+ * Allow for object config style
29
+ */
30
+ if ( typeof conf === 'object'
31
+ && typeof conf.data === 'object'
32
+ && typeof conf.id === 'string') {
33
+
34
+ var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
35
+
36
+ this.data = new Array(conf.data.length);
37
+
38
+ // Store the data set(s)
39
+ this.data = RGraph.arrayClone(conf.data);
40
+
41
+
42
+ // Account for just one dataset being given
43
+ if (typeof conf.data === 'object' && typeof conf.data[0] === 'object' && typeof conf.data[0][0] === 'number') {
44
+ var tmp = RGraph.arrayClone(conf.data);
45
+ conf.data = new Array();
46
+ conf.data[0] = RGraph.arrayClone(tmp);
47
+
48
+ this.data = RGraph.arrayClone(conf.data);
49
+ }
50
+
51
+ } else {
52
+
53
+ var conf = {id: conf};
54
+ conf.data = arguments[1];
55
+
56
+
57
+ this.data = [];
58
+
59
+ // Handle multiple datasets being given as one argument
60
+ if (arguments[1][0] && arguments[1][0][0] && typeof arguments[1][0][0] == 'object') {
61
+ // Store the data set(s)
62
+ for (var i=0; i<arguments[1].length; ++i) {
63
+ this.data[i] = arguments[1][i];
64
+ }
65
+
66
+ // Handle multiple data sets being supplied as seperate arguments
67
+ } else {
68
+
69
+ // Store the data set(s)
70
+ for (var i=1; i<arguments.length; ++i) {
71
+ this.data[i - 1] = RGraph.arrayClone(arguments[i]);
72
+ }
73
+ }
74
+ }
75
+
76
+
77
+
78
+
79
+ this.id = conf.id
80
+ this.canvas = document.getElementById(this.id)
81
+ this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null;
82
+ this.canvas.__object__ = this;
83
+ this.type = 'rscatter';
84
+ this.hasTooltips = false;
85
+ this.isRGraph = true;
86
+ this.uid = RGraph.CreateUID();
87
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
88
+ this.colorsParsed = false;
89
+ this.coordsText = [];
90
+ this.original_colors = [];
91
+ this.firstDraw = true; // After the first draw this will be false
92
+
93
+
94
+ /**
95
+ * Compatibility with older browsers
96
+ */
97
+ //RGraph.OldBrowserCompat(this.context);
98
+
99
+
100
+ this.centerx = 0;
101
+ this.centery = 0;
102
+ this.radius = 0;
103
+ this.max = 0;
104
+
105
+ this.properties =
106
+ {
107
+ 'chart.background.color': 'transparent',
108
+ 'chart.background.grid': true,
109
+ 'chart.background.grid.diagonals': true,
110
+ 'chart.background.grid.diagonals.count': null,
111
+ 'chart.background.grid.radials': true,
112
+ 'chart.background.grid.radials.count': null,
113
+ 'chart.background.grid.linewidth': 1,
114
+ 'chart.background.grid.color': '#ccc',
115
+ 'chart.radius': null,
116
+ 'chart.colors': [], // This is used internally for the key
117
+ 'chart.colors.default': 'black',
118
+ 'chart.gutter.left': 25,
119
+ 'chart.gutter.right': 25,
120
+ 'chart.gutter.top': 25,
121
+ 'chart.gutter.bottom': 25,
122
+ 'chart.title': '',
123
+ 'chart.title.background': null,
124
+ 'chart.title.hpos': null,
125
+ 'chart.title.vpos': null,
126
+ 'chart.title.bold': true,
127
+ 'chart.title.font': null,
128
+ 'chart.title.x': null,
129
+ 'chart.title.y': null,
130
+ 'chart.title.halign': null,
131
+ 'chart.title.valign': null,
132
+ 'chart.labels': null,
133
+ 'chart.labels.color': null,
134
+ 'chart.labels.axes': 'nsew',
135
+ 'chart.labels.axes.background': 'rgba(255,255,255,0.8)',
136
+ 'chart.labels.count': 5,
137
+ 'chart.text.color': 'black',
138
+ 'chart.text.font': 'Arial',
139
+ 'chart.text.size': 12,
140
+ 'chart.key': null,
141
+ 'chart.key.background': 'white',
142
+ 'chart.key.position': 'graph',
143
+ 'chart.key.halign': 'right',
144
+ 'chart.key.shadow': false,
145
+ 'chart.key.shadow.color': '#666',
146
+ 'chart.key.shadow.blur': 3,
147
+ 'chart.key.shadow.offsetx': 2,
148
+ 'chart.key.shadow.offsety': 2,
149
+ 'chart.key.position.gutter.boxed':false,
150
+ 'chart.key.position.x': null,
151
+ 'chart.key.position.y': null,
152
+ 'chart.key.color.shape': 'square',
153
+ 'chart.key.rounded': true,
154
+ 'chart.key.linewidth': 1,
155
+ 'chart.key.colors': null,
156
+ 'chart.key.interactive': false,
157
+ 'chart.key.interactive.highlight.chart.fill':'rgba(255,0,0,0.9)',
158
+ 'chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)',
159
+ 'chart.key.text.color': 'black',
160
+ 'chart.contextmenu': null,
161
+ 'chart.tooltips': null,
162
+ 'chart.tooltips.event': 'onmousemove',
163
+ 'chart.tooltips.effect': 'fade',
164
+ 'chart.tooltips.css.class': 'RGraph_tooltip',
165
+ 'chart.tooltips.highlight': true,
166
+ 'chart.tooltips.hotspot': 3,
167
+ 'chart.tooltips.coords.page': false,
168
+ 'chart.annotatable': false,
169
+ 'chart.annotate.color': 'black',
170
+ 'chart.zoom.factor': 1.5,
171
+ 'chart.zoom.fade.in': true,
172
+ 'chart.zoom.fade.out': true,
173
+ 'chart.zoom.hdir': 'right',
174
+ 'chart.zoom.vdir': 'down',
175
+ 'chart.zoom.frames': 25,
176
+ 'chart.zoom.delay': 16.666,
177
+ 'chart.zoom.shadow': true,
178
+ 'chart.zoom.background': true,
179
+ 'chart.zoom.action': 'zoom',
180
+ 'chart.resizable': false,
181
+ 'chart.resize.handle.background': null,
182
+ 'chart.ymax': null,
183
+ 'chart.ymin': 0,
184
+ 'chart.tickmarks': 'cross',
185
+ 'chart.ticksize': 3,
186
+ 'chart.scale.decimals': null,
187
+ 'chart.scale.point': '.',
188
+ 'chart.scale.thousand': ',',
189
+ 'chart.scale.round': false,
190
+ 'chart.scale.zerostart': true,
191
+ 'chart.units.pre': '',
192
+ 'chart.units.post': '',
193
+ 'chart.events.mousemove': null,
194
+ 'chart.events.click': null,
195
+ 'chart.highlight.stroke': 'transparent',
196
+ 'chart.highlight.fill': 'rgba(255,255,255,0.7)',
197
+ 'chart.highlight.point.radius': 3,
198
+ 'chart.axes.color': 'black',
199
+ 'chart.axes.numticks': null,
200
+ 'chart.axes.caps': true,
201
+ 'chart.segment.highlight': false,
202
+ 'chart.segment.highlight.count': null,
203
+ 'chart.segment.highlight.fill': 'rgba(0,255,0,0.5)',
204
+ 'chart.segment.highlight.stroke':'rgba(0,0,0,0)'
205
+ }
206
+
207
+
208
+
209
+
210
+ /**
211
+ * Create the $ objects so that functions can be added to them
212
+ */
213
+
214
+ for (var i=0,idx=0; i<this.data.length; ++i) {
215
+ for (var j=0,len=this.data[i].length; j<len; j+=1,idx+=1) {
216
+ this['$' + idx] = {}
217
+ }
218
+ }
219
+
220
+
221
+
222
+
223
+
224
+ /**
225
+ * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
226
+ * done already
227
+ */
228
+ if (!this.canvas.__rgraph_aa_translated__) {
229
+ this.context.translate(0.5,0.5);
230
+
231
+ this.canvas.__rgraph_aa_translated__ = true;
232
+ }
233
+
234
+
235
+
236
+ // Short variable names
237
+ var RG = RGraph,
238
+ ca = this.canvas,
239
+ co = ca.getContext('2d'),
240
+ prop = this.properties,
241
+ pa = RG.Path,
242
+ pa2 = RG.path2,
243
+ win = window,
244
+ doc = document,
245
+ ma = Math
246
+
247
+
248
+
249
+ /**
250
+ * "Decorate" the object with the generic effects if the effects library has been included
251
+ */
252
+ if (RG.Effects && typeof RG.Effects.decorate === 'function') {
253
+ RG.Effects.decorate(this);
254
+ }
255
+
256
+
257
+
258
+
259
+ /**
260
+ * A simple setter
261
+ *
262
+ * @param string name The name of the property to set
263
+ * @param string value The value of the property
264
+ */
265
+ this.set =
266
+ this.Set = function (name, value)
267
+ {
268
+ var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
269
+
270
+ /**
271
+ * the number of arguments is only one and it's an
272
+ * object - parse it for configuration data and return.
273
+ */
274
+ if (arguments.length === 1 && typeof name === 'object') {
275
+ RG.parseObjectStyleConfig(this, name);
276
+ return this;
277
+ }
278
+
279
+
280
+
281
+ /**
282
+ * This should be done first - prepend the property name with "chart." if necessary
283
+ */
284
+ if (name.substr(0,6) != 'chart.') {
285
+ name = 'chart.' + name;
286
+ }
287
+
288
+
289
+
290
+
291
+ // Convert uppercase letters to dot+lower case letter
292
+ name = name.replace(/([A-Z])/g, function (str)
293
+ {
294
+ return '.' + String(RegExp.$1).toLowerCase();
295
+ });
296
+
297
+
298
+
299
+
300
+
301
+
302
+
303
+ //
304
+ // Change chart.segments.highlight* to chart.segment.highlight (no plural)
305
+ //
306
+ if (name === 'chart.segments.highlight') name = 'chart.segment.highlight';
307
+ if (name === 'chart.segments.highlight.count') name = 'chart.segment.highlight.count';
308
+ if (name === 'chart.segments.highlight.fill') name = 'chart.segment.highlight.fill';
309
+ if (name === 'chart.segments.highlight.stroke') name = 'chart.segment.highlight.stroke';
310
+
311
+ prop[name.toLowerCase()] = value;
312
+
313
+ return this;
314
+ };
315
+
316
+
317
+
318
+
319
+ /**
320
+ * A simple getter
321
+ *
322
+ * @param string name The name of the property to get
323
+ */
324
+ this.get =
325
+ this.Get = function (name)
326
+ {
327
+ /**
328
+ * This should be done first - prepend the property name with "chart." if necessary
329
+ */
330
+ if (name.substr(0,6) != 'chart.') {
331
+ name = 'chart.' + name;
332
+ }
333
+
334
+ // Convert uppercase letters to dot+lower case letter
335
+ name = name.replace(/([A-Z])/g, function (str)
336
+ {
337
+ return '.' + String(RegExp.$1).toLowerCase()
338
+ });
339
+
340
+ return prop[name.toLowerCase()];
341
+ };
342
+
343
+
344
+
345
+
346
+ /**
347
+ * This method draws the rose chart
348
+ */
349
+ this.draw =
350
+ this.Draw = function ()
351
+ {
352
+ /**
353
+ * Fire the onbeforedraw event
354
+ */
355
+ RG.FireCustomEvent(this, 'onbeforedraw');
356
+
357
+
358
+ /**
359
+ * This doesn't affect the chart, but is used for compatibility
360
+ */
361
+ this.gutterLeft = prop['chart.gutter.left'];
362
+ this.gutterRight = prop['chart.gutter.right'];
363
+ this.gutterTop = prop['chart.gutter.top'];
364
+ this.gutterBottom = prop['chart.gutter.bottom'];
365
+
366
+ // Calculate the radius
367
+ this.radius = (Math.min(ca.width - this.gutterLeft - this.gutterRight, ca.height - this.gutterTop - this.gutterBottom) / 2);
368
+ this.centerx = ((ca.width - this.gutterLeft - this.gutterRight) / 2) + this.gutterLeft;
369
+ this.centery = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
370
+ this.coords = [];
371
+ this.coords2 = [];
372
+
373
+
374
+
375
+ /**
376
+ * Stop this growing uncontrollably
377
+ */
378
+ this.coordsText = [];
379
+
380
+
381
+
382
+
383
+ /**
384
+ * If there's a user specified radius/centerx/centery, use them
385
+ */
386
+ if (typeof(prop['chart.centerx']) == 'number') this.centerx = prop['chart.centerx'];
387
+ if (typeof(prop['chart.centery']) == 'number') this.centery = prop['chart.centery'];
388
+ if (typeof(prop['chart.radius']) == 'number') this.radius = prop['chart.radius'];
389
+
390
+
391
+
392
+ /**
393
+ * Parse the colors for gradients. Its down here so that the center X/Y can be used
394
+ */
395
+ if (!this.colorsParsed) {
396
+
397
+ this.parseColors();
398
+
399
+ // Don't want to do this again
400
+ this.colorsParsed = true;
401
+ }
402
+
403
+
404
+ /**
405
+ * Work out the scale
406
+ */
407
+ var max = prop['chart.ymax'];
408
+ var min = prop['chart.ymin'];
409
+
410
+ if (typeof(max) == 'number') {
411
+ this.max = max;
412
+ this.scale2 = RG.getScale2(this, {
413
+ 'max':max,
414
+ 'min':min,
415
+ 'strict':true,
416
+ 'scale.decimals':Number(prop['chart.scale.decimals']),
417
+ 'scale.point':prop['chart.scale.point'],
418
+ 'scale.thousand':prop['chart.scale.thousand'],
419
+ 'scale.round':prop['chart.scale.round'],
420
+ 'units.pre':prop['chart.units.pre'],
421
+ 'units.post':prop['chart.units.post'],
422
+ 'ylabels.count':prop['chart.labels.count']
423
+ });
424
+ } else {
425
+
426
+ for (var i=0; i<this.data.length; i+=1) {
427
+ for (var j=0,len=this.data[i].length; j<len; j+=1) {
428
+ this.max = Math.max(this.max, this.data[i][j][1]);
429
+ }
430
+ }
431
+
432
+ this.min = prop['chart.ymin'];
433
+
434
+ this.scale2 = RG.getScale2(this, {
435
+ 'max':this.max,
436
+ 'min':min,
437
+ 'scale.decimals':Number(prop['chart.scale.decimals']),
438
+ 'scale.point':prop['chart.scale.point'],
439
+ 'scale.thousand':prop['chart.scale.thousand'],
440
+ 'scale.round':prop['chart.scale.round'],
441
+ 'units.pre':prop['chart.units.pre'],
442
+ 'units.post':prop['chart.units.post'],
443
+ 'ylabels.count':prop['chart.labels.count']
444
+ });
445
+ this.max = this.scale2.max;
446
+ }
447
+
448
+ /**
449
+ * Change the centerx marginally if the key is defined
450
+ */
451
+ if (prop['chart.key'] && prop['chart.key'].length > 0 && prop['chart.key'].length >= 3) {
452
+ this.centerx = this.centerx - prop['chart.gutter.right'] + 5;
453
+ }
454
+
455
+ /**
456
+ * Populate the colors array for the purposes of generating the key
457
+ */
458
+ if (typeof(prop['chart.key']) == 'object' && RG.is_array(prop['chart.key']) && prop['chart.key'][0]) {
459
+
460
+ // Reset the colors array
461
+ prop['chart.colors'] = [];
462
+
463
+ for (var i=0; i<this.data.length; i+=1) {
464
+ for (var j=0,len=this.data[i].length; j<len; j+=1) {
465
+ if (typeof this.data[i][j][2] == 'string') {
466
+ prop['chart.colors'].push(this.data[i][j][2]);
467
+ }
468
+ }
469
+ }
470
+ }
471
+
472
+
473
+
474
+
475
+ /**
476
+ * Populate the chart.tooltips array
477
+ */
478
+ this.Set('chart.tooltips', []);
479
+
480
+ for (var i=0; i<this.data.length; i+=1) {
481
+ for (var j=0,len=this.data[i].length; j<len; j+=1) {
482
+ if (typeof this.data[i][j][3] == 'string') {
483
+ prop['chart.tooltips'].push(this.data[i][j][3]);
484
+ }
485
+ }
486
+ }
487
+
488
+
489
+
490
+ // This resets the chart drawing state
491
+ co.beginPath();
492
+
493
+ this.DrawBackground();
494
+ this.DrawRscatter();
495
+ this.DrawLabels();
496
+
497
+ /**
498
+ * Setup the context menu if required
499
+ */
500
+ if (prop['chart.contextmenu']) {
501
+ RG.ShowContext(this);
502
+ }
503
+
504
+
505
+
506
+ // Draw the title if any has been set
507
+ if (prop['chart.title']) {
508
+ RG.DrawTitle(
509
+ this,
510
+ prop['chart.title'],
511
+ this.centery - this.radius - 10,
512
+ this.centerx,
513
+ prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2
514
+ );
515
+ }
516
+
517
+
518
+ /**
519
+ * This function enables resizing
520
+ */
521
+ if (prop['chart.resizable']) {
522
+ RG.AllowResizing(this);
523
+ }
524
+
525
+
526
+ /**
527
+ * This installs the event listeners
528
+ */
529
+ RG.InstallEventListeners(this);
530
+
531
+
532
+
533
+
534
+
535
+
536
+ //
537
+ // Allow the segments to be highlighted
538
+ //
539
+ if (prop['chart.segment.highlight']) {
540
+ RG.allowSegmentHighlight({
541
+ object: this,
542
+
543
+ // This is duplicated in the drawBackground function
544
+ count: typeof prop['chart.segment.highlight.count'] === 'number' ? prop['chart.segment.highlight.count'] : ((prop['chart.background.grid.diagonals.count'] ? prop['chart.background.grid.diagonals.count'] : (prop['chart.labels'] ? prop['chart.labels'].length : 8))),
545
+
546
+ fill: prop['chart.segment.highlight.fill'],
547
+ stroke: prop['chart.segment.highlight.stroke']
548
+ });
549
+ }
550
+
551
+
552
+
553
+
554
+ /**
555
+ * Fire the onfirstdraw event
556
+ */
557
+ if (this.firstDraw) {
558
+ RG.fireCustomEvent(this, 'onfirstdraw');
559
+ this.firstDraw = false;
560
+ this.firstDrawFunc();
561
+ }
562
+
563
+
564
+
565
+
566
+ /**
567
+ * Fire the RGraph ondraw event
568
+ */
569
+ RG.FireCustomEvent(this, 'ondraw');
570
+
571
+
572
+
573
+
574
+ return this;
575
+ };
576
+
577
+
578
+
579
+
580
+ /**
581
+ * This method draws the rscatter charts background
582
+ */
583
+ this.drawBackground =
584
+ this.DrawBackground = function ()
585
+ {
586
+ //
587
+ // Draw the background color first
588
+ //
589
+ if (prop['chart.background.color'] != 'transparent') {
590
+ pa(co, ['b','a', this.centerx, this.centery, this.radius, 0, 2 * ma.PI, -1, 'f', prop['chart.background.color']]);
591
+ }
592
+
593
+
594
+ var gridEnabled = prop['chart.background.grid'];
595
+
596
+
597
+ if (gridEnabled) {
598
+ co.lineWidth = prop['chart.background.grid.linewidth'];
599
+
600
+
601
+
602
+ // Draw the background grey circles
603
+ if (prop['chart.background.grid.radials']) {
604
+
605
+ co.strokeStyle = prop['chart.background.grid.color'];
606
+
607
+ if (RG.isNull(prop['chart.background.grid.radials.count'])) {
608
+ prop['chart.background.grid.radials.count'] = prop['chart.labels.count'];
609
+ }
610
+
611
+ // Radius must be greater than 0 for Opera to work
612
+
613
+ var r = this.radius / prop['chart.background.grid.radials.count'];
614
+
615
+ for (var i=0,len=this.radius; i<=len; i+=r) {
616
+
617
+ // Radius must be greater than 0 for Opera to work
618
+ co.arc(this.centerx, this.centery, i, 0, RG.TWOPI, 0);
619
+ }
620
+ co.stroke();
621
+ }
622
+
623
+
624
+
625
+
626
+
627
+
628
+
629
+ // Draw the background lines that go from the center outwards
630
+ if (prop['chart.background.grid.diagonals']) {
631
+
632
+ co.strokeStyle = prop['chart.background.grid.color'];
633
+
634
+ co.beginPath();
635
+
636
+ // This is duplicated in the allowSegmentHighlight call
637
+ var inc = 360 / ((prop['chart.background.grid.diagonals.count'] ? prop['chart.background.grid.diagonals.count'] : (prop['chart.labels'] ? prop['chart.labels'].length : 8)));
638
+
639
+
640
+ for (var i=inc; i<360; i+=inc) {
641
+
642
+ // Radius must be greater than 0 for Opera to work
643
+ co.arc(
644
+ this.centerx,
645
+ this.centery,
646
+ this.radius,
647
+ (i / (180 / RG.PI)) - RG.HALFPI,
648
+ ((i + 0.01) / (180 / RG.PI)) - RG.HALFPI,
649
+ 0
650
+ );
651
+
652
+ co.lineTo(this.centerx, this.centery);
653
+ }
654
+ co.stroke();
655
+ }
656
+ }
657
+
658
+ // Reset the linewidth
659
+ co.lineWidth = 1;
660
+
661
+
662
+
663
+
664
+
665
+
666
+
667
+
668
+
669
+
670
+
671
+
672
+
673
+ co.beginPath();
674
+ co.strokeStyle = prop['chart.axes.color'];
675
+
676
+ // Draw the X axis
677
+ co.moveTo(this.centerx - this.radius, Math.round(this.centery));
678
+ co.lineTo(this.centerx + this.radius, Math.round(this.centery));
679
+
680
+ // Draw the X ends
681
+ if (prop['chart.axes.caps']) {
682
+ co.moveTo(ma.round(this.centerx - this.radius), this.centery - 5);
683
+ co.lineTo(ma.round(this.centerx - this.radius), this.centery + 5);
684
+ co.moveTo(ma.round(this.centerx + this.radius), this.centery - 5);
685
+ co.lineTo(ma.round(this.centerx + this.radius), this.centery + 5);
686
+ }
687
+
688
+
689
+
690
+ if (!RG.isNull(prop['chart.axes.numticks'])) {
691
+ var numticks = prop['chart.axes.numticks']
692
+ } else {
693
+ var numticks = prop['chart.labels.count'];
694
+ }
695
+
696
+ var caps = prop['chart.axes.caps'];
697
+
698
+ if (numticks) {
699
+ // Draw the X check marks
700
+ for (var i=(this.centerx - this.radius); i<(this.centerx + this.radius); i+=(this.radius / numticks)) {
701
+ co.moveTo(ma.round(i), this.centery - 3);
702
+ co.lineTo(ma.round(i), this.centery + 3);
703
+ }
704
+
705
+ // Draw the Y check marks
706
+ for (var i=(this.centery - this.radius); i<(this.centery + this.radius); i+=(this.radius / numticks)) {
707
+ co.moveTo(this.centerx - 3, ma.round(i));
708
+ co.lineTo(this.centerx + 3, ma.round(i));
709
+ }
710
+ }
711
+
712
+ // Draw the Y axis
713
+ co.moveTo(ma.round(this.centerx), this.centery - this.radius);
714
+ co.lineTo(ma.round(this.centerx), this.centery + this.radius);
715
+
716
+ // Draw the Y ends
717
+ if (prop['chart.axes.caps']) {
718
+ co.moveTo(this.centerx - 5, ma.round(this.centery - this.radius));
719
+ co.lineTo(this.centerx + 5, ma.round(this.centery - this.radius));
720
+
721
+ co.moveTo(this.centerx - 5, ma.round(this.centery + this.radius));
722
+ co.lineTo(this.centerx + 5, ma.round(this.centery + this.radius));
723
+ }
724
+
725
+ // Stroke it
726
+ co.closePath();
727
+ co.stroke();
728
+ };
729
+
730
+
731
+
732
+
733
+ /**
734
+ * This method draws a set of data on the graph
735
+ */
736
+ this.drawRscatter =
737
+ this.DrawRscatter = function ()
738
+ {
739
+ for (var dataset=0; dataset<this.data.length; dataset+=1) {
740
+
741
+ var data = this.data[dataset];
742
+ this.coords2[dataset] = [];
743
+
744
+ for (var i=0; i<data.length; ++i) {
745
+
746
+ var d1 = data[i][0];
747
+ var d2 = data[i][1];
748
+ var a = d1 / (180 / RG.PI); // RADIANS
749
+ var r = ( (d2 - prop['chart.ymin']) / (this.scale2.max - this.scale2.min) ) * this.radius;
750
+ var x = Math.sin(a) * r;
751
+ var y = Math.cos(a) * r;
752
+ var color = data[i][2] ? data[i][2] : prop['chart.colors.default'];
753
+ var tooltip = data[i][3] ? data[i][3] : null;
754
+
755
+ if (tooltip && String(tooltip).length) {
756
+ this.hasTooltips = true;
757
+ }
758
+
759
+ /**
760
+ * Account for the correct quadrant
761
+ */
762
+ x = x + this.centerx;
763
+ y = this.centery - y;
764
+
765
+
766
+ this.DrawTick(x, y, color);
767
+
768
+ // Populate the coords array with the coordinates and the tooltip
769
+ this.coords.push([x, y, color, tooltip]);
770
+ this.coords2[dataset].push([x, y, color, tooltip]);
771
+ }
772
+ }
773
+ };
774
+
775
+
776
+
777
+
778
+ /**
779
+ * Unsuprisingly, draws the labels
780
+ */
781
+ this.drawLabels =
782
+ this.DrawLabels = function ()
783
+ {
784
+ co.lineWidth = 1;
785
+
786
+ // Default the color to black
787
+ co.fillStyle = 'black';
788
+ co.strokeStyle = 'black';
789
+
790
+ var key = prop['chart.key'];
791
+ var r = this.radius;
792
+ var axesColor = prop['chart.axes.color'];
793
+ var color = prop['chart.text.color'];
794
+ var font = prop['chart.text.font'];
795
+ var size = prop['chart.text.size'];
796
+ var axes = prop['chart.labels.axes'].toLowerCase();
797
+ var units_pre = prop['chart.units.pre'];
798
+ var units_post = prop['chart.units.post'];
799
+ var decimals = prop['chart.scale.decimals'];
800
+ var centerx = this.centerx;
801
+ var centery = this.centery;
802
+
803
+ co.fillStyle = prop['chart.text.color'];
804
+
805
+ // Draw any labels
806
+ if (typeof prop['chart.labels'] == 'object' && prop['chart.labels']) {
807
+ this.DrawCircularLabels(co, prop['chart.labels'], font , size, r);
808
+ }
809
+
810
+
811
+ //
812
+ // If the axes are transparent - then the labels should have no offset,
813
+ // otherwise it defaults to true. Similarly the labels can or can't be
814
+ // centered if there's no axes
815
+ //
816
+ var offset = 10;
817
+ var centered = false;
818
+
819
+ if ( axesColor === 'rgba(0,0,0,0)'
820
+ || axesColor === 'rgb(0,0,0)'
821
+ || axesColor === 'transparent') {
822
+
823
+ offset = 0;
824
+ centered = true;
825
+ }
826
+
827
+ // Draw the axis labels
828
+ for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
829
+ if (axes.indexOf('n') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx - offset,'y':centery - (r * ((i+1) / len)),'text':this.scale2.labels[i],'valign':'center','halign':centered ? 'center' : 'right',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
830
+ if (axes.indexOf('s') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx - offset,'y':centery + (r * ((i+1) / len)),'text':this.scale2.labels[i],'valign':'center','halign':centered ? 'center' : 'right',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
831
+ if (axes.indexOf('e') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx + (r * ((i+1) / len)),'y':centery + offset,'text':this.scale2.labels[i],'valign':centered ? 'center' : 'top','halign':'center',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
832
+ if (axes.indexOf('w') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx - (r * ((i+1) / len)),'y':centery + offset,'text':this.scale2.labels[i],'valign':centered ? 'center' : 'top','halign':'center',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
833
+ }
834
+
835
+ // Draw the center minimum value (but only if there's at least one axes labels stipulated)
836
+ if (prop['chart.labels.axes'].length > 0 && prop['chart.scale.zerostart']) {
837
+ RG.text2(this, {
838
+ 'font':font,
839
+ 'size':size,
840
+ 'x':centerx,
841
+ 'y':centery,
842
+ 'text':RG.numberFormat(this, Number(this.scale2.min).toFixed(this.scale2.decimals), this.scale2.units_pre, this.scale2.units_post),
843
+ 'valign':'center',
844
+ 'halign':'center',
845
+ 'bounding':true,
846
+ 'boundingFill': prop['chart.labels.axes.background'],
847
+ 'boundingStroke': 'rgba(0,0,0,0)',
848
+ 'tag': 'scale'
849
+ });
850
+ }
851
+
852
+ /**
853
+ * Draw the key
854
+ */
855
+ if (key && key.length) {
856
+ RG.drawKey(this, key, prop['chart.colors']);
857
+ }
858
+ };
859
+
860
+
861
+
862
+
863
+ /**
864
+ * Draws the circular labels that go around the charts
865
+ *
866
+ * @param labels array The labels that go around the chart
867
+ */
868
+ this.drawCircularLabels =
869
+ this.DrawCircularLabels = function (context, labels, font_face, font_size, r)
870
+ {
871
+ var r = r + 10,
872
+ color = prop['chart.labels.color'];
873
+
874
+ for (var i=0; i<labels.length; ++i) {
875
+
876
+ var a = (360 / labels.length) * (i + 1) - (360 / (labels.length * 2));
877
+ var a = a - 90 + (prop['chart.labels.position'] == 'edge' ? ((360 / labels.length) / 2) : 0);
878
+
879
+ var x = ma.cos(a / (180/RG.PI) ) * r;
880
+ var y = ma.sin(a / (180/RG.PI)) * r;
881
+
882
+ RG.Text2(this, {
883
+ 'color': color,
884
+ 'font':font_face,
885
+ 'size':font_size,
886
+ 'x':this.centerx + x,
887
+ 'y':this.centery + y,
888
+ 'text':String(labels[i]),
889
+ 'valign':'center',
890
+ 'halign':( (this.centerx + x) > this.centerx) ? 'left' : 'right',
891
+ 'tag': 'labels'
892
+ });
893
+ }
894
+ };
895
+
896
+
897
+
898
+
899
+ /**
900
+ * Draws a single tickmark
901
+ */
902
+ this.drawTick =
903
+ this.DrawTick = function (x, y, color)
904
+ {
905
+ var tickmarks = prop['chart.tickmarks'];
906
+ var ticksize = prop['chart.ticksize'];
907
+
908
+ co.strokeStyle = color;
909
+ co.fillStyle = color;
910
+
911
+ // Cross
912
+ if (tickmarks == 'cross') {
913
+
914
+ co.beginPath();
915
+ co.moveTo(x + ticksize, y + ticksize);
916
+ co.lineTo(x - ticksize, y - ticksize);
917
+ co.stroke();
918
+
919
+ co.beginPath();
920
+ co.moveTo(x - ticksize, y + ticksize);
921
+ co.lineTo(x + ticksize, y - ticksize);
922
+ co.stroke();
923
+
924
+ // Circle
925
+ } else if (tickmarks == 'circle') {
926
+
927
+ co.beginPath();
928
+ co.arc(x, y, ticksize, 0, 6.2830, false);
929
+ co.fill();
930
+
931
+ // Square
932
+ } else if (tickmarks == 'square') {
933
+
934
+ co.beginPath();
935
+ co.fillRect(x - ticksize, y - ticksize, 2 * ticksize, 2 * ticksize);
936
+ co.fill();
937
+
938
+ // Diamond shape tickmarks
939
+ } else if (tickmarks == 'diamond') {
940
+
941
+ co.beginPath();
942
+ co.moveTo(x, y - ticksize);
943
+ co.lineTo(x + ticksize, y);
944
+ co.lineTo(x, y + ticksize);
945
+ co.lineTo(x - ticksize, y);
946
+ co.closePath();
947
+ co.fill();
948
+
949
+ // Plus style tickmarks
950
+ } else if (tickmarks == 'plus') {
951
+
952
+ co.lineWidth = 1;
953
+
954
+ co.beginPath();
955
+ co.moveTo(x, y - ticksize);
956
+ co.lineTo(x, y + ticksize);
957
+ co.moveTo(x - ticksize, y);
958
+ co.lineTo(x + ticksize, y);
959
+ co.stroke();
960
+ }
961
+ };
962
+
963
+
964
+
965
+
966
+ /**
967
+ * This function makes it much easier to get the (if any) point that is currently being hovered over.
968
+ *
969
+ * @param object e The event object
970
+ */
971
+ this.getShape =
972
+ this.getPoint = function (e)
973
+ {
974
+ var mouseXY = RG.getMouseXY(e);
975
+ var mouseX = mouseXY[0];
976
+ var mouseY = mouseXY[1];
977
+ var overHotspot = false;
978
+ var offset = prop['chart.tooltips.hotspot']; // This is how far the hotspot extends
979
+
980
+ for (var i=0,len=this.coords.length; i<len; ++i) {
981
+
982
+ var x = this.coords[i][0];
983
+ var y = this.coords[i][1];
984
+ var tooltip = this.coords[i][3];
985
+
986
+ if (
987
+ mouseX < (x + offset) &&
988
+ mouseX > (x - offset) &&
989
+ mouseY < (y + offset) &&
990
+ mouseY > (y - offset)
991
+ ) {
992
+
993
+ var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i);
994
+
995
+ return {0:this,1:x,2:y,3:i,'object':this, 'x':x, 'y':y, 'index':i, 'tooltip': tooltip};
996
+ }
997
+ }
998
+ };
999
+
1000
+
1001
+
1002
+
1003
+ /**
1004
+ * This function facilitates the installation of tooltip event listeners if
1005
+ * tooltips are defined.
1006
+ */
1007
+ this.allowTooltips =
1008
+ this.AllowTooltips = function ()
1009
+ {
1010
+ // Preload any tooltip images that are used in the tooltips
1011
+ RG.PreLoadTooltipImages(this);
1012
+
1013
+
1014
+ /**
1015
+ * This installs the window mousedown event listener that lears any
1016
+ * highlight that may be visible.
1017
+ */
1018
+ RG.InstallWindowMousedownTooltipListener(this);
1019
+
1020
+
1021
+ /**
1022
+ * This installs the canvas mousemove event listener. This function
1023
+ * controls the pointer shape.
1024
+ */
1025
+ RG.InstallCanvasMousemoveTooltipListener(this);
1026
+
1027
+
1028
+ /**
1029
+ * This installs the canvas mouseup event listener. This is the
1030
+ * function that actually shows the appropriate tooltip (if any).
1031
+ */
1032
+ RG.InstallCanvasMouseupTooltipListener(this);
1033
+ };
1034
+
1035
+
1036
+
1037
+
1038
+ /**
1039
+ * Each object type has its own Highlight() function which highlights the appropriate shape
1040
+ *
1041
+ * @param object shape The shape to highlight
1042
+ */
1043
+ this.highlight =
1044
+ this.Highlight = function (shape)
1045
+ {
1046
+ // Add the new highlight
1047
+ RG.Highlight.Point(this, shape);
1048
+ };
1049
+
1050
+
1051
+
1052
+
1053
+ /**
1054
+ * The getObjectByXY() worker method. Don't call this call:
1055
+ *
1056
+ * RGraph.ObjectRegistry.getObjectByXY(e)
1057
+ *
1058
+ * @param object e The event object
1059
+ */
1060
+ this.getObjectByXY = function (e)
1061
+ {
1062
+ var mouseXY = RG.getMouseXY(e);
1063
+ var mouseX = mouseXY[0];
1064
+ var mouseY = mouseXY[1];
1065
+ var centerx = this.centerx;
1066
+ var centery = this.centery;
1067
+ var radius = this.radius;
1068
+
1069
+ if (
1070
+ mouseX > (centerx - radius)
1071
+ && mouseX < (centerx + radius)
1072
+ && mouseY > (centery - radius)
1073
+ && mouseY < (centery + radius)
1074
+ ) {
1075
+
1076
+ return this;
1077
+ }
1078
+ };
1079
+
1080
+
1081
+
1082
+
1083
+ /**
1084
+ * This function positions a tooltip when it is displayed
1085
+ *
1086
+ * @param obj object The chart object
1087
+ * @param int x The X coordinate specified for the tooltip
1088
+ * @param int y The Y coordinate specified for the tooltip
1089
+ * @param objec tooltip The tooltips DIV element
1090
+ */
1091
+ this.positionTooltip = function (obj, x, y, tooltip, idx)
1092
+ {
1093
+ var coordX = obj.coords[tooltip.__index__][0];
1094
+ var coordY = obj.coords[tooltip.__index__][1];
1095
+ var canvasXY = RG.getCanvasXY(obj.canvas);
1096
+ var gutterLeft = obj.gutterLeft;
1097
+ var gutterTop = obj.gutterTop;
1098
+ var width = tooltip.offsetWidth;
1099
+
1100
+ // Set the top position
1101
+ tooltip.style.left = 0;
1102
+ tooltip.style.top = parseInt(tooltip.style.top) - 7 + 'px';
1103
+
1104
+ // By default any overflow is hidden
1105
+ tooltip.style.overflow = '';
1106
+
1107
+ // The arrow
1108
+ var img = new Image();
1109
+ img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAFCAYAAACjKgd3AAAARUlEQVQYV2NkQAN79+797+RkhC4M5+/bd47B2dmZEVkBCgcmgcsgbAaA9GA1BCSBbhAuA/AagmwQPgMIGgIzCD0M0AMMAEFVIAa6UQgcAAAAAElFTkSuQmCC';
1110
+ img.style.position = 'absolute';
1111
+ img.id = '__rgraph_tooltip_pointer__';
1112
+ img.style.top = (tooltip.offsetHeight - 2) + 'px';
1113
+ tooltip.appendChild(img);
1114
+
1115
+ // Reposition the tooltip if at the edges:
1116
+
1117
+ // LEFT edge
1118
+ if ((canvasXY[0] + coordX - (width / 2)) < 10) {
1119
+ tooltip.style.left = (canvasXY[0] + coordX - (width * 0.1)) + 'px';
1120
+ img.style.left = ((width * 0.1) - 8.5) + 'px';
1121
+
1122
+ // RIGHT edge
1123
+ } else if ((canvasXY[0] + coordX + (width / 2)) > doc.body.offsetWidth) {
1124
+ tooltip.style.left = canvasXY[0] + coordX - (width * 0.9) + 'px';
1125
+ img.style.left = ((width * 0.9) - 8.5) + 'px';
1126
+
1127
+ // Default positioning - CENTERED
1128
+ } else {
1129
+ tooltip.style.left = (canvasXY[0] + coordX - (width * 0.5)) + 'px';
1130
+ img.style.left = ((width * 0.5) - 8.5) + 'px';
1131
+ }
1132
+ };
1133
+
1134
+
1135
+
1136
+
1137
+ /**
1138
+ * This function returns the radius (ie the distance from the center) for a particular
1139
+ * value.
1140
+ *
1141
+ * @param number value The value you want the radius for
1142
+ */
1143
+ this.getRadius = function (value)
1144
+ {
1145
+ var max = this.max;
1146
+
1147
+ if (value < 0 || value > max) {
1148
+ return null;
1149
+ }
1150
+
1151
+ var r = (value / max) * this.radius;
1152
+
1153
+ return r;
1154
+ };
1155
+
1156
+
1157
+
1158
+
1159
+ /**
1160
+ * This allows for easy specification of gradients
1161
+ */
1162
+ this.parseColors = function ()
1163
+ {
1164
+ // Save the original colors so that they can be restored when the canvas is reset
1165
+ if (this.original_colors.length === 0) {
1166
+ this.original_colors['data'] = RG.array_clone(this.data);
1167
+ this.original_colors['chart.highlight.stroke'] = RG.arrayClone(prop['chart.highlight.stroke']);
1168
+ this.original_colors['chart.highlight.fill'] = RG.arrayClone(prop['chart.highlight.fill']);
1169
+ this.original_colors['chart.colors.default'] = RG.arrayClone(prop['chart.colors.default']);
1170
+ this.original_colors['chart.background.grid.color'] = RG.arrayClone(prop['chart.background.grid.color']);
1171
+ this.original_colors['chart.background.color'] = RG.arrayClone(prop['chart.background.color']);
1172
+ this.original_colors['chart.segment.highlight.stroke'] = RG.arrayClone(prop['chart.segment.highlight.stroke']);
1173
+ this.original_colors['chart.segment.highlight.fill'] = RG.arrayClone(prop['chart.segment.highlight.fill']);
1174
+ }
1175
+
1176
+
1177
+
1178
+
1179
+
1180
+
1181
+ // Go through the data
1182
+ for (var i=0; i<this.data.length; i+=1) {
1183
+ for (var j=0,len=this.data[i].length; j<len; j+=1) {
1184
+ this.data[i][j][2] = this.parseSingleColorForGradient(this.data[i][j][2]);
1185
+ }
1186
+ }
1187
+
1188
+ prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
1189
+ prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
1190
+ prop['chart.colors.default'] = this.parseSingleColorForGradient(prop['chart.colors.default']);
1191
+ prop['chart.background.grid.color'] = this.parseSingleColorForGradient(prop['chart.background.grid.color']);
1192
+ prop['chart.background.color'] = this.parseSingleColorForGradient(prop['chart.background.color']);
1193
+ prop['chart.segment.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.segment.highlight.stroke']);
1194
+ prop['chart.segment.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.segment.highlight.fill']);
1195
+ };
1196
+
1197
+
1198
+
1199
+
1200
+ /**
1201
+ * Use this function to reset the object to the post-constructor state. Eg reset colors if
1202
+ * need be etc
1203
+ */
1204
+ this.reset = function ()
1205
+ {
1206
+ };
1207
+
1208
+
1209
+
1210
+
1211
+ /**
1212
+ * This parses a single color value
1213
+ */
1214
+ this.parseSingleColorForGradient = function (color)
1215
+ {
1216
+ if (!color || typeof color != 'string') {
1217
+ return color;
1218
+ }
1219
+
1220
+ if (color.match(/^gradient\((.*)\)$/i)) {
1221
+
1222
+ var parts = RegExp.$1.split(':');
1223
+
1224
+ // Create the gradient
1225
+ var grad = co.createRadialGradient(this.centerx, this.centery, 0, this.centerx, this.centery, this.radius);
1226
+
1227
+ var diff = 1 / (parts.length - 1);
1228
+
1229
+ grad.addColorStop(0, RG.trim(parts[0]));
1230
+
1231
+ for (var j=1; j<parts.length; ++j) {
1232
+ grad.addColorStop(j * diff, RG.trim(parts[j]));
1233
+ }
1234
+ }
1235
+
1236
+ return grad ? grad : color;
1237
+ };
1238
+
1239
+
1240
+
1241
+
1242
+ /**
1243
+ * This function handles highlighting an entire data-series for the interactive
1244
+ * key
1245
+ *
1246
+ * @param int index The index of the data series to be highlighted
1247
+ */
1248
+ this.interactiveKeyHighlight = function (index)
1249
+ {
1250
+ if (this.coords2 && this.coords2[index] && this.coords2[index].length) {
1251
+ this.coords2[index].forEach(function (value, idx, arr)
1252
+ {
1253
+ co.beginPath();
1254
+ co.fillStyle = prop['chart.key.interactive.highlight.chart.fill'];
1255
+ co.arc(value[0], value[1], prop['chart.ticksize'] + 2, 0, RG.TWOPI, false);
1256
+ co.fill();
1257
+ });
1258
+ }
1259
+ };
1260
+
1261
+
1262
+
1263
+
1264
+ /**
1265
+ * Using a function to add events makes it easier to facilitate method chaining
1266
+ *
1267
+ * @param string type The type of even to add
1268
+ * @param function func
1269
+ */
1270
+ this.on = function (type, func)
1271
+ {
1272
+ if (type.substr(0,2) !== 'on') {
1273
+ type = 'on' + type;
1274
+ }
1275
+
1276
+ this[type] = func;
1277
+
1278
+ return this;
1279
+ };
1280
+
1281
+
1282
+
1283
+
1284
+ /**
1285
+ * This helps the Gantt reset colors when the reset function is called.
1286
+ * It handles going through the data and resetting the colors.
1287
+ */
1288
+ this.resetColorsToOriginalValues = function ()
1289
+ {
1290
+ /**
1291
+ * Copy the original colors over for single-event-per-line data
1292
+ */
1293
+ for (var i=0,len=this.original_colors['data'].length; i<len; ++i) {
1294
+ for (var j=0,len2=this.original_colors['data'][i].length; j<len2;++j) {
1295
+ this.data[i][j][2] = RG.array_clone(this.original_colors['data'][i][j][2]);
1296
+ }
1297
+ }
1298
+ };
1299
+
1300
+
1301
+
1302
+
1303
+ /**
1304
+ * This function runs once only
1305
+ * (put at the end of the file (before any effects))
1306
+ */
1307
+ this.firstDrawFunc = function ()
1308
+ {
1309
+ };
1310
+
1311
+
1312
+ RG.att(ca);
1313
+
1314
+
1315
+
1316
+
1317
+ /**
1318
+ * Register the object
1319
+ */
1320
+ RG.Register(this);
1321
+
1322
+
1323
+
1324
+
1325
+ /**
1326
+ * This is the 'end' of the constructor so if the first argument
1327
+ * contains configuration data - handle that.
1328
+ */
1329
+ if (parseConfObjectForOptions) {
1330
+ RG.parseObjectStyleConfig(this, conf.options);
1331
+ }
1332
+ };