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,1242 @@
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 bar chart constructor
20
+ *
21
+ * @param string canvas The canvas ID
22
+ * @param min integer The minimum value
23
+ * @param max integer The maximum value
24
+ * @param value integer The indicated value
25
+ */
26
+ RGraph.Meter = function (conf)
27
+ {
28
+ /**
29
+ * Allow for object config style
30
+ */
31
+ if ( typeof conf === 'object'
32
+ && typeof conf.min === 'number'
33
+ && typeof conf.max === 'number'
34
+ && typeof conf.value !== 'undefined'
35
+ && typeof conf.id === 'string') {
36
+
37
+ var id = conf.id
38
+ var canvas = document.getElementById(id);
39
+ var min = conf.min;
40
+ var max = conf.max;
41
+ var value = conf.value;
42
+ var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
43
+
44
+ } else {
45
+
46
+ var id = conf;
47
+ var canvas = document.getElementById(id);
48
+ var min = arguments[1];
49
+ var max = arguments[2];
50
+ var value = arguments[3];
51
+ }
52
+
53
+
54
+
55
+
56
+ // id, min, max, value
57
+ // Get the canvas and context objects
58
+ this.id = id;
59
+ this.canvas = canvas;
60
+ this.context = this.canvas.getContext ? this.canvas.getContext("2d", {alpha: (typeof id === 'object' && id.alpha === false) ? false : true}) : null;
61
+ this.canvas.__object__ = this;
62
+ this.type = 'meter';
63
+ this.min = min;
64
+ this.max = max;
65
+ this.value = RGraph.stringsToNumbers(value);
66
+ this.centerx = null;
67
+ this.centery = null;
68
+ this.radius = null;
69
+ this.isRGraph = true;
70
+ this.currentValue = null;
71
+ this.uid = RGraph.CreateUID();
72
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
73
+ this.colorsParsed = false;
74
+ this.coordsText = [];
75
+ this.original_colors = [];
76
+ this.firstDraw = true; // After the first draw this will be false
77
+
78
+
79
+ /**
80
+ * Compatibility with older browsers
81
+ */
82
+ //RGraph.OldBrowserCompat(this.context);
83
+
84
+
85
+ // Various config type stuff
86
+ this.properties =
87
+ {
88
+ 'chart.background.image.url': null,
89
+ 'chart.background.image.offsetx': 0,
90
+ 'chart.background.image.offsety': 0,
91
+ 'chart.background.image.stretch': true,
92
+ 'chart.background.color': 'white',
93
+ 'chart.gutter.left': 15,
94
+ 'chart.gutter.right': 15,
95
+ 'chart.gutter.top': 15,
96
+ 'chart.gutter.bottom': 20,
97
+ 'chart.linewidth': 1,
98
+ 'chart.linewidth.segments': 0,
99
+ 'chart.strokestyle': null,
100
+ 'chart.border': true,
101
+ 'chart.border.color': 'black',
102
+ 'chart.text.font': 'Arial',
103
+ 'chart.text.size': 12,
104
+ 'chart.text.color': 'black',
105
+ 'chart.text.valign': 'center',
106
+ 'chart.value.text.decimals': 0,
107
+ 'chart.value.text.units.pre': '',
108
+ 'chart.value.text.units.post': '',
109
+ 'chart.title': '',
110
+ 'chart.title.background': null,
111
+ 'chart.title.hpos': null,
112
+ 'chart.title.vpos': null,
113
+ 'chart.title.color': 'black',
114
+ 'chart.title.bold': true,
115
+ 'chart.title.font': null,
116
+ 'chart.title.x': null,
117
+ 'chart.title.y': null,
118
+ 'chart.title.halign': null,
119
+ 'chart.title.valign': null,
120
+ 'chart.green.start': ((this.max - this.min) * 0.35) + this.min,
121
+ 'chart.green.end': this.max,
122
+ 'chart.green.color': '#207A20',
123
+ 'chart.yellow.start': ((this.max - this.min) * 0.1) + this.min,
124
+ 'chart.yellow.end': ((this.max - this.min) * 0.35) + this.min,
125
+ 'chart.yellow.color': '#D0AC41',
126
+ 'chart.red.start': this.min,
127
+ 'chart.red.end': ((this.max - this.min) * 0.1) + this.min,
128
+ 'chart.red.color': '#9E1E1E',
129
+ 'chart.colors.ranges': null,
130
+ 'chart.units.pre': '',
131
+ 'chart.units.post': '',
132
+ 'chart.contextmenu': null,
133
+ 'chart.zoom.factor': 1.5,
134
+ 'chart.zoom.fade.in': true,
135
+ 'chart.zoom.fade.out': true,
136
+ 'chart.zoom.hdir': 'right',
137
+ 'chart.zoom.vdir': 'down',
138
+ 'chart.zoom.frames': 25,
139
+ 'chart.zoom.delay': 16.666,
140
+ 'chart.zoom.shadow': true,
141
+ 'chart.zoom.background': true,
142
+ 'chart.zoom.action': 'zoom',
143
+ 'chart.annotatable': false,
144
+ 'chart.annotate.color': 'black',
145
+ 'chart.shadow': false,
146
+ 'chart.shadow.color': 'rgba(0,0,0,0.5)',
147
+ 'chart.shadow.blur': 3,
148
+ 'chart.shadow.offsetx': 3,
149
+ 'chart.shadow.offsety': 3,
150
+ 'chart.resizable': false,
151
+ 'chart.resize.handle.adjust': [0,0],
152
+ 'chart.resize.handle.background': null,
153
+ 'chart.tickmarks.small.num': 100,
154
+ 'chart.tickmarks.big.num': 10,
155
+ 'chart.tickmarks.small.color': '#bbb',
156
+ 'chart.tickmarks.big.color': 'black',
157
+ 'chart.scale.decimals': 0,
158
+ 'chart.scale.point': '.',
159
+ 'chart.scale.thousand': ',',
160
+ 'chart.radius': null,
161
+ 'chart.centerx': null,
162
+ 'chart.centery': null,
163
+ 'chart.labels': true,
164
+ 'chart.labels.count': 10,
165
+ 'chart.segment.radius.start': 0,
166
+ 'chart.needle.radius': null,
167
+ 'chart.needle.tail': false,
168
+ 'chart.needle.head': true,
169
+ 'chart.needle.color': 'black',
170
+ 'chart.needle.image.url': null,
171
+ 'chart.needle.image.offsetx': 0,
172
+ 'chart.needle.image.offsety': 0,
173
+ 'chart.adjustable': false,
174
+ 'chart.angles.start': RGraph.PI,
175
+ 'chart.angles.end': RGraph.TWOPI,
176
+ 'chart.centerpin.stroke': 'black',
177
+ 'chart.centerpin.fill': 'white'
178
+ }
179
+
180
+
181
+ // Check for support
182
+ if (!this.canvas) {
183
+ alert('[METER] No canvas support');
184
+ return;
185
+ }
186
+
187
+
188
+
189
+ /*
190
+ * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
191
+ * done already
192
+ */
193
+ if (!this.canvas.__rgraph_aa_translated__) {
194
+ this.context.translate(0.5,0.5);
195
+
196
+ this.canvas.__rgraph_aa_translated__ = true;
197
+ }
198
+
199
+
200
+
201
+
202
+ // Short variable names
203
+ var RG = RGraph,
204
+ ca = this.canvas,
205
+ co = ca.getContext('2d'),
206
+ prop = this.properties,
207
+ pa = RG.Path,
208
+ pa2 = RG.path2,
209
+ win = window,
210
+ doc = document,
211
+ ma = Math
212
+
213
+
214
+
215
+ /**
216
+ * "Decorate" the object with the generic effects if the effects library has been included
217
+ */
218
+ if (RG.Effects && typeof RG.Effects.decorate === 'function') {
219
+ RG.Effects.decorate(this);
220
+ }
221
+
222
+
223
+
224
+ /**
225
+ * A setter
226
+ *
227
+ * @param name string The name of the property to set
228
+ * @param value mixed The value of the property
229
+ */
230
+ this.set =
231
+ this.Set = function (name)
232
+ {
233
+ var value = arguments[1] || null;
234
+
235
+ /**
236
+ * the number of arguments is only one and it's an
237
+ * object - parse it for configuration data and return.
238
+ */
239
+ if (arguments.length === 1 && typeof name === 'object') {
240
+ RG.parseObjectStyleConfig(this, name);
241
+ return this;
242
+ }
243
+
244
+
245
+
246
+
247
+
248
+ /**
249
+ * This should be done first - prepend the propertyy name with "chart." if necessary
250
+ */
251
+ if (name.substr(0,6) != 'chart.') {
252
+ name = 'chart.' + name;
253
+ }
254
+
255
+
256
+
257
+
258
+ // Convert uppercase letters to dot+lower case letter
259
+ name = name.replace(/([A-Z])/g, function (str)
260
+ {
261
+ return '.' + String(RegExp.$1).toLowerCase();
262
+ });
263
+
264
+
265
+
266
+
267
+ if (name == 'chart.value') {
268
+ this.value = value;
269
+ return;
270
+ }
271
+
272
+
273
+
274
+
275
+
276
+
277
+ prop[name] = value;
278
+
279
+ return this;
280
+ };
281
+
282
+
283
+
284
+
285
+ /**
286
+ * A getter
287
+ *
288
+ * @param name string The name of the property to get
289
+ */
290
+ this.get =
291
+ this.Get = function (name)
292
+ {
293
+ /**
294
+ * This should be done first - prepend the property name with "chart." if necessary
295
+ */
296
+ if (name.substr(0,6) != 'chart.') {
297
+ name = 'chart.' + name;
298
+ }
299
+
300
+ // Convert uppercase letters to dot+lower case letter
301
+ name = name.replace(/([A-Z])/g, function (str)
302
+ {
303
+ return '.' + String(RegExp.$1).toLowerCase()
304
+ });
305
+
306
+ if (name == 'chart.value') {
307
+ return this.value;
308
+ }
309
+
310
+ return prop[name];
311
+ };
312
+
313
+
314
+
315
+
316
+ /**
317
+ * The function you call to draw 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
+ * Constrain the value to be within the min and max
329
+ */
330
+ if (this.value > this.max) this.value = this.max;
331
+ if (this.value < this.min) this.value = this.min;
332
+
333
+ /**
334
+ * Set the current value
335
+ */
336
+ this.currentValue = this.value;
337
+
338
+ /**
339
+ * This is new in May 2011 and facilitates indiviual gutter settings,
340
+ * eg chart.gutter.left
341
+ */
342
+ this.gutterLeft = prop['chart.gutter.left'];
343
+ this.gutterRight = prop['chart.gutter.right'];
344
+ this.gutterTop = prop['chart.gutter.top'];
345
+ this.gutterBottom = prop['chart.gutter.bottom'];
346
+
347
+ this.centerx = ((ca.width - this.gutterLeft - this.gutterRight) / 2) + this.gutterLeft;
348
+ this.centery = ca.height - this.gutterBottom;
349
+ this.radius = Math.min(
350
+ (ca.width - this.gutterLeft - this.gutterRight) / 2,
351
+ (ca.height - this.gutterTop - this.gutterBottom)
352
+ );
353
+
354
+ /**
355
+ * Stop this growing uncontrollably
356
+ */
357
+ this.coordsText = [];
358
+
359
+
360
+
361
+ /**
362
+ * Custom centerx, centery and radius
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
+ /**
370
+ * Parse the colors for gradients. Its down here so that the center X/Y can be used
371
+ */
372
+ if (!this.colorsParsed) {
373
+
374
+ this.parseColors();
375
+
376
+ // Don't want to do this again
377
+ this.colorsParsed = true;
378
+ }
379
+
380
+
381
+ this.drawBackground();
382
+ this.drawLabels();
383
+ this.drawNeedle();
384
+ this.drawReadout();
385
+
386
+ /**
387
+ * Draw the title
388
+ */
389
+ RG.DrawTitle(this, prop['chart.title'], this.gutterTop, null, prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2);
390
+
391
+ /**
392
+ * Setup the context menu if required
393
+ */
394
+ if (prop['chart.contextmenu']) {
395
+ RG.ShowContext(this);
396
+ }
397
+
398
+
399
+ /**
400
+ * This function enables resizing
401
+ */
402
+ if (prop['chart.resizable']) {
403
+ RG.AllowResizing(this);
404
+ }
405
+
406
+
407
+ /**
408
+ * This installs the event listeners
409
+ */
410
+ RG.InstallEventListeners(this);
411
+
412
+
413
+
414
+ /**
415
+ * Fire the onfirstdraw event
416
+ */
417
+ if (this.firstDraw) {
418
+ RG.fireCustomEvent(this, 'onfirstdraw');
419
+ this.firstDraw = false;
420
+ this.firstDrawFunc();
421
+ }
422
+
423
+
424
+
425
+
426
+ /**
427
+ * Fire the RGraph ondraw event
428
+ */
429
+ RG.FireCustomEvent(this, 'ondraw');
430
+
431
+
432
+
433
+ return this;
434
+ };
435
+
436
+
437
+
438
+ /**
439
+ * Used in chaining. Runs a function there and then - not waiting for
440
+ * the events to fire (eg the onbeforedraw event)
441
+ *
442
+ * @param function func The function to execute
443
+ */
444
+ this.exec = function (func)
445
+ {
446
+ func(this);
447
+
448
+ return this;
449
+ };
450
+
451
+
452
+
453
+
454
+ /**
455
+ * Draws the background of the chart
456
+ */
457
+ this.drawBackground =
458
+ this.DrawBackground = function ()
459
+ {
460
+ /**
461
+ * First draw the background image if it's defined
462
+ */
463
+ if (typeof prop['chart.background.image.url'] === 'string' && !this.__background_image__) {
464
+
465
+ var x = 0 + prop['chart.background.image.offsetx'];
466
+ var y = 0 + prop['chart.background.image.offsety'];
467
+ var img = new Image();
468
+
469
+ this.__background_image__ = img;
470
+ img.src = prop['chart.background.image.url'];
471
+
472
+ img.onload = function ()
473
+ {
474
+ if (prop['chart.background.image.stretch']) {
475
+ co.drawImage(this, x,y,ca.width, ca.height);
476
+ } else {
477
+ co.drawImage(this, x,y);
478
+ }
479
+ RG.redraw();
480
+ }
481
+
482
+ } else if (this.__background_image__) {
483
+
484
+ var x = 0 + prop['chart.background.image.offsetx'];
485
+ var y = 0 + prop['chart.background.image.offsety'];
486
+
487
+ if (prop['chart.background.image.stretch']) {
488
+ co.drawImage(this.__background_image__, x,y,ca.width, ca.height);
489
+ } else {
490
+ co.drawImage(this.__background_image__, x,y);
491
+ }
492
+ }
493
+
494
+
495
+
496
+ /**
497
+ * Draw the white background
498
+ */
499
+ co.beginPath();
500
+
501
+ co.fillStyle = prop['chart.background.color'];
502
+
503
+ if (prop['chart.shadow']) {
504
+ RG.SetShadow(this, prop['chart.shadow.color'],prop['chart.shadow.offsetx'],prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
505
+ }
506
+ co.moveTo(this.centerx,this.centery);
507
+ co.arc(this.centerx,
508
+ this.centery,
509
+ this.radius,
510
+ prop['chart.angles.start'],
511
+ prop['chart.angles.end'],
512
+ false);
513
+
514
+ co.fill();
515
+
516
+ RG.NoShadow(this);
517
+
518
+
519
+ // Draw the shadow
520
+ if (prop['chart.shadow']) {
521
+
522
+ co.beginPath();
523
+ var r = (this.radius * 0.06) > 40 ? 40 : (this.radius * 0.06);
524
+ co.arc(this.centerx, this.centery, r, 0, RG.TWOPI, 0);
525
+ co.fill();
526
+
527
+ RG.NoShadow(this);
528
+ }
529
+
530
+
531
+
532
+ // First, draw the grey tickmarks
533
+ if (prop['chart.tickmarks.small.num']) {
534
+ for (var i=0; i<(prop['chart.angles.end'] - prop['chart.angles.start']); i+=(RG.PI / prop['chart.tickmarks.small.num'])) {
535
+ co.beginPath();
536
+ co.strokeStyle = prop['chart.tickmarks.small.color'];
537
+ co.arc(this.centerx, this.centery, this.radius, prop['chart.angles.start'] + i, prop['chart.angles.start'] + i + 0.00001, 0);
538
+ co.arc(this.centerx, this.centery, this.radius - 5, prop['chart.angles.start'] + i, prop['chart.angles.start'] + i + 0.00001, 0);
539
+ co.stroke();
540
+ }
541
+
542
+ // Draw the semi-circle that makes the tickmarks
543
+ co.beginPath();
544
+ co.fillStyle = prop['chart.background.color'];
545
+ co.arc(this.centerx, this.centery, this.radius - 4, prop['chart.angles.start'], prop['chart.angles.end'], false);
546
+ co.closePath();
547
+ co.fill();
548
+ }
549
+
550
+
551
+ // Second, draw the darker tickmarks. First run draws them in white to get rid of the existing tickmark,
552
+ // then the second run draws them in the requested color
553
+
554
+
555
+ if (prop['chart.tickmarks.big.num']) {
556
+ var colors = ['white','white',prop['chart.tickmarks.big.color']];
557
+ for (var j=0; j<colors.length; ++j) {
558
+ for (var i=0; i<(prop['chart.angles.end'] - prop['chart.angles.start']); i+=((prop['chart.angles.end'] - prop['chart.angles.start']) / prop['chart.tickmarks.big.num'])) {
559
+ co.beginPath();
560
+ co.strokeStyle = colors[j];
561
+ co.arc(this.centerx, this.centery, this.radius, prop['chart.angles.start'] + i, prop['chart.angles.start'] + i + 0.001, 0);
562
+ co.arc(this.centerx, this.centery, this.radius - 5, prop['chart.angles.start'] + i, prop['chart.angles.start'] + i + 0.0001, 0);
563
+ co.stroke();
564
+ }
565
+ }
566
+ }
567
+
568
+ // Draw the white circle that makes the tickmarks
569
+ co.beginPath();
570
+ co.fillStyle = prop['chart.background.color'];
571
+ co.moveTo(this.centerx, this.centery);
572
+ co.arc(this.centerx, this.centery, this.radius - 7, prop['chart.angles.start'], prop['chart.angles.end'], false);
573
+ co.closePath();
574
+ co.fill();
575
+
576
+ /**
577
+ * Color ranges - either green/yellow/red or an arbitrary number of ranges
578
+ */
579
+ var ranges = prop['chart.colors.ranges'];
580
+
581
+ if (RG.is_array(prop['chart.colors.ranges'])) {
582
+
583
+ var ranges = prop['chart.colors.ranges'];
584
+
585
+ for (var i=0; i<ranges.length; ++i) {
586
+
587
+ co.strokeStyle = prop['chart.strokestyle'] ? prop['chart.strokestyle'] : ranges[i][2];
588
+ co.fillStyle = ranges[i][2];
589
+ co.lineWidth = prop['chart.linewidth.segments'];
590
+
591
+ co.beginPath();
592
+ co.arc(this.centerx,
593
+ this.centery,
594
+ this.radius * 0.85,
595
+ (((ranges[i][0] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
596
+ (((ranges[i][1] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
597
+ false);
598
+
599
+ if (prop['chart.segment.radius.start'] > 0) {
600
+ co.arc(this.centerx,
601
+ this.centery,
602
+ prop['chart.segment.radius.start'],
603
+ (((ranges[i][1] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
604
+ (((ranges[i][0] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
605
+ true);
606
+ } else {
607
+ co.lineTo(this.centerx, this.centery);
608
+ }
609
+
610
+ co.closePath();
611
+ co.stroke();
612
+ co.fill();
613
+ }
614
+
615
+ // Stops the last line from being changed to a big linewidth.
616
+ co.beginPath();
617
+
618
+ } else {
619
+ co.lineWidth = prop['chart.linewidth'];
620
+
621
+ // Draw the green area
622
+ co.strokeStyle = prop['chart.strokestyle'] ? prop['chart.strokestyle'] : prop['chart.green.color'];
623
+ co.fillStyle = prop['chart.green.color'];
624
+ co.lineWidth = prop['chart.linewidth.segments'];
625
+
626
+ co.beginPath();
627
+ co.arc(this.centerx,
628
+ this.centery,
629
+ this.radius * 0.85,
630
+ (((prop['chart.green.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - this.properties['chart.angles.start'])) + prop['chart.angles.start'],
631
+ (((prop['chart.green.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
632
+ false);
633
+
634
+ if (prop['chart.segment.radius.start'] > 0) {
635
+
636
+ co.arc(this.centerx,
637
+ this.centery,
638
+ prop['chart.segment.radius.start'],
639
+ (((prop['chart.green.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
640
+ (((prop['chart.green.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
641
+ true);
642
+ } else {
643
+ co.lineTo(this.centerx, this.centery);
644
+ }
645
+
646
+ co.closePath();
647
+ co.stroke();
648
+ co.fill();
649
+
650
+ // Draw the yellow area
651
+ co.strokeStyle = prop['chart.strokestyle'] ? prop['chart.strokestyle'] : prop['chart.yellow.color'];
652
+ co.fillStyle = prop['chart.yellow.color'];
653
+ co.lineWidth = prop['chart.linewidth.segments'];
654
+ co.beginPath();
655
+ co.arc(this.centerx,
656
+ this.centery,
657
+ this.radius * 0.85,
658
+ (((prop['chart.yellow.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
659
+ (((prop['chart.yellow.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
660
+ false);
661
+
662
+ if (prop['chart.segment.radius.start'] > 0) {
663
+ co.arc(this.centerx,
664
+ this.centery,
665
+ prop['chart.segment.radius.start'],
666
+ (((prop['chart.yellow.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
667
+ (((prop['chart.yellow.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
668
+ true);
669
+ } else {
670
+ co.lineTo(this.centerx, this.centery);
671
+ }
672
+
673
+ co.closePath();
674
+ co.stroke();
675
+ co.fill();
676
+
677
+ // Draw the red area
678
+ co.strokeStyle = prop['chart.strokestyle'] ? prop['chart.strokestyle'] : prop['chart.red.color'];
679
+ co.fillStyle = prop['chart.red.color'];
680
+ co.lineWidth = prop['chart.linewidth.segments'];
681
+
682
+ co.beginPath();
683
+ co.arc(this.centerx,
684
+ this.centery,this.radius * 0.85,
685
+ (((prop['chart.red.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
686
+ (((prop['chart.red.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
687
+ false);
688
+
689
+ if (prop['chart.segment.radius.start'] > 0) {
690
+ co.arc(this.centerx,
691
+ this.centery,
692
+ prop['chart.segment.radius.start'],
693
+ (((prop['chart.red.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
694
+ (((prop['chart.red.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
695
+ true);
696
+ } else {
697
+ co.lineTo(this.centerx, this.centery);
698
+ }
699
+
700
+ co.closePath();
701
+ co.stroke();
702
+ co.fill();
703
+
704
+ // Revert the linewidth
705
+ co.lineWidth = 1;
706
+ }
707
+
708
+ // Draw the outline
709
+ if (prop['chart.border']) {
710
+ co.strokeStyle = prop['chart.border.color'];
711
+ co.lineWidth = prop['chart.linewidth'];
712
+
713
+ co.beginPath();
714
+ co.moveTo(this.centerx, this.centery);
715
+ co.arc(this.centerx,
716
+ this.centery,
717
+ this.radius,
718
+ prop['chart.angles.start'],
719
+ prop['chart.angles.end'],
720
+ false);
721
+ co.closePath();
722
+ }
723
+
724
+ co.stroke();
725
+
726
+ // Reset the linewidth back to 1
727
+ co.lineWidth = 1;
728
+ };
729
+
730
+
731
+
732
+
733
+ /**
734
+ * Draws the pointer
735
+ */
736
+ this.drawNeedle =
737
+ this.DrawNeedle = function ()
738
+ {
739
+ /**
740
+ * The angle that the needle is at
741
+ */
742
+ var a = (((this.value - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'];
743
+
744
+ /**
745
+ * First draw the background image if it's defined
746
+ */
747
+ if (typeof prop['chart.needle.image.url'] === 'string' && !this.__needle_image__) {
748
+
749
+ var img = new Image();
750
+
751
+ this.__needle_image__ = img;
752
+ img.src = prop['chart.needle.image.url'];
753
+
754
+ img.onload = function ()
755
+ {
756
+ co.save();
757
+ RG.rotateCanvas(ca, this.centerx, this.centery, a);
758
+ co.drawImage(this,
759
+ this.centerx + prop['chart.needle.image.offsetx'],
760
+ this.centery + prop['chart.needle.image.offsety']);
761
+ co.restore();
762
+
763
+ RG.redraw();
764
+ }
765
+
766
+ } else if (this.__needle_image__) {
767
+
768
+ co.save();
769
+ RG.rotateCanvas(ca, this.centerx, this.centery, a);
770
+ co.drawImage(this.__needle_image__,
771
+ this.centerx + prop['chart.needle.image.offsetx'],
772
+ this.centery + prop['chart.needle.image.offsety']);
773
+ //pa(co, ['b', 'r', this.centerx, this.centery, 1, 1, 'f', 'red']);
774
+ co.restore();
775
+ }
776
+
777
+
778
+
779
+
780
+
781
+
782
+
783
+
784
+ // Allow customising the needle radius
785
+ var needleRadius = typeof(prop['chart.needle.radius']) == 'number' ? prop['chart.needle.radius'] : this.radius * 0.7;
786
+
787
+ // First draw the circle at the bottom
788
+ co.fillStyle = 'black';
789
+ co.lineWidth = this.radius >= 200 ? 7 : 3;
790
+ co.lineCap = 'round';
791
+
792
+ // Now, draw the arm of the needle
793
+ co.beginPath();
794
+ co.strokeStyle = prop['chart.needle.color'];
795
+ if (typeof(prop['chart.needle.linewidth']) == 'number') co.lineWidth = prop['chart.needle.linewidth'];
796
+
797
+
798
+ co.arc(this.centerx, this.centery, needleRadius, a, a + 0.001, false);
799
+ co.lineTo(this.centerx, this.centery);
800
+ co.stroke();
801
+
802
+ // Draw the triangular needle head
803
+ if (prop['chart.needle.head']) {
804
+
805
+ co.fillStyle = prop['chart.needle.color'];
806
+ co.beginPath();
807
+ co.lineWidth = 1;
808
+ //co.moveTo(this.centerx, this.centery);
809
+ co.arc(this.centerx, this.centery, needleRadius + 15, a, a + 0.001, 0);
810
+ co.arc(this.centerx, this.centery, needleRadius - 15, a + 0.087, a + 0.087999, 0);
811
+ co.arc(this.centerx, this.centery, needleRadius - 15, a - 0.087, a - 0.087999, 1);
812
+ co.fill();
813
+ }
814
+
815
+ // Draw the tail if requested
816
+ if (prop['chart.needle.tail']) {
817
+ co.beginPath();
818
+ co.strokeStyle = prop['chart.needle.color'];
819
+ if (typeof(prop['chart.needle.linewidth']) == 'number') co.lineWidth = prop['chart.needle.linewidth'];
820
+
821
+ var a = ((this.value - this.min) / (this.max - this.min) * (this.properties['chart.angles.end'] - this.properties['chart.angles.start'])) + this.properties['chart.angles.start'] + RG.PI;
822
+ co.arc(this.centerx, this.centery, 25, a, a + 0.001, false);
823
+ co.lineTo(this.centerx, this.centery);
824
+ co.stroke();
825
+ }
826
+
827
+ // Draw the center circle (the stroke)
828
+ var r = (this.radius * 0.06) > 40 ? 40 : (this.radius * 0.06);
829
+
830
+ co.beginPath();
831
+ co.fillStyle = prop['chart.centerpin.stroke'];
832
+ co.arc(this.centerx, this.centery, r, 0 + 0.001, RG.TWOPI, 0);
833
+ co.fill();
834
+
835
+
836
+
837
+
838
+
839
+
840
+
841
+
842
+
843
+
844
+
845
+
846
+
847
+
848
+ // Draw the centre bit of the circle (the fill)
849
+ co.fillStyle = prop['chart.centerpin.fill'];
850
+ co.beginPath();
851
+ co.arc(this.centerx, this.centery, r - 2, 0 + 0.001, RG.TWOPI, 0);
852
+ co.fill();
853
+ };
854
+
855
+
856
+
857
+
858
+ /**
859
+ * Draws the labels
860
+ */
861
+ this.drawLabels =
862
+ this.DrawLabels = function ()
863
+ {
864
+ if (!prop['chart.labels']) {
865
+ return;
866
+ }
867
+
868
+ var radius = this.radius;
869
+ var text_size = prop['chart.text.size'];
870
+ var text_font = prop['chart.text.font'];
871
+ var units_post = prop['chart.units.post'];
872
+ var units_pre = prop['chart.units.pre'];
873
+ var centerx = this.centerx;
874
+ var centery = this.centery;
875
+ var min = this.min;
876
+ var max = this.max;
877
+ var decimals = prop['chart.scale.decimals'];
878
+ var numLabels = prop['chart.labels.count'];
879
+
880
+ co.fillStyle = prop['chart.text.color'];
881
+ co.lineWidth = 1;
882
+
883
+ co.beginPath();
884
+
885
+ for (var i=0; i<=numLabels; ++i) {
886
+
887
+ var angle = ((prop['chart.angles.end'] - prop['chart.angles.start']) * (i / numLabels)) + prop['chart.angles.start'];
888
+ var coords = RG.getRadiusEndPoint(centerx, centery, angle + (((i == 0 || i == numLabels) && prop['chart.border']) ? (i == 0 ? 0.05 : -0.05) : 0), (this.radius * 0.925) - (prop['chart.text.valign'] === 'bottom' ? 15 : 0));
889
+
890
+ var angleStart = prop['chart.angles.start'];
891
+ var angleEnd = prop['chart.angles.end'];
892
+ var angleRange = angleEnd - angleStart;
893
+
894
+ var angleStart_degrees = angleStart * (180 / RG.PI);
895
+ var angleEnd_degrees = angleEnd * (180 / RG.PI);
896
+ var angleRange_degrees = angleRange * (180 / RG.PI);
897
+
898
+ // Vertical alignment
899
+ valign = prop['chart.text.valign'];
900
+
901
+ // Horizontal alignment
902
+ if (prop['chart.border']) {
903
+ if (i == 0) {
904
+ halign = 'left';
905
+ } else if (i == numLabels) {
906
+ halign = 'right';
907
+ } else {
908
+ halign = 'center'
909
+ }
910
+ } else {
911
+ halign = 'center';
912
+ }
913
+
914
+ RG.Text2(this, {'font':text_font,
915
+ 'size':text_size,
916
+ 'x':coords[0],
917
+ 'y':coords[1],
918
+ 'text':RG.numberFormat(this, (((this.max - this.min) * (i / numLabels)) + this.min).toFixed(decimals),units_pre,units_post),
919
+ 'halign':halign,
920
+ 'valign':valign,
921
+ 'angle':((angleRange_degrees * (1 / numLabels) * i) + angleStart_degrees) - 270,
922
+ 'bounding':false,
923
+ 'boundingFill':(i == 0 || i == numLabels) ? 'white': null,
924
+ 'tag': 'scale'
925
+ });
926
+ }
927
+ };
928
+
929
+
930
+
931
+
932
+ /**
933
+ * This function draws the text readout if specified
934
+ */
935
+ this.drawReadout =
936
+ this.DrawReadout = function ()
937
+ {
938
+ if (prop['chart.value.text']) {
939
+ co.beginPath();
940
+ co.fillStyle = prop['chart.text.color'];
941
+ RG.Text2(this, {'font':prop['chart.text.font'],
942
+ 'size':prop['chart.text.size'],
943
+ 'x':this.centerx,
944
+ 'y':this.centery - prop['chart.text.size'] - 15,
945
+ 'text': prop['chart.value.text.units.pre'] + (this.value).toFixed(prop['chart.value.text.decimals']) + prop['chart.value.text.units.post'],
946
+ 'halign':'center',
947
+ 'valign':'bottom',
948
+ 'bounding':true,
949
+ 'boundingFill':'white',
950
+ 'tag': 'value.text'
951
+ });
952
+
953
+ co.stroke();
954
+ co.fill();
955
+ }
956
+ };
957
+
958
+
959
+
960
+
961
+ /**
962
+ * A placeholder function
963
+ *
964
+ * @param object The event object
965
+ */
966
+ this.getShape = function (e) {};
967
+
968
+
969
+
970
+
971
+ /**
972
+ * This function returns the pertinent value for a particular click (or other mouse event)
973
+ *
974
+ * @param obj e The event object
975
+ */
976
+ this.getValue = function (e)
977
+ {
978
+ var mouseXY = RG.getMouseXY(e);
979
+ var angle = RG.getAngleByXY(this.centerx, this.centery, mouseXY[0], mouseXY[1]);
980
+
981
+ // Work out the radius
982
+ var radius = RG.getHypLength(this.centerx, this.centery, mouseXY[0], mouseXY[1]);
983
+ if (radius > this.radius) {
984
+ return null;
985
+ }
986
+
987
+
988
+ if (angle < RG.HALFPI) {
989
+ angle += RG.TWOPI;
990
+ }
991
+
992
+ var value = (((angle - prop['chart.angles.start']) / (prop['chart.angles.end'] - prop['chart.angles.start'])) * (this.max - this.min)) + this.min;
993
+
994
+ value = Math.max(value, this.min);
995
+ value = Math.min(value, this.max);
996
+
997
+ return value;
998
+ };
999
+
1000
+
1001
+
1002
+
1003
+ /**
1004
+ * The getObjectByXY() worker method. Don't call this call:
1005
+ *
1006
+ * RGraph.ObjectRegistry.getObjectByXY(e)
1007
+ *
1008
+ * @param object e The event object
1009
+ */
1010
+ this.getObjectByXY = function (e)
1011
+ {
1012
+ var mouseXY = RGraph.getMouseXY(e);
1013
+
1014
+ // Work out the radius
1015
+ var radius = RG.getHypLength(this.centerx, this.centery, mouseXY[0], mouseXY[1]);
1016
+
1017
+ if (
1018
+ mouseXY[0] > (this.centerx - this.radius)
1019
+ && mouseXY[0] < (this.centerx + this.radius)
1020
+ && mouseXY[1] > (this.centery - this.radius)
1021
+ && mouseXY[1] < (this.centery + this.radius)
1022
+ && radius <= this.radius
1023
+ ) {
1024
+
1025
+ return this;
1026
+ }
1027
+ };
1028
+
1029
+
1030
+
1031
+
1032
+ /**
1033
+ * This method handles the adjusting calculation for when the mouse is moved
1034
+ *
1035
+ * @param object e The event object
1036
+ */
1037
+ this.adjusting_mousemove =
1038
+ this.Adjusting_mousemove = function (e)
1039
+ {
1040
+ /**
1041
+ * Handle adjusting for the Bar
1042
+ */
1043
+ if (prop['chart.adjustable'] && RG.Registry.Get('chart.adjusting') && RG.Registry.Get('chart.adjusting').uid == this.uid) {
1044
+ this.value = this.getValue(e);
1045
+ RG.clear(this.canvas);
1046
+ RG.redrawCanvas(this.canvas);
1047
+ RG.fireCustomEvent(this, 'onadjust');
1048
+ }
1049
+ };
1050
+
1051
+
1052
+
1053
+
1054
+ /**
1055
+ * This method returns the appropriate angle for a value
1056
+ *
1057
+ * @param number value The value
1058
+ */
1059
+ this.getAngle = function (value)
1060
+ {
1061
+ // Higher than max
1062
+ if (value > this.max || value < this.min) {
1063
+ return null;
1064
+ }
1065
+
1066
+ var angle = (((value - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'];
1067
+
1068
+ return angle;
1069
+ };
1070
+
1071
+
1072
+
1073
+
1074
+ /**
1075
+ * This allows for easy specification of gradients
1076
+ */
1077
+ this.parseColors = function ()
1078
+ {
1079
+ // Save the original colors so that they can be restored when the canvas is reset
1080
+ if (this.original_colors.length === 0) {
1081
+ this.original_colors['chart.green.color'] = RG.array_clone(prop['chart.green.color']);
1082
+ this.original_colors['chart.yellow.color'] = RG.array_clone(prop['chart.yellow.color']);
1083
+ this.original_colors['chart.red.color'] = RG.array_clone(prop['chart.red.color']);
1084
+ this.original_colors['chart.colors.ranges'] = RG.array_clone(prop['chart.colors.ranges']);
1085
+ }
1086
+
1087
+ // Parse the basic colors
1088
+ prop['chart.green.color'] = this.parseSingleColorForGradient(prop['chart.green.color']);
1089
+ prop['chart.yellow.color'] = this.parseSingleColorForGradient(prop['chart.yellow.color']);
1090
+ prop['chart.red.color'] = this.parseSingleColorForGradient(prop['chart.red.color']);
1091
+
1092
+ // Parse chart.colors.ranges
1093
+ var ranges = prop['chart.colors.ranges'];
1094
+ if (ranges && ranges.length) {
1095
+ for (var i=0; i<ranges.length; ++i) {
1096
+ ranges[i][2] = this.parseSingleColorForGradient(ranges[i][2]);
1097
+ }
1098
+ }
1099
+ };
1100
+
1101
+
1102
+
1103
+
1104
+ /**
1105
+ * Use this function to reset the object to the post-constructor state. Eg reset colors if
1106
+ * need be etc
1107
+ */
1108
+ this.reset = function ()
1109
+ {
1110
+ };
1111
+
1112
+
1113
+
1114
+
1115
+ /**
1116
+ * This parses a single color value
1117
+ */
1118
+ this.parseSingleColorForGradient = function (color)
1119
+ {
1120
+ if (!color || typeof(color) != 'string') {
1121
+ return color;
1122
+ }
1123
+
1124
+ if (color.match(/^gradient\((.*)\)$/i)) {
1125
+
1126
+ var parts = RegExp.$1.split(':');
1127
+
1128
+ // Create the gradient
1129
+ var grad = co.createRadialGradient(this.centerx, this.centery, prop['chart.segment.radius.start'], this.centerx, this.centery, this.radius * 0.85);
1130
+
1131
+ var diff = 1 / (parts.length - 1);
1132
+
1133
+ for (var j=0; j<parts.length; ++j) {
1134
+ grad.addColorStop(j * diff, RG.trim(parts[j]));
1135
+ }
1136
+ }
1137
+
1138
+ return grad ? grad : color;
1139
+ };
1140
+
1141
+
1142
+
1143
+
1144
+ /**
1145
+ * Using a function to add events makes it easier to facilitate method chaining
1146
+ *
1147
+ * @param string type The type of even to add
1148
+ * @param function func
1149
+ */
1150
+ this.on = function (type, func)
1151
+ {
1152
+ if (type.substr(0,2) !== 'on') {
1153
+ type = 'on' + type;
1154
+ }
1155
+
1156
+ this[type] = func;
1157
+
1158
+ return this;
1159
+ };
1160
+
1161
+
1162
+
1163
+
1164
+ /**
1165
+ * This function runs once only
1166
+ * (put at the end of the file (before any effects))
1167
+ */
1168
+ this.firstDrawFunc = function ()
1169
+ {
1170
+ };
1171
+
1172
+
1173
+
1174
+
1175
+ /**
1176
+ * Meter Grow
1177
+ *
1178
+ * This effect gradually increases the represented value
1179
+ *
1180
+ * @param An object of options - eg: {frames: 60}
1181
+ * @param function An optional callback function
1182
+ */
1183
+ this.grow = function ()
1184
+ {
1185
+ var obj = this;
1186
+
1187
+ obj.currentValue = obj.currentValue || obj.min;
1188
+
1189
+ var opt = arguments[0] || {};
1190
+ var frames = opt.frames || 30;
1191
+ var frame = 0;
1192
+ var diff = obj.value - obj.currentValue;
1193
+ var step = diff / frames;
1194
+ var callback = arguments[1] || function () {};
1195
+ var initial = obj.currentValue;
1196
+
1197
+
1198
+
1199
+ function iterator ()
1200
+ {
1201
+ obj.value = initial + (frame++ * step);
1202
+
1203
+ RG.clear(obj.canvas);
1204
+ RG.redrawCanvas(obj.canvas);
1205
+
1206
+ if (frame <= frames) {
1207
+ RG.Effects.updateCanvas(iterator);
1208
+ } else {
1209
+ callback(obj);
1210
+ }
1211
+ }
1212
+
1213
+ iterator();
1214
+
1215
+ return this;
1216
+ };
1217
+
1218
+
1219
+
1220
+
1221
+
1222
+ RG.att(ca);
1223
+
1224
+
1225
+
1226
+
1227
+ /**
1228
+ * Register the object
1229
+ */
1230
+ RG.register(this);
1231
+
1232
+
1233
+
1234
+
1235
+ /**
1236
+ * This is the 'end' of the constructor so if the first argument
1237
+ * contains configuration data - handle that.
1238
+ */
1239
+ if (parseConfObjectForOptions) {
1240
+ RG.parseObjectStyleConfig(this, conf.options);
1241
+ }
1242
+ };