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,1391 @@
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 line chart constructor
20
+ *
21
+ * @param object canvas The canvas ID
22
+ * @param array data The chart data
23
+ * @param array ... Other lines to plot
24
+ */
25
+ RGraph.Gauge = function (conf)
26
+ {
27
+ /**
28
+ * Allow for object config style
29
+ */
30
+ if ( typeof conf === 'object'
31
+ && typeof conf.min === 'number'
32
+ && typeof conf.max === 'number'
33
+ && typeof conf.id === 'string') {
34
+
35
+ var id = conf.id
36
+ var canvas = document.getElementById(id);
37
+ var min = conf.min;
38
+ var max = conf.max;
39
+ var value = conf.value;
40
+ var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
41
+
42
+ } else {
43
+
44
+ var id = conf;
45
+ var canvas = document.getElementById(id);
46
+ var min = arguments[1];
47
+ var max = arguments[2];
48
+ var value = arguments[3];
49
+ }
50
+
51
+ // id, min, max, value
52
+ this.id = id;
53
+ this.canvas = canvas;
54
+ this.context = this.canvas.getContext ? this.canvas.getContext("2d", {alpha: (typeof id === 'object' && id.alpha === false) ? false : true}) : null;
55
+ this.canvas.__object__ = this;
56
+ this.type = 'gauge';
57
+ this.min = min;
58
+ this.max = max;
59
+ this.value = RGraph.stringsToNumbers(value);
60
+ this.isRGraph = true;
61
+ this.currentValue = null;
62
+ this.uid = RGraph.CreateUID();
63
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
64
+ this.colorsParsed = false;
65
+ this.coordsText = [];
66
+ this.original_colors = [];
67
+ this.firstDraw = true; // After the first draw this will be false
68
+
69
+ /**
70
+ * Range checking
71
+ */
72
+ if (typeof(this.value) == 'object') {
73
+ for (var i=0; i<this.value.length; ++i) {
74
+ if (this.value[i] > this.max) this.value[i] = max;
75
+ if (this.value[i] < this.min) this.value[i] = min;
76
+ }
77
+ } else {
78
+ if (this.value > this.max) this.value = max;
79
+ if (this.value < this.min) this.value = min;
80
+ }
81
+
82
+
83
+
84
+ /**
85
+ * Compatibility with older browsers
86
+ */
87
+ //RGraph.OldBrowserCompat(this.context);
88
+
89
+
90
+ // Various config type stuff
91
+ this.properties =
92
+ {
93
+ 'chart.angles.start': null,
94
+ 'chart.angles.end': null,
95
+ 'chart.centerx': null,
96
+ 'chart.centery': null,
97
+ 'chart.radius': null,
98
+ 'chart.gutter.left': 15,
99
+ 'chart.gutter.right': 15,
100
+ 'chart.gutter.top': 15,
101
+ 'chart.gutter.bottom': 15,
102
+ 'chart.border.width': 10,
103
+ 'chart.title.top': '',
104
+ 'chart.title.top.font':'Arial',
105
+ 'chart.title.top.size':14,
106
+ 'chart.title.top.color':'#333',
107
+ 'chart.title.top.bold':false,
108
+ 'chart.title.top.pos': null,
109
+ 'chart.title.bottom': '',
110
+ 'chart.title.bottom.font':'Arial',
111
+ 'chart.title.bottom.size':14,
112
+ 'chart.title.bottom.color':'#333',
113
+ 'chart.title.bottom.bold':false,
114
+ 'chart.title.bottom.pos':null,
115
+ 'chart.text.font': 'Arial',
116
+ 'chart.text.color': '#666',
117
+ 'chart.text.size': 12,
118
+ 'chart.background.color': 'white',
119
+ 'chart.background.gradient': false,
120
+ 'chart.scale.decimals': 0,
121
+ 'chart.scale.point': '.',
122
+ 'chart.scale.thousand': ',',
123
+ 'chart.units.pre': '',
124
+ 'chart.units.post': '',
125
+
126
+ 'chart.value.text': false,
127
+ 'chart.value.text.y.pos': 0.5,
128
+ 'chart.value.text.units.pre': null,
129
+ 'chart.value.text.units.post': null,
130
+ 'chart.value.text.color': 'black',
131
+ 'chart.value.text.bounding': true,
132
+ 'chart.value.text.bounding.fill': 'white',
133
+ 'chart.value.text.bounding.stroke': 'black',
134
+
135
+ 'chart.red.start': 0.9 * this.max,
136
+ 'chart.red.color': '#DC3912',
137
+ 'chart.yellow.color': '#FF9900',
138
+ 'chart.green.end': 0.7 * this.max,
139
+ 'chart.green.color': 'rgba(0,0,0,0)',
140
+ 'chart.colors.ranges': null,
141
+ 'chart.needle.size': null,
142
+ 'chart.needle.tail': false,
143
+ 'chart.needle.colors': ['#D5604D', 'red', 'green', 'yellow'],
144
+ 'chart.needle.type': 'triangle',
145
+ 'chart.border.outer': '#ccc',
146
+ 'chart.border.inner': '#f1f1f1',
147
+ 'chart.border.outline': 'black',
148
+ 'chart.centerpin.color': 'blue',
149
+ 'chart.centerpin.radius': null,
150
+ 'chart.zoom.background': true,
151
+ 'chart.zoom.action': 'zoom',
152
+ 'chart.tickmarks.small': 25,
153
+ 'chart.tickmarks.small.color': 'black',
154
+ 'chart.tickmarks.medium': 0,
155
+ 'chart.tickmarks.medium.color': 'black',
156
+ 'chart.tickmarks.big': 5,
157
+ 'chart.tickmarks.big.color': 'black',
158
+ 'chart.labels.count': 5,
159
+ 'chart.labels.centered': false,
160
+ 'chart.labels.offset': 0,
161
+ 'chart.border.gradient': false,
162
+ 'chart.adjustable': false,
163
+ 'chart.shadow': true,
164
+ 'chart.shadow.color': 'gray',
165
+ 'chart.shadow.offsetx': 0,
166
+ 'chart.shadow.offsety': 0,
167
+ 'chart.shadow.blur': 15
168
+ }
169
+
170
+
171
+
172
+
173
+ /*
174
+ * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
175
+ * done already
176
+ */
177
+ if (!this.canvas.__rgraph_aa_translated__) {
178
+ this.context.translate(0.5,0.5);
179
+
180
+ this.canvas.__rgraph_aa_translated__ = true;
181
+ }
182
+
183
+
184
+
185
+
186
+
187
+ // Short variable names
188
+ var RG = RGraph,
189
+ ca = this.canvas,
190
+ co = ca.getContext('2d'),
191
+ prop = this.properties,
192
+ pa = RG.Path,
193
+ pa2 = RG.path2,
194
+ win = window,
195
+ doc = document,
196
+ ma = Math
197
+
198
+
199
+
200
+ /**
201
+ * "Decorate" the object with the generic effects if the effects library has been included
202
+ */
203
+ if (RG.Effects && typeof RG.Effects.decorate === 'function') {
204
+ RG.Effects.decorate(this);
205
+ }
206
+
207
+
208
+
209
+
210
+ /**
211
+ * An all encompassing accessor
212
+ *
213
+ * @param string name The name of the property
214
+ * @param mixed value The value of the property
215
+ */
216
+ this.set =
217
+ this.Set = function (name)
218
+ {
219
+ var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
220
+
221
+ /**
222
+ * the number of arguments is only one and it's an
223
+ * object - parse it for configuration data and return.
224
+ */
225
+ if (arguments.length === 1 && typeof name === 'object') {
226
+ RG.parseObjectStyleConfig(this, name);
227
+ return this;
228
+ }
229
+
230
+
231
+
232
+
233
+
234
+ /**
235
+ * This should be done first - prepend the propertyy name with "chart." if necessary
236
+ */
237
+ if (name.substr(0,6) != 'chart.') {
238
+ name = 'chart.' + name;
239
+ }
240
+
241
+
242
+
243
+
244
+ // Convert uppercase letters to dot+lower case letter
245
+ name = name.replace(/([A-Z])/g, function (str)
246
+ {
247
+ return '.' + String(RegExp.$1).toLowerCase();
248
+ });
249
+
250
+
251
+
252
+
253
+
254
+ /**
255
+ * Title compatibility
256
+ */
257
+ if (name == 'chart.title') name = 'chart.title.top';
258
+ if (name == 'chart.title.font') name = 'chart.title.top.font';
259
+ if (name == 'chart.title.size') name = 'chart.title.top.size';
260
+ if (name == 'chart.title.color') name = 'chart.title.top.color';
261
+ if (name == 'chart.title.bold') name = 'chart.title.top.bold';
262
+
263
+ // BC
264
+ if (name == 'chart.needle.color') {
265
+ name = 'chart.needle.colors';
266
+ }
267
+
268
+
269
+
270
+
271
+
272
+
273
+ prop[name] = value;
274
+
275
+ return this;
276
+ };
277
+
278
+
279
+
280
+
281
+ /**
282
+ * An all encompassing accessor
283
+ *
284
+ * @param string name The name of the property
285
+ */
286
+ this.get =
287
+ this.Get = function (name)
288
+ {
289
+ /**
290
+ * This should be done first - prepend the property name with "chart." if necessary
291
+ */
292
+ if (name.substr(0,6) != 'chart.') {
293
+ name = 'chart.' + name;
294
+ }
295
+
296
+ // Convert uppercase letters to dot+lower case letter
297
+ name = name.replace(/([A-Z])/g, function (str)
298
+ {
299
+ return '.' + String(RegExp.$1).toLowerCase()
300
+ });
301
+
302
+ // BC
303
+ if (name == 'chart.needle.color') {
304
+ name = 'chart.needle.colors';
305
+ }
306
+
307
+ return prop[name];
308
+ };
309
+
310
+
311
+
312
+
313
+ /**
314
+ * The function you call to draw the line chart
315
+ *
316
+ * @param bool An optional bool used internally to ditinguish whether the
317
+ * line chart is being called by the bar chart
318
+ */
319
+ this.draw =
320
+ this.Draw = function ()
321
+ {
322
+ /**
323
+ * Fire the onbeforedraw event
324
+ */
325
+ RG.FireCustomEvent(this, 'onbeforedraw');
326
+
327
+
328
+
329
+ /**
330
+ * Store the value (for animation primarily
331
+ */
332
+ this.currentValue = this.value;
333
+
334
+
335
+ /**
336
+ * This is new in May 2011 and facilitates indiviual gutter settings,
337
+ * eg chart.gutter.left
338
+ */
339
+ this.gutterLeft = prop['chart.gutter.left'];
340
+ this.gutterRight = prop['chart.gutter.right'];
341
+ this.gutterTop = prop['chart.gutter.top'];
342
+ this.gutterBottom = prop['chart.gutter.bottom'];
343
+
344
+ this.centerx = ((ca.width - this.gutterLeft - this.gutterRight) / 2) + this.gutterLeft;
345
+ this.centery = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
346
+ this.radius = Math.min(
347
+ ((ca.width - this.gutterLeft - this.gutterRight) / 2),
348
+ ((ca.height - this.gutterTop - this.gutterBottom) / 2)
349
+ );
350
+ this.startAngle = prop['chart.angles.start'] ? prop['chart.angles.start'] : (RG.HALFPI / 3) + RG.HALFPI;
351
+ this.endAngle = prop['chart.angles.end'] ? prop['chart.angles.end'] : RG.TWOPI + RG.HALFPI - (RG.HALFPI / 3);
352
+
353
+
354
+ /**
355
+ * Reset this so it doesn't keep growing
356
+ */
357
+ this.coordsText = [];
358
+
359
+
360
+
361
+ /**
362
+ * You can now override the positioning and radius if you so wish.
363
+ */
364
+ if (typeof(prop['chart.centerx']) == 'number') this.centerx = prop['chart.centerx'];
365
+ if (typeof(prop['chart.centery']) == 'number') this.centery = prop['chart.centery'];
366
+ if (typeof(prop['chart.radius']) == 'number') this.radius = prop['chart.radius'];
367
+
368
+ /**
369
+ * Parse the colors. This allows for simple gradient syntax
370
+ */
371
+ if (!this.colorsParsed) {
372
+ this.parseColors();
373
+
374
+ // Don't want to do this again
375
+ this.colorsParsed = true;
376
+ }
377
+
378
+
379
+ // This has to be in the constructor
380
+ this.centerpinRadius = 0.16 * this.radius;
381
+
382
+ if (typeof(prop['chart.centerpin.radius']) == 'number') {
383
+ this.centerpinRadius = prop['chart.centerpin.radius'];
384
+ }
385
+
386
+
387
+
388
+ /**
389
+ * Setup the context menu if required
390
+ */
391
+ if (prop['chart.contextmenu']) {
392
+ RG.ShowContext(this);
393
+ }
394
+
395
+
396
+
397
+ // DRAW THE CHART HERE
398
+ this.DrawBackGround();
399
+ this.DrawGradient();
400
+ this.DrawColorBands();
401
+ this.DrawSmallTickmarks();
402
+ this.DrawMediumTickmarks();
403
+ this.DrawBigTickmarks();
404
+ this.DrawLabels();
405
+ this.DrawTopTitle();
406
+ this.DrawBottomTitle();
407
+
408
+ if (typeof(this.value) == 'object') {
409
+ for (var i=0; i<this.value.length; ++i) {
410
+ this.DrawNeedle(this.value[i], prop['chart.needle.colors'][i], i);
411
+ }
412
+ } else {
413
+ this.DrawNeedle(this.value, prop['chart.needle.colors'][0], 0);
414
+ }
415
+
416
+ this.DrawCenterpin();
417
+
418
+ /**
419
+ * This function enables resizing
420
+ */
421
+ if (prop['chart.resizable']) {
422
+ RG.AllowResizing(this);
423
+ }
424
+
425
+
426
+ /**
427
+ * This installs the event listeners
428
+ */
429
+ RG.InstallEventListeners(this);
430
+
431
+
432
+ /**
433
+ * Fire the onfirstdraw event
434
+ */
435
+ if (this.firstDraw) {
436
+ RG.fireCustomEvent(this, 'onfirstdraw');
437
+ this.firstDraw = false;
438
+ this.firstDrawFunc();
439
+ }
440
+
441
+
442
+
443
+
444
+ /**
445
+ * Fire the RGraph ondraw event
446
+ */
447
+ RG.FireCustomEvent(this, 'ondraw');
448
+
449
+ return this;
450
+ };
451
+
452
+
453
+
454
+ /**
455
+ * Used in chaining. Runs a function there and then - not waiting for
456
+ * the events to fire (eg the onbeforedraw event)
457
+ *
458
+ * @param function func The function to execute
459
+ */
460
+ this.exec = function (func)
461
+ {
462
+ func(this);
463
+
464
+ return this;
465
+ };
466
+
467
+
468
+
469
+
470
+ /**
471
+ * Draw the background
472
+ */
473
+ this.drawBackGround =
474
+ this.DrawBackGround = function ()
475
+ {
476
+ // Shadow //////////////////////////////////////////////
477
+ if (prop['chart.shadow']) {
478
+ RG.SetShadow(this, prop['chart.shadow.color'], prop['chart.shadow.offsetx'], prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
479
+ }
480
+
481
+ co.beginPath();
482
+ co.fillStyle = prop['chart.background.color'];
483
+ //co.moveTo(this.centerx, this.centery)
484
+ co.arc(this.centerx, this.centery, this.radius, 0, RG.TWOPI, 0);
485
+ co.fill();
486
+
487
+ // Turn off the shadow
488
+ RG.NoShadow(this);
489
+ // Shadow //////////////////////////////////////////////
490
+
491
+
492
+ var grad = co.createRadialGradient(this.centerx + 50, this.centery - 50, 0, this.centerx + 50, this.centery - 50, 150);
493
+ grad.addColorStop(0, '#eee');
494
+ grad.addColorStop(1, 'white');
495
+
496
+ var borderWidth = prop['chart.border.width'];
497
+
498
+ co.beginPath();
499
+ co.fillStyle = prop['chart.background.color'];
500
+ co.arc(this.centerx, this.centery, this.radius, 0, RG.TWOPI, 0);
501
+ co.fill();
502
+
503
+ /**
504
+ * Draw the gray circle
505
+ */
506
+ co.beginPath();
507
+ co.fillStyle = prop['chart.border.outer'];
508
+ co.arc(this.centerx, this.centery, this.radius, 0, RG.TWOPI, 0);
509
+ co.fill();
510
+
511
+ /**
512
+ * Draw the light gray inner border
513
+ */
514
+ co.beginPath();
515
+ co.fillStyle = prop['chart.border.inner'];
516
+ co.arc(this.centerx, this.centery, this.radius - borderWidth, 0, RG.TWOPI, 0);
517
+ co.fill();
518
+
519
+
520
+
521
+ // Draw the white circle inner border
522
+ co.beginPath();
523
+ co.fillStyle = prop['chart.background.color'];
524
+ co.arc(this.centerx, this.centery, this.radius - borderWidth - 4, 0, RG.TWOPI, 0);
525
+ co.fill();
526
+
527
+
528
+
529
+ // Draw the circle background. Can be any colour now.
530
+ co.beginPath();
531
+ co.fillStyle = prop['chart.background.color'];
532
+ co.arc(this.centerx, this.centery, this.radius - borderWidth - 4, 0, RG.TWOPI, 0);
533
+ co.fill();
534
+
535
+ if (prop['chart.background.gradient']) {
536
+
537
+ // Draw a partially transparent gradient that sits on top of the background
538
+ co.beginPath();
539
+ co.fillStyle = RG.RadialGradient(this,
540
+ this.centerx,
541
+ this.centery,
542
+ 0,
543
+ this.centerx,
544
+ this.centery,
545
+ this.radius,
546
+ 'rgba(255,255,255,0.6)',
547
+ 'rgba(255,255,255,0.1)');
548
+ co.arc(this.centerx, this.centery, this.radius - borderWidth - 4, 0, RG.TWOPI, 0);
549
+ co.fill();
550
+ }
551
+
552
+
553
+
554
+ // Draw a black border around the chart
555
+ co.beginPath();
556
+ co.strokeStyle = prop['chart.border.outline'];
557
+ co.arc(this.centerx, this.centery, this.radius, 0, RG.TWOPI, 0);
558
+ co.stroke();
559
+ };
560
+
561
+
562
+
563
+
564
+ /**
565
+ * This function draws the smaller tickmarks
566
+ */
567
+ this.drawSmallTickmarks =
568
+ this.DrawSmallTickmarks = function ()
569
+ {
570
+ var numTicks = prop['chart.tickmarks.small'];
571
+ co.lineWidth = 1;
572
+
573
+ for (var i=0; i<=numTicks; ++i) {
574
+ co.beginPath();
575
+ co.strokeStyle = prop['chart.tickmarks.small.color'];
576
+ var a = (((this.endAngle - this.startAngle) / numTicks) * i) + this.startAngle;
577
+ co.arc(this.centerx, this.centery, this.radius - prop['chart.border.width'] - 10, a, a + 0.00001, 0);
578
+ co.arc(this.centerx, this.centery, this.radius - prop['chart.border.width'] - 10 - 5, a, a + 0.00001, 0);
579
+ co.stroke();
580
+ }
581
+ };
582
+
583
+
584
+
585
+
586
+ /**
587
+ * This function draws the medium sized tickmarks
588
+ */
589
+ this.drawMediumTickmarks =
590
+ this.DrawMediumTickmarks = function ()
591
+ {
592
+ if (prop['chart.tickmarks.medium']) {
593
+
594
+ var numTicks = prop['chart.tickmarks.medium'];
595
+ co.lineWidth = 3;
596
+ co.lineCap = 'round';
597
+ co.strokeStyle = prop['chart.tickmarks.medium.color'];
598
+
599
+ for (var i=0; i<=numTicks; ++i) {
600
+ co.beginPath();
601
+ var a = (((this.endAngle - this.startAngle) / numTicks) * i) + this.startAngle + (((this.endAngle - this.startAngle) / (2 * numTicks)));
602
+
603
+ if (a > this.startAngle && a< this.endAngle) {
604
+ co.arc(this.centerx, this.centery, this.radius - prop['chart.border.width'] - 10, a, a + 0.00001, 0);
605
+ co.arc(this.centerx, this.centery, this.radius - prop['chart.border.width'] - 10 - 6, a, a + 0.00001, 0);
606
+ }
607
+ co.stroke();
608
+ }
609
+ }
610
+ };
611
+
612
+
613
+
614
+
615
+ /**
616
+ * This function draws the large, bold tickmarks
617
+ */
618
+ this.drawBigTickmarks =
619
+ this.DrawBigTickmarks = function ()
620
+ {
621
+ var numTicks = prop['chart.tickmarks.big'];
622
+ co.lineWidth = 3;
623
+ co.lineCap = 'round';
624
+
625
+ for (var i=0; i<=numTicks; ++i) {
626
+ co.beginPath();
627
+ co.strokeStyle = prop['chart.tickmarks.big.color'];
628
+ var a = (((this.endAngle - this.startAngle) / numTicks) * i) + this.startAngle;
629
+ co.arc(this.centerx, this.centery, this.radius - prop['chart.border.width'] - 10, a, a + 0.00001, 0);
630
+ co.arc(this.centerx, this.centery, this.radius - prop['chart.border.width'] - 10 - 10, a, a + 0.00001, 0);
631
+ co.stroke();
632
+ }
633
+ };
634
+
635
+
636
+
637
+
638
+ /**
639
+ * This function draws the centerpin
640
+ */
641
+ this.drawCenterpin =
642
+ this.DrawCenterpin = function ()
643
+ {
644
+ var offset = 6;
645
+
646
+ var grad = co.createRadialGradient(this.centerx + offset, this.centery - offset, 0, this.centerx + offset, this.centery - offset, 25);
647
+ grad.addColorStop(0, '#ddf');
648
+ grad.addColorStop(1, prop['chart.centerpin.color']);
649
+
650
+ co.beginPath();
651
+ co.fillStyle = grad;
652
+ co.arc(this.centerx, this.centery, this.centerpinRadius, 0, RG.TWOPI, 0);
653
+ co.fill();
654
+ };
655
+
656
+
657
+
658
+
659
+ /**
660
+ * This function draws the labels
661
+ */
662
+ this.drawLabels =
663
+ this.DrawLabels = function ()
664
+ {
665
+ co.fillStyle = prop['chart.text.color'];
666
+ var font = prop['chart.text.font'];
667
+ var size = prop['chart.text.size'];
668
+ var num = prop['chart.labels.specific'] ? (prop['chart.labels.specific'].length - 1) : prop['chart.labels.count'];
669
+
670
+ co.beginPath();
671
+ for (var i=0; i<=num; ++i) {
672
+ var hyp = (this.radius - 25 - prop['chart.border.width']) - prop['chart.labels.offset'];
673
+ var a = (this.endAngle - this.startAngle) / num
674
+ a = this.startAngle + (i * a);
675
+ a -= RG.HALFPI;
676
+
677
+ var x = this.centerx - (Math.sin(a) * hyp);
678
+ var y = this.centery + (Math.cos(a) * hyp);
679
+
680
+ var hAlign = x > this.centerx ? 'right' : 'left';
681
+ var vAlign = y > this.centery ? 'bottom' : 'top';
682
+
683
+ // This handles the label alignment when the label is on a PI/HALFPI boundary
684
+ if (a == RG.HALFPI) {
685
+ vAlign = 'center';
686
+ } else if (a == RG.PI) {
687
+ hAlign = 'center';
688
+ } else if (a == (RG.HALFPI + RG.PI) ) {
689
+ vAlign = 'center';
690
+ }
691
+
692
+ /**
693
+ * Can now force center alignment
694
+ */
695
+ if (prop['chart.labels.centered']) {
696
+ hAlign = 'center';
697
+ vAlign = 'center';
698
+ }
699
+
700
+
701
+ RG.Text2(this, {'font':font,
702
+ 'size':size,
703
+ 'x':x,
704
+ 'y':y,
705
+ 'text':prop['chart.labels.specific'] ? prop['chart.labels.specific'][i] : RG.number_format(this, (((this.max - this.min) * (i / num)) + this.min).toFixed(prop['chart.scale.decimals']), prop['chart.units.pre'], prop['chart.units.post']),
706
+ 'halign':hAlign,
707
+ 'valign':vAlign,
708
+ 'tag': prop['chart.labels.specific'] ? 'labels.specific' : 'labels'
709
+ });
710
+ }
711
+ co.fill();
712
+
713
+
714
+ /**
715
+ * Draw the textual value if requested
716
+ */
717
+ if (prop['chart.value.text']) {
718
+
719
+ var x = this.centerx;
720
+ var y = this.centery + (prop['chart.value.text.y.pos'] * this.radius);
721
+
722
+ var units_pre = typeof(prop['chart.value.text.units.pre']) == 'string' ? prop['chart.value.text.units.pre'] : prop['chart.units.pre'];
723
+ var units_post = typeof(prop['chart.value.text.units.post']) == 'string' ? prop['chart.value.text.units.post'] : prop['chart.units.post'];
724
+ var color = prop['chart.value.text.color'];
725
+ var bounding = prop['chart.value.text.bounding'];
726
+ var boundingFill = prop['chart.value.text.bounding.fill'];
727
+ var boundingStroke = prop['chart.value.text.bounding.stroke'];
728
+
729
+ co.fillStyle = color;
730
+
731
+ RG.text2(this, {
732
+ 'font':font,
733
+ 'size':size + 2,
734
+ 'x':x,
735
+ 'y':y,
736
+ 'text':RG.number_format(this, this.value.toFixed(prop['chart.scale.decimals']), units_pre, units_post),
737
+ 'halign':'center',
738
+ 'valign':'center',
739
+ 'bounding':bounding,
740
+ 'bounding.fill':boundingFill,
741
+ 'bounding.stroke': boundingStroke,
742
+ 'tag': 'value.text'
743
+ });
744
+ }
745
+ };
746
+
747
+
748
+
749
+
750
+ /**
751
+ * This function draws the top title
752
+ */
753
+ this.drawTopTitle =
754
+ this.DrawTopTitle = function ()
755
+ {
756
+ var x = this.centerx;
757
+ var y = this.centery - 25;
758
+
759
+ // Totally override the calculated positioning
760
+ if (typeof(prop['chart.title.top.pos']) == 'number') {
761
+ y = this.centery - (this.radius * prop['chart.title.top.pos']);
762
+ }
763
+
764
+ if (prop['chart.title.top']) {
765
+ co.fillStyle = prop['chart.title.top.color'];
766
+ RG.Text2(this, {'font':prop['chart.title.top.font'],
767
+ 'size':prop['chart.title.top.size'],
768
+ 'x':x,
769
+ 'y':y,
770
+ 'text':String(prop['chart.title.top']),
771
+ 'halign':'center',
772
+ 'valign':'bottom',
773
+ 'bold':prop['chart.title.top.bold'],
774
+ 'tag': 'title.top'
775
+ });
776
+ }
777
+ };
778
+
779
+
780
+
781
+
782
+ /**
783
+ * This function draws the bottom title
784
+ */
785
+ this.drawBottomTitle =
786
+ this.DrawBottomTitle = function ()
787
+ {
788
+ var x = this.centerx;
789
+ var y = this.centery + this.centerpinRadius + 10;
790
+
791
+ // Totally override the calculated positioning
792
+ if (typeof(prop['chart.title.bottom.pos']) == 'number') {
793
+ y = this.centery + (this.radius * prop['chart.title.bottom.pos']);
794
+ }
795
+
796
+ if (prop['chart.title.bottom']) {
797
+ co.fillStyle = prop['chart.title.bottom.color'];
798
+
799
+ RG.Text2(this, {'font':prop['chart.title.bottom.font'],
800
+ 'size':prop['chart.title.bottom.size'],
801
+ 'x':x,
802
+ 'y':y,
803
+ 'text':String(prop['chart.title.bottom']),
804
+ 'halign':'center',
805
+ 'valign':'top',
806
+ 'bold':prop['chart.title.bottom.bold'],
807
+ 'tag': 'title.bottom'
808
+ });
809
+ }
810
+ };
811
+
812
+
813
+
814
+
815
+ /**
816
+ * This function draws the Needle
817
+ *
818
+ * @param number value The value to draw the needle for
819
+ */
820
+ this.drawNeedle =
821
+ this.DrawNeedle = function (value, color, index)
822
+ {
823
+ var type = prop['chart.needle.type'];
824
+
825
+ co.lineWidth = 0.5;
826
+ co.strokeStyle = 'gray';
827
+ co.fillStyle = color;
828
+
829
+ var angle = (this.endAngle - this.startAngle) * ((value - this.min) / (this.max - this.min));
830
+ angle += this.startAngle;
831
+
832
+
833
+ // Work out the size of the needle
834
+ if ( typeof(prop['chart.needle.size']) == 'object'
835
+ && prop['chart.needle.size']
836
+ && typeof(prop['chart.needle.size'][index]) == 'number') {
837
+
838
+ var size = prop['chart.needle.size'][index];
839
+
840
+ } else if (typeof(prop['chart.needle.size']) == 'number') {
841
+ var size = prop['chart.needle.size'];
842
+
843
+ } else {
844
+ var size = this.radius - 25 - prop['chart.border.width'];
845
+ }
846
+
847
+
848
+
849
+ if (type == 'line') {
850
+
851
+ co.beginPath();
852
+
853
+ co.lineWidth = 7;
854
+ co.strokeStyle = color;
855
+
856
+ co.arc(this.centerx,
857
+ this.centery,
858
+ size,
859
+ angle,
860
+ angle + 0.0001,
861
+ false);
862
+
863
+ co.lineTo(this.centerx, this.centery);
864
+
865
+ if (prop['chart.needle.tail']) {
866
+ co.arc(this.centerx, this.centery, this.radius * 0.2 , angle + RG.PI, angle + 0.00001 + RG.PI, false);
867
+ }
868
+
869
+ co.lineTo(this.centerx, this.centery);
870
+
871
+ co.stroke();
872
+ //co.fill();
873
+
874
+ } else {
875
+
876
+ co.beginPath();
877
+ co.arc(this.centerx, this.centery, size, angle, angle + 0.00001, false);
878
+ co.arc(this.centerx, this.centery, this.centerpinRadius * 0.5, angle + RG.HALFPI, angle + 0.00001 + RG.HALFPI, false);
879
+
880
+ if (prop['chart.needle.tail']) {
881
+ co.arc(this.centerx, this.centery, this.radius * 0.2 , angle + RG.PI, angle + 0.00001 + RG.PI, false);
882
+ }
883
+
884
+ co.arc(this.centerx, this.centery, this.centerpinRadius * 0.5, angle - RG.HALFPI, angle - 0.00001 - RG.HALFPI, false);
885
+ co.stroke();
886
+ co.fill();
887
+
888
+ /**
889
+ * Store the angle in an object variable
890
+ */
891
+ this.angle = angle;
892
+ }
893
+ };
894
+
895
+
896
+
897
+
898
+ /**
899
+ * This draws the green background to the tickmarks
900
+ */
901
+ this.drawColorBands =
902
+ this.DrawColorBands = function ()
903
+ {
904
+ if (RG.is_array(prop['chart.colors.ranges'])) {
905
+
906
+ var ranges = prop['chart.colors.ranges'];
907
+
908
+ for (var i=0; i<ranges.length; ++i) {
909
+
910
+ //co.strokeStyle = prop['chart.strokestyle'] ? prop['chart.strokestyle'] : ranges[i][2];
911
+ co.fillStyle = ranges[i][2];
912
+ co.lineWidth = 0;//prop['chart.linewidth.segments'];
913
+
914
+ co.beginPath();
915
+ co.arc(this.centerx,
916
+ this.centery,
917
+ this.radius - 10 - prop['chart.border.width'],
918
+ (((ranges[i][0] - this.min) / (this.max - this.min)) * (this.endAngle - this.startAngle)) + this.startAngle,
919
+ (((ranges[i][1] - this.min) / (this.max - this.min)) * (this.endAngle - this.startAngle)) + this.startAngle,
920
+ false);
921
+
922
+ co.arc(this.centerx,
923
+ this.centery,
924
+ this.radius - 20 - prop['chart.border.width'],
925
+ (((ranges[i][1] - this.min) / (this.max - this.min)) * (this.endAngle - this.startAngle)) + this.startAngle,
926
+ (((ranges[i][0] - this.min) / (this.max - this.min)) * (this.endAngle - this.startAngle)) + this.startAngle,
927
+ true);
928
+ co.closePath();
929
+ co.fill();
930
+ }
931
+
932
+ return;
933
+ }
934
+
935
+
936
+
937
+
938
+ /**
939
+ * Draw the GREEN region
940
+ */
941
+ co.strokeStyle = prop['chart.green.color'];
942
+ co.fillStyle = prop['chart.green.color'];
943
+
944
+ var greenStart = this.startAngle;
945
+ var greenEnd = this.startAngle + (this.endAngle - this.startAngle) * ((prop['chart.green.end'] - this.min) / (this.max - this.min))
946
+
947
+ co.beginPath();
948
+ co.arc(this.centerx, this.centery, this.radius - 10 - prop['chart.border.width'], greenStart, greenEnd, false);
949
+ co.arc(this.centerx, this.centery, this.radius - 20 - prop['chart.border.width'], greenEnd, greenStart, true);
950
+ co.fill();
951
+
952
+
953
+
954
+
955
+
956
+ /**
957
+ * Draw the YELLOW region
958
+ */
959
+ co.strokeStyle = prop['chart.yellow.color'];
960
+ co.fillStyle = prop['chart.yellow.color'];
961
+
962
+ var yellowStart = greenEnd;
963
+ var yellowEnd = this.startAngle + (this.endAngle - this.startAngle) * ((prop['chart.red.start'] - this.min) / (this.max - this.min))
964
+
965
+ co.beginPath();
966
+ co.arc(this.centerx, this.centery, this.radius - 10 - prop['chart.border.width'], yellowStart, yellowEnd, false);
967
+ co.arc(this.centerx, this.centery, this.radius - 20 - prop['chart.border.width'], yellowEnd, yellowStart, true);
968
+ co.fill();
969
+
970
+
971
+
972
+
973
+
974
+ /**
975
+ * Draw the RED region
976
+ */
977
+ co.strokeStyle = prop['chart.red.color'];
978
+ co.fillStyle = prop['chart.red.color'];
979
+
980
+ var redStart = yellowEnd;
981
+ var redEnd = this.startAngle + (this.endAngle - this.startAngle) * ((this.max - this.min) / (this.max - this.min))
982
+
983
+ co.beginPath();
984
+ co.arc(this.centerx, this.centery, this.radius - 10 - prop['chart.border.width'], redStart, redEnd, false);
985
+ co.arc(this.centerx, this.centery, this.radius - 20 - prop['chart.border.width'], redEnd, redStart, true);
986
+ co.fill();
987
+ };
988
+
989
+
990
+
991
+
992
+ /**
993
+ * A placeholder function
994
+ *
995
+ * @param object The event object
996
+ */
997
+ this.getShape = function (e) {};
998
+
999
+
1000
+
1001
+
1002
+ /**
1003
+ * A getValue method
1004
+ *
1005
+ * @param object e An event object
1006
+ */
1007
+ this.getValue = function (e)
1008
+ {
1009
+ var mouseXY = RG.getMouseXY(e);
1010
+ var mouseX = mouseXY[0];
1011
+ var mouseY = mouseXY[1];
1012
+
1013
+ var angle = RG.getAngleByXY(this.centerx, this.centery, mouseX, mouseY);
1014
+
1015
+ if (angle >= 0 && angle <= RG.HALFPI) {
1016
+ angle += RG.TWOPI;
1017
+ }
1018
+
1019
+ var value = ((angle - this.startAngle) / (this.endAngle - this.startAngle)) * (this.max - this.min);
1020
+ value = value + this.min;
1021
+
1022
+ if (value < this.min) {
1023
+ value = this.min
1024
+ }
1025
+
1026
+ if (value > this.max) {
1027
+ value = this.max
1028
+ }
1029
+
1030
+ return value;
1031
+ };
1032
+
1033
+
1034
+
1035
+
1036
+ /**
1037
+ * The getObjectByXY() worker method. Don't call this call:
1038
+ *
1039
+ * RGraph.ObjectRegistry.getObjectByXY(e)
1040
+ *
1041
+ * @param object e The event object
1042
+ */
1043
+ this.getObjectByXY = function (e)
1044
+ {
1045
+ var mouseXY = RGraph.getMouseXY(e);
1046
+
1047
+ if (
1048
+ mouseXY[0] > (this.centerx - this.radius)
1049
+ && mouseXY[0] < (this.centerx + this.radius)
1050
+ && mouseXY[1] > (this.centery - this.radius)
1051
+ && mouseXY[1] < (this.centery + this.radius)
1052
+ && RG.getHypLength(this.centerx, this.centery, mouseXY[0], mouseXY[1]) <= this.radius
1053
+ ) {
1054
+
1055
+ return this;
1056
+ }
1057
+ };
1058
+
1059
+
1060
+
1061
+
1062
+ /**
1063
+ * This draws the gradient that goes around the Gauge chart
1064
+ */
1065
+ this.drawGradient =
1066
+ this.DrawGradient = function ()
1067
+ {
1068
+ if (prop['chart.border.gradient']) {
1069
+
1070
+ co.beginPath();
1071
+
1072
+ var grad = co.createRadialGradient(this.centerx, this.centery, this.radius, this.centerx, this.centery, this.radius - 15);
1073
+ grad.addColorStop(0, 'gray');
1074
+ grad.addColorStop(1, 'white');
1075
+
1076
+ co.fillStyle = grad;
1077
+ co.arc(this.centerx, this.centery, this.radius, 0, RG.TWOPI, false)
1078
+ co.arc(this.centerx, this.centery, this.radius - 15, RG.TWOPI,0, true)
1079
+ co.fill();
1080
+ }
1081
+ };
1082
+
1083
+
1084
+
1085
+
1086
+ /**
1087
+ * This method handles the adjusting calculation for when the mouse is moved
1088
+ *
1089
+ * @param object e The event object
1090
+ */
1091
+ this.adjusting_mousemove =
1092
+ this.Adjusting_mousemove = function (e)
1093
+ {
1094
+ /**
1095
+ * Handle adjusting for the Bar
1096
+ */
1097
+ if (prop['chart.adjustable'] && RG.Registry.Get('chart.adjusting') && RG.Registry.Get('chart.adjusting').uid == this.uid) {
1098
+ this.value = this.getValue(e);
1099
+ //RG.Clear(this.canvas);
1100
+ RG.redrawCanvas(this.canvas);
1101
+ RG.fireCustomEvent(this, 'onadjust');
1102
+ }
1103
+ };
1104
+
1105
+
1106
+
1107
+
1108
+ /**
1109
+ * This method returns an appropriate angle for the given value (in RADIANS)
1110
+ *
1111
+ * @param number value The value to get the angle for
1112
+ */
1113
+ this.getAngle = function (value)
1114
+ {
1115
+ // Higher than max
1116
+ if (value > this.max || value < this.min) {
1117
+ return null;
1118
+ }
1119
+
1120
+ //var value = ((angle - this.startAngle) / (this.endAngle - this.startAngle)) * (this.max - this.min);
1121
+ //value = value + this.min;
1122
+
1123
+ var angle = (((value - this.min) / (this.max - this.min)) * (this.endAngle - this.startAngle)) + this.startAngle;
1124
+
1125
+ return angle;
1126
+ };
1127
+
1128
+
1129
+
1130
+
1131
+ /**
1132
+ * This allows for easy specification of gradients. Could optimise this not to repeatedly call parseSingleColors()
1133
+ */
1134
+ this.parseColors = function ()
1135
+ {
1136
+ // Save the original colors so that they can be restored when the canvas is reset
1137
+ if (this.original_colors.length === 0) {
1138
+ this.original_colors['chart.background.color'] = RG.array_clone(prop['chart.background.color']);
1139
+ this.original_colors['chart.red.color'] = RG.array_clone(prop['chart.red.color']);
1140
+ this.original_colors['chart.yellow.color'] = RG.array_clone(prop['chart.yellow.color']);
1141
+ this.original_colors['chart.green.color'] = RG.array_clone(prop['chart.green.color']);
1142
+ this.original_colors['chart.border.inner'] = RG.array_clone(prop['chart.border.inner']);
1143
+ this.original_colors['chart.border.outer'] = RG.array_clone(prop['chart.border.outer']);
1144
+ this.original_colors['chart.colors.ranges'] = RG.array_clone(prop['chart.colors.ranges']);
1145
+ this.original_colors['chart.needle.colors'] = RG.array_clone(prop['chart.needle.colors']);
1146
+ }
1147
+
1148
+ prop['chart.background.color'] = this.parseSingleColorForGradient(prop['chart.background.color']);
1149
+ prop['chart.red.color'] = this.parseSingleColorForGradient(prop['chart.red.color']);
1150
+ prop['chart.yellow.color'] = this.parseSingleColorForGradient(prop['chart.yellow.color']);
1151
+ prop['chart.green.color'] = this.parseSingleColorForGradient(prop['chart.green.color']);
1152
+ prop['chart.border.inner'] = this.parseSingleColorForGradient(prop['chart.border.inner']);
1153
+ prop['chart.border.outer'] = this.parseSingleColorForGradient(prop['chart.border.outer']);
1154
+
1155
+ // Parse the chart.color.ranges value
1156
+ if (prop['chart.colors.ranges']) {
1157
+
1158
+ var ranges = prop['chart.colors.ranges'];
1159
+
1160
+ for (var i=0; i<ranges.length; ++i) {
1161
+ ranges[i][2] = this.parseSingleColorForGradient(ranges[i][2], this.radius - 30);
1162
+ }
1163
+ }
1164
+
1165
+ // Parse the chart.needle.colors value
1166
+ if (prop['chart.needle.colors']) {
1167
+
1168
+ var colors = prop['chart.needle.colors'];
1169
+
1170
+ for (var i=0; i<colors.length; ++i) {
1171
+ colors[i] = this.parseSingleColorForGradient(colors[i]);
1172
+ }
1173
+ }
1174
+ };
1175
+
1176
+
1177
+
1178
+
1179
+ /**
1180
+ * Use this function to reset the object to the post-constructor state. Eg reset colors if
1181
+ * need be etc
1182
+ */
1183
+ this.reset = function ()
1184
+ {
1185
+ };
1186
+
1187
+
1188
+
1189
+
1190
+ /**
1191
+ * This parses a single color value
1192
+ *
1193
+ * @param string color The color to look for a gradient in
1194
+ * @param radius OPTIONAL The start radius to start the gradient at.
1195
+ * If not suppllied the centerx value is used
1196
+ */
1197
+ this.parseSingleColorForGradient = function (color)
1198
+ {
1199
+ var radiusStart = arguments[1] || 0;
1200
+
1201
+ if (!color || typeof(color) != 'string') {
1202
+ return color;
1203
+ }
1204
+
1205
+ if (color.match(/^gradient\((.*)\)$/i)) {
1206
+
1207
+ var parts = RegExp.$1.split(':');
1208
+
1209
+ // Create the gradient
1210
+ var grad = co.createRadialGradient(this.centerx,
1211
+ this.centery,
1212
+ radiusStart,
1213
+ this.centerx,
1214
+ this.centery,
1215
+ this.radius
1216
+ );
1217
+
1218
+ var diff = 1 / (parts.length - 1);
1219
+
1220
+ grad.addColorStop(0, RG.trim(parts[0]));
1221
+
1222
+ for (var j=1; j<parts.length; ++j) {
1223
+ grad.addColorStop(j * diff, RG.trim(parts[j]));
1224
+ }
1225
+ }
1226
+
1227
+ return grad ? grad : color;
1228
+ };
1229
+
1230
+
1231
+
1232
+
1233
+ /**
1234
+ * Using a function to add events makes it easier to facilitate method chaining
1235
+ *
1236
+ * @param string type The type of even to add
1237
+ * @param function func
1238
+ */
1239
+ this.on = function (type, func)
1240
+ {
1241
+ if (type.substr(0,2) !== 'on') {
1242
+ type = 'on' + type;
1243
+ }
1244
+
1245
+ this[type] = func;
1246
+
1247
+ return this;
1248
+ };
1249
+
1250
+
1251
+
1252
+
1253
+ /**
1254
+ * This function runs once only
1255
+ * (put at the end of the file (before any effects))
1256
+ */
1257
+ this.firstDrawFunc = function ()
1258
+ {
1259
+ };
1260
+
1261
+
1262
+
1263
+
1264
+ /**
1265
+ * Gauge Grow
1266
+ *
1267
+ * This effect gradually increases the represented value
1268
+ *
1269
+ * @param object Options for the effect. You can pass frames here
1270
+ * @param function An optional callback function
1271
+ */
1272
+ this.grow = function ()
1273
+ {
1274
+ var obj = this;
1275
+ var opt = arguments[0] ? arguments[0] : {};
1276
+ var callback = arguments[1] ? arguments[1] : function () {};
1277
+ var frames = opt.frames || 30;
1278
+ var frame = 0;
1279
+
1280
+ // Single pointer
1281
+ if (typeof obj.value === 'number') {
1282
+
1283
+ var origValue = Number(obj.currentValue);
1284
+
1285
+ if (obj.currentValue == null) {
1286
+ obj.currentValue = obj.min;
1287
+ origValue = obj.min;
1288
+ }
1289
+
1290
+ var newValue = obj.value;
1291
+ var diff = newValue - origValue;
1292
+
1293
+
1294
+ var iterator = function ()
1295
+ {
1296
+ obj.value = ((frame / frames) * diff) + origValue;
1297
+
1298
+ if (obj.value > obj.max) obj.value = obj.max;
1299
+ if (obj.value < obj.min) obj.value = obj.min;
1300
+
1301
+ //RGraph.clear(obj.canvas);
1302
+ RG.redrawCanvas(obj.canvas);
1303
+
1304
+ if (frame++ < frames) {
1305
+ RG.Effects.updateCanvas(iterator);
1306
+ } else {
1307
+ callback(obj);
1308
+ }
1309
+ };
1310
+
1311
+ iterator();
1312
+
1313
+
1314
+
1315
+ /**
1316
+ * Multiple pointers
1317
+ */
1318
+ } else {
1319
+
1320
+ if (obj.currentValue == null) {
1321
+ obj.currentValue = [];
1322
+
1323
+ for (var i=0; i<obj.value.length; ++i) {
1324
+ obj.currentValue[i] = obj.min;
1325
+ }
1326
+
1327
+ origValue = RG.array_clone(obj.currentValue);
1328
+ }
1329
+
1330
+ var origValue = RG.array_clone(obj.currentValue);
1331
+ var newValue = RG.array_clone(obj.value);
1332
+ var diff = [];
1333
+
1334
+ for (var i=0,len=newValue.length; i<len; ++i) {
1335
+ diff[i] = newValue[i] - Number(obj.currentValue[i]);
1336
+ }
1337
+
1338
+
1339
+
1340
+ var iterator = function ()
1341
+ {
1342
+ frame++;
1343
+
1344
+ for (var i=0,len=obj.value.length; i<len; ++i) {
1345
+
1346
+ obj.value[i] = ((frame / frames) * diff[i]) + origValue[i];
1347
+
1348
+ if (obj.value[i] > obj.max) obj.value[i] = obj.max;
1349
+ if (obj.value[i] < obj.min) obj.value[i] = obj.min;
1350
+ }
1351
+
1352
+ //RG.clear(obj.canvas);
1353
+ RG.redrawCanvas(obj.canvas);
1354
+
1355
+
1356
+ if (frame < frames) {
1357
+ RG.Effects.updateCanvas(iterator);
1358
+ } else {
1359
+ callback(obj);
1360
+ }
1361
+ };
1362
+
1363
+ iterator();
1364
+ }
1365
+
1366
+ return this;
1367
+ };
1368
+
1369
+
1370
+
1371
+ RG.att(ca);
1372
+
1373
+
1374
+
1375
+
1376
+ /**
1377
+ * Register the object
1378
+ */
1379
+ RG.Register(this);
1380
+
1381
+
1382
+
1383
+
1384
+ /**
1385
+ * This is the 'end' of the constructor so if the first argument
1386
+ * contains configuration data - handle that.
1387
+ */
1388
+ if (parseConfObjectForOptions) {
1389
+ RG.parseObjectStyleConfig(this, conf.options);
1390
+ }
1391
+ };