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,1326 @@
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
+
20
+
21
+ /**
22
+ * The progress bar constructor
23
+ *
24
+ * @param mixed conf This can either be an object that contains all of the configuration data
25
+ * (the updated way of configuring the object) or it can be a string consisting of the
26
+ * canvas ID
27
+ * @param number The minimum value (if using the older configuration style)
28
+ * @param number The maximum value (if using the older configuration style)
29
+ * @param number The represented value (if using the older configuration style)
30
+ */
31
+ RGraph.VProgress = function (conf)
32
+ {
33
+ /**
34
+ * Allow for object config style
35
+ */
36
+ if ( typeof conf === 'object'
37
+ && typeof conf.min === 'number'
38
+ && typeof conf.max === 'number'
39
+ && typeof conf.id === 'string') {
40
+
41
+ var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
42
+
43
+ } else {
44
+
45
+ var conf = {
46
+ id: arguments[0],
47
+ min: arguments[1],
48
+ max: arguments[2],
49
+ value: arguments[3]
50
+ }
51
+ }
52
+
53
+
54
+
55
+
56
+ this.id = conf.id;
57
+ this.canvas = document.getElementById(this.id);
58
+ this.context = this.canvas.getContext('2d');
59
+ this.canvas.__object__ = this;
60
+
61
+ this.min = conf.min;
62
+ this.max = conf.max;
63
+ this.value = RGraph.stringsToNumbers(conf.value);
64
+ this.type = 'vprogress';
65
+ this.coords = [];
66
+ this.isRGraph = true;
67
+ this.currentValue = null;
68
+ this.uid = RGraph.CreateUID();
69
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
70
+ this.colorsParsed = false;
71
+ this.coordsText = [];
72
+ this.original_colors = [];
73
+ this.firstDraw = true; // After the first draw this will be false
74
+
75
+
76
+ /**
77
+ * Compatibility with older browsers
78
+ */
79
+ //RGraph.OldBrowserCompat(this.context);
80
+
81
+ this.properties =
82
+ {
83
+ 'chart.colors': ['Gradient(white:#0c0)','Gradient(white:red)','Gradient(white:green)','yellow','pink','cyan','black','white','gray'],
84
+ 'chart.strokestyle.inner': '#999',
85
+ 'chart.strokestyle.outer': '#999',
86
+ 'chart.tickmarks': true,
87
+ 'chart.tickmarks.zerostart':true,
88
+ 'chart.tickmarks.color': '#999',
89
+ 'chart.tickmarks.inner': false,
90
+ 'chart.gutter.left': 25,
91
+ 'chart.gutter.right': 25,
92
+ 'chart.gutter.top': 25,
93
+ 'chart.gutter.bottom': 25,
94
+ 'chart.numticks': 10,
95
+ 'chart.numticks.inner': 50,
96
+ 'chart.background.color': '#eee',
97
+ 'chart.shadow': false,
98
+ 'chart.shadow.color': 'rgba(0,0,0,0.5)',
99
+ 'chart.shadow.blur': 3,
100
+ 'chart.shadow.offsetx': 3,
101
+ 'chart.shadow.offsety': 3,
102
+ 'chart.title': '',
103
+ 'chart.title.bold': true,
104
+ 'chart.title.font': null,
105
+ 'chart.title.size': null,
106
+ 'chart.title.color': 'black',
107
+ 'chart.title.side': null,
108
+ 'chart.title.side.font': 'Arial',
109
+ 'chart.title.side.size': 12,
110
+ 'chart.title.side.color': 'black',
111
+ 'chart.title.side.bold': true,
112
+ 'chart.text.size': 12,
113
+ 'chart.text.color': 'black',
114
+ 'chart.text.font': 'Arial',
115
+ 'chart.contextmenu': null,
116
+ 'chart.units.pre': '',
117
+ 'chart.units.post': '',
118
+ 'chart.tooltips': null,
119
+ 'chart.tooltips.effect': 'fade',
120
+ 'chart.tooltips.css.class': 'RGraph_tooltip',
121
+ 'chart.tooltips.highlight': true,
122
+ 'chart.tooltips.event': 'onclick',
123
+ 'chart.highlight.stroke': 'rgba(0,0,0,0)',
124
+ 'chart.highlight.fill': 'rgba(255,255,255,0.7)',
125
+ 'chart.annotatable': false,
126
+ 'chart.annotate.color': 'black',
127
+ 'chart.zoom.factor': 1.5,
128
+ 'chart.zoom.fade.in': true,
129
+ 'chart.zoom.fade.out': true,
130
+ 'chart.zoom.hdir': 'right',
131
+ 'chart.zoom.vdir': 'down',
132
+ 'chart.zoom.frames': 25,
133
+ 'chart.zoom.delay': 16.666,
134
+ 'chart.zoom.shadow': true,
135
+ 'chart.zoom.background': true,
136
+ 'chart.zoom.action': 'zoom',
137
+ 'chart.arrows': false,
138
+ 'chart.margin': 0,
139
+ 'chart.resizable': false,
140
+ 'chart.resize.handle.adjust': [0,0],
141
+ 'chart.resize.handle.background': null,
142
+ 'chart.label.inner': false,
143
+ 'chart.labels.count': 10,
144
+ 'chart.labels.position': 'right',
145
+ 'chart.adjustable': false,
146
+ 'chart.scale.decimals': 0,
147
+ 'chart.scale.thousand': ',',
148
+ 'chart.scale.point': '.',
149
+ 'chart.key': null,
150
+ 'chart.key.background': 'white',
151
+ 'chart.key.position': 'graph',
152
+ 'chart.key.halign': 'right',
153
+ 'chart.key.shadow': false,
154
+ 'chart.key.shadow.color': '#666',
155
+ 'chart.key.shadow.blur': 3,
156
+ 'chart.key.shadow.offsetx': 2,
157
+ 'chart.key.shadow.offsety': 2,
158
+ 'chart.key.position.gutter.boxed': false,
159
+ 'chart.key.position.x': null,
160
+ 'chart.key.position.y': null,
161
+ 'chart.key.color.shape': 'square',
162
+ 'chart.key.rounded': true,
163
+ 'chart.key.linewidth': 1,
164
+ 'chart.key.colors': null,
165
+ 'chart.key.interactive': false,
166
+ 'chart.key.interactive.highlight.chart.stroke': '#000',
167
+ 'chart.key.interactive.highlight.chart.fill': 'rgba(255,255,255,0.7)',
168
+ 'chart.key.interactive.highlight.label': 'rgba(255,0,0,0.2)',
169
+ 'chart.key.text.color': 'black',
170
+ 'chart.events.click': null,
171
+ 'chart.events.mousemove': null,
172
+ 'chart.border.inner': true
173
+ }
174
+
175
+ // Check for support
176
+ if (!this.canvas) {
177
+ alert('[PROGRESS] No canvas support');
178
+ return;
179
+ }
180
+
181
+
182
+ /**
183
+ * Create the dollar objects so that functions can be added to them
184
+ */
185
+ var linear_data = RGraph.arrayLinearize(this.value);
186
+ for (var i=0; i<linear_data.length; ++i) {
187
+ this['$' + i] = {};
188
+ }
189
+
190
+
191
+ /**
192
+ * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
193
+ * done already
194
+ */
195
+ if (!this.canvas.__rgraph_aa_translated__) {
196
+ this.context.translate(0.5,0.5);
197
+
198
+ this.canvas.__rgraph_aa_translated__ = true;
199
+ }
200
+
201
+
202
+
203
+
204
+ // Short variable names
205
+ var RG = RGraph,
206
+ ca = this.canvas,
207
+ co = ca.getContext('2d'),
208
+ prop = this.properties,
209
+ pa = RG.Path,
210
+ pa2 = RG.path2,
211
+ win = window,
212
+ doc = document,
213
+ ma = Math
214
+
215
+
216
+
217
+ /**
218
+ * "Decorate" the object with the generic effects if the effects library has been included
219
+ */
220
+ if (RG.Effects && typeof RG.Effects.decorate === 'function') {
221
+ RG.Effects.decorate(this);
222
+ }
223
+
224
+
225
+
226
+
227
+ /**
228
+ * A generic setter
229
+ *
230
+ * @param string name The name of the property to set or it can also be an object containing
231
+ * object style configuration
232
+ */
233
+ this.set =
234
+ this.Set = function (name)
235
+ {
236
+ var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
237
+
238
+ /**
239
+ * the number of arguments is only one and it's an
240
+ * object - parse it for configuration data and return.
241
+ */
242
+ if (arguments.length === 1 && typeof name === 'object') {
243
+ RG.parseObjectStyleConfig(this, name);
244
+ return this;
245
+ }
246
+
247
+
248
+
249
+ /**
250
+ * This should be done first - prepend the propertyy name with "chart." if necessary
251
+ */
252
+ if (name.substr(0,6) != 'chart.') {
253
+ name = 'chart.' + name;
254
+ }
255
+
256
+ /**
257
+ * chart.strokestyle now sets both chart.strokestyle.inner and chart.strokestyle.outer
258
+ */
259
+ if (name == 'chart.strokestyle') {
260
+ prop['chart.strokestyle.inner'] = value;
261
+ prop['chart.strokestyle.outer'] = value;
262
+
263
+ return;
264
+ }
265
+
266
+
267
+
268
+ // Convert uppercase letters to dot+lower case letter
269
+ name = name.replace(/([A-Z])/g, function (str)
270
+ {
271
+ return '.' + String(RegExp.$1).toLowerCase();
272
+ });
273
+
274
+
275
+
276
+
277
+ prop[name.toLowerCase()] = value;
278
+
279
+ return this;
280
+ };
281
+
282
+
283
+
284
+
285
+ /**
286
+ * A generic getter
287
+ *
288
+ * @param string name 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
+ return prop[name.toLowerCase()];
307
+ };
308
+
309
+
310
+
311
+
312
+ /**
313
+ * Draws the progress bar
314
+ */
315
+ this.draw =
316
+ this.Draw = function ()
317
+ {
318
+ /**
319
+ * Fire the onbeforedraw event
320
+ */
321
+ RG.FireCustomEvent(this, 'onbeforedraw');
322
+
323
+
324
+
325
+ /**
326
+ * Parse the colors. This allows for simple gradient syntax
327
+ */
328
+ if (!this.colorsParsed) {
329
+
330
+ this.parseColors();
331
+
332
+
333
+ // Don't want to do this again
334
+ this.colorsParsed = true;
335
+ }
336
+
337
+
338
+ /**
339
+ * Set the current value
340
+ */
341
+ this.currentValue = this.value;
342
+
343
+ /**
344
+ * This is new in May 2011 and facilitates indiviual gutter settings,
345
+ * eg chart.gutter.left
346
+ */
347
+ this.gutterLeft = prop['chart.gutter.left'];
348
+ this.gutterRight = prop['chart.gutter.right'];
349
+ this.gutterTop = prop['chart.gutter.top'];
350
+ this.gutterBottom = prop['chart.gutter.bottom'];
351
+
352
+ // Figure out the width and height
353
+ this.width = ca.width - this.gutterLeft - this.gutterRight;
354
+ this.height = ca.height - this.gutterTop - this.gutterBottom;
355
+ this.coords = [];
356
+
357
+
358
+
359
+ /**
360
+ * Stop this growing uncontrollably
361
+ */
362
+ this.coordsText = [];
363
+
364
+
365
+
366
+
367
+
368
+ this.Drawbar();
369
+ this.DrawTickMarks();
370
+ this.DrawLabels();
371
+ this.DrawTitles();
372
+
373
+ co.stroke();
374
+ co.fill();
375
+
376
+
377
+ /**
378
+ * Draw the bevel effect if requested
379
+ */
380
+ if (prop['chart.bevel']) {
381
+ this.DrawBevel();
382
+ }
383
+
384
+
385
+
386
+ /**
387
+ * Setup the context menu if required
388
+ */
389
+ if (prop['chart.contextmenu']) {
390
+ RG.ShowContext(this);
391
+ }
392
+
393
+
394
+ /**
395
+ * This installs the event listeners
396
+ */
397
+ RG.InstallEventListeners(this);
398
+
399
+ // Draw a key if necessary
400
+ if (prop['chart.key'] && prop['chart.key'].length) {
401
+ RG.DrawKey(this, prop['chart.key'], prop['chart.colors']);
402
+ }
403
+
404
+
405
+
406
+ /**
407
+ * This function enables resizing
408
+ */
409
+ if (prop['chart.resizable']) {
410
+ RG.AllowResizing(this);
411
+ }
412
+
413
+ /**
414
+ * Instead of using RGraph.common.adjusting.js, handle them here
415
+ */
416
+ this.AllowAdjusting();
417
+
418
+
419
+ /**
420
+ * Fire the onfirstdraw event
421
+ */
422
+ if (this.firstDraw) {
423
+ RG.fireCustomEvent(this, 'onfirstdraw');
424
+ this.firstDraw = false;
425
+ this.firstDrawFunc();
426
+ }
427
+
428
+
429
+
430
+
431
+ /**
432
+ * Fire the RGraph ondraw event
433
+ */
434
+ RG.FireCustomEvent(this, 'ondraw');
435
+
436
+ return this;
437
+ };
438
+
439
+
440
+
441
+
442
+ /**
443
+ * Draw the bar itself
444
+ */
445
+ this.drawbar =
446
+ this.Drawbar = function ()
447
+ {
448
+ /**
449
+ * First get the scale
450
+ */
451
+ this.scale2 = RGraph.getScale2(this, {
452
+ 'max':this.max,
453
+ 'min':this.min,
454
+ 'strict':true,
455
+ 'scale.thousand':prop['chart.scale.thousand'],
456
+ 'scale.point':prop['chart.scale.point'],
457
+ 'scale.decimals':prop['chart.scale.decimals'],
458
+ 'ylabels.count':prop['chart.labels.count'],
459
+ 'scale.round':prop['chart.scale.round'],
460
+ 'units.pre': prop['chart.units.pre'],
461
+ 'units.post': prop['chart.units.post']
462
+ });
463
+
464
+
465
+ // Set a shadow if requested
466
+ if (prop['chart.shadow']) {
467
+ RG.SetShadow(this, prop['chart.shadow.color'], prop['chart.shadow.offsetx'], prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
468
+ }
469
+
470
+ // Draw the shadow for MSIE
471
+ if (RGraph.ISOLD && prop['chart.shadow']) {
472
+ co.fillStyle = prop['chart.shadow.color'];
473
+ co.fillRect(this.gutterLeft + prop['chart.shadow.offsetx'], this.gutterTop + prop['chart.shadow.offsety'], this.width, this.height);
474
+ }
475
+
476
+ // Draw the outline
477
+ co.fillStyle = prop['chart.background.color'];
478
+ co.strokeStyle = prop['chart.strokestyle.outer'];
479
+ co.strokeRect(this.gutterLeft, this.gutterTop, this.width, this.height);
480
+ co.fillRect(this.gutterLeft, this.gutterTop, this.width, this.height);
481
+
482
+ // Turn off any shadow
483
+ RG.NoShadow(this);
484
+
485
+ co.strokeStyle = prop['chart.strokestyle.outer'];
486
+ co.fillStyle = prop['chart.colors'][0];
487
+ var margin = prop['chart.margin'];
488
+ var barHeight = (ca.height - this.gutterTop - this.gutterBottom) * ((RG.arraySum(this.value) - this.min) / (this.max - this.min));
489
+
490
+ // Draw the actual bar itself
491
+ if (typeof this.value == 'number') {
492
+
493
+ co.lineWidth = 1;
494
+ co.strokeStyle = prop['chart.strokestyle.inner'];
495
+
496
+ } else if (typeof this.value == 'object') {
497
+
498
+ co.beginPath();
499
+ co.strokeStyle = prop['chart.strokestyle.inner'];
500
+
501
+ var startPoint = ca.height - this.gutterBottom;
502
+
503
+ for (var i=0; i<this.value.length; ++i) {
504
+
505
+ var segmentHeight = ( (this.value[i] - this.min) / (this.max - this.min) ) * (ca.height - this.gutterBottom - this.gutterTop);
506
+
507
+ co.fillStyle = prop['chart.colors'][i];
508
+
509
+ if (prop['chart.border.inner']) {
510
+ co.strokeRect(this.gutterLeft + margin, startPoint - segmentHeight, this.width - margin - margin, segmentHeight);
511
+ }
512
+ co.fillRect(this.gutterLeft + margin, startPoint - segmentHeight, this.width - margin - margin, segmentHeight);
513
+
514
+
515
+
516
+ // Store the coords
517
+ this.coords.push([this.gutterLeft + margin, startPoint - segmentHeight, this.width - margin - margin, segmentHeight]);
518
+
519
+ startPoint -= segmentHeight;
520
+ }
521
+
522
+
523
+ co.stroke();
524
+ co.fill();
525
+ }
526
+
527
+ /**
528
+ * Inner tickmarks
529
+ */
530
+ if (prop['chart.tickmarks.inner']) {
531
+
532
+ var spacing = (ca.height - this.gutterTop - this.gutterBottom) / prop['chart.numticks.inner'];
533
+
534
+ co.lineWidth = 1;
535
+ co.strokeStyle = prop['chart.strokestyle.outer'];
536
+
537
+ co.beginPath();
538
+
539
+ for (var y = this.gutterTop; y<ca.height - this.gutterBottom; y+=spacing) {
540
+ co.moveTo(this.gutterLeft, Math.round(y));
541
+ co.lineTo(this.gutterLeft + 3, Math.round(y));
542
+
543
+ co.moveTo(ca.width - this.gutterRight, Math.round(y));
544
+ co.lineTo(ca.width - this.gutterRight - 3, Math.round(y));
545
+ }
546
+
547
+ co.stroke();
548
+ }
549
+
550
+ co.beginPath();
551
+ co.strokeStyle = prop['chart.strokestyle.inner'];
552
+
553
+ if (typeof this.value == 'number') {
554
+
555
+ if (prop['chart.border.inner']) {
556
+ co.strokeRect(this.gutterLeft + margin, this.gutterTop + this.height - barHeight, this.width - margin - margin, barHeight);
557
+ }
558
+ co.fillRect(
559
+ this.gutterLeft + margin,
560
+ this.gutterTop + this.height - barHeight,
561
+ this.width - margin - margin,
562
+ barHeight
563
+ );
564
+
565
+ // Store the coords
566
+ this.coords.push([this.gutterLeft + margin, this.gutterTop + this.height - barHeight, this.width - margin - margin, barHeight]);
567
+ }
568
+
569
+
570
+ /**
571
+ * Draw the arrows indicating the level if requested
572
+ */
573
+ if (prop['chart.arrows']) {
574
+ var x = this.gutterLeft - 4;
575
+ var y = ca.height - this.gutterBottom - barHeight;
576
+
577
+ co.lineWidth = 1;
578
+ co.fillStyle = 'black';
579
+ co.strokeStyle = 'black';
580
+
581
+ co.beginPath();
582
+ co.moveTo(x, y);
583
+ co.lineTo(x - 4, y - 2);
584
+ co.lineTo(x - 4, y + 2);
585
+ co.closePath();
586
+
587
+ co.stroke();
588
+ co.fill();
589
+
590
+ x += this.width + 8;
591
+
592
+ co.beginPath();
593
+ co.moveTo(x, y);
594
+ co.lineTo(x + 4, y - 2);
595
+ co.lineTo(x + 4, y + 2);
596
+ co.closePath();
597
+
598
+ co.stroke();
599
+ co.fill();
600
+ }
601
+
602
+
603
+
604
+
605
+ /**
606
+ * Draw the "in-bar" label
607
+ */
608
+ if (prop['chart.label.inner']) {
609
+ co.fillStyle = 'black';
610
+ RG.Text2(this, {'font':prop['chart.text.font'],
611
+ 'size':prop['chart.text.size'],
612
+ 'x':((ca.width - this.gutterLeft - this.gutterRight) / 2) + this.gutterLeft,'y':this.coords[this.coords.length - 1][1] - 5,'text':RGraph.number_format(this, (typeof(this.value) == 'number' ? this.value : RG.array_sum(this.value)).toFixed(prop['chart.scale.decimals'])),
613
+ 'valign':'bottom',
614
+ 'halign':'center',
615
+ 'bounding':true,
616
+ 'boundingFill':'white',
617
+ 'tag': 'label.inner'
618
+ });
619
+ }
620
+ };
621
+
622
+
623
+
624
+
625
+ /**
626
+ * The function that draws the tick marks.
627
+ */
628
+ this.drawTickMarks =
629
+ this.DrawTickMarks = function ()
630
+ {
631
+ co.strokeStyle = prop['chart.tickmarks.color'];
632
+
633
+ if (prop['chart.tickmarks']) {
634
+ co.beginPath();
635
+ for (var i=0; prop['chart.tickmarks.zerostart'] ? i<=prop['chart.numticks'] : i<prop['chart.numticks']; i++) {
636
+
637
+ var startX = prop['chart.labels.position'] == 'left' ? this.gutterLeft : ca.width - prop['chart.gutter.right'];
638
+ var endX = prop['chart.labels.position'] == 'left' ? startX - 4 : startX + 4;
639
+ var yPos = (this.height * (i / prop['chart.numticks'])) + this.gutterTop
640
+
641
+ co.moveTo(startX, Math.round(yPos));
642
+ co.lineTo(endX, Math.round(yPos));
643
+ }
644
+ co.stroke();
645
+ }
646
+ };
647
+
648
+
649
+
650
+
651
+ /**
652
+ * The function that draws the labels
653
+ */
654
+ this.drawLabels =
655
+ this.DrawLabels = function ()
656
+ {
657
+ if (!RG.is_null(prop['chart.labels.specific'])) {
658
+ return this.DrawSpecificLabels();
659
+ }
660
+
661
+ co.fillStyle = prop['chart.text.color'];
662
+
663
+ var position = prop['chart.labels.position'];
664
+ var xAlignment = position == 'left' ? 'right' : 'left';
665
+ var yAlignment = 'center';
666
+ var count = prop['chart.labels.count'];
667
+ var units_pre = prop['chart.units.pre'];
668
+ var units_post = prop['chart.units.post'];
669
+ var text_size = prop['chart.text.size'];
670
+ var text_font = prop['chart.text.font'];
671
+ var decimals = prop['chart.scale.decimals'];
672
+
673
+ if (prop['chart.tickmarks']) {
674
+
675
+ for (var i=0; i<count ; ++i) {
676
+ RG.Text2(this, {'font':text_font,
677
+ 'size':text_size,
678
+ 'x':position == 'left' ? (this.gutterLeft - 7) : (ca.width - this.gutterRight + 7),
679
+ 'y':(((ca.height - this.gutterTop - this.gutterBottom) / count) * i) + this.gutterTop,
680
+ 'text':this.scale2.labels[this.scale2.labels.length - (i+1)],
681
+ 'valign':yAlignment,
682
+ 'halign':xAlignment,
683
+ 'tag': 'scale'
684
+ });
685
+ }
686
+
687
+ /**
688
+ * Show zero?
689
+ */
690
+ if (prop['chart.tickmarks.zerostart'] && this.min == 0) {
691
+ RG.Text2(this, {'font':text_font,
692
+ 'size':text_size,
693
+ 'x':position == 'left' ? (this.gutterLeft - 5) : (ca.width - this.gutterRight + 5),
694
+ 'y':ca.height - this.gutterBottom,'text':RG.number_format(this, this.min.toFixed(decimals), units_pre, units_post),
695
+ 'valign':yAlignment,
696
+ 'halign':xAlignment,
697
+ 'tag': 'scale'
698
+ });
699
+ }
700
+
701
+ /**
702
+ * min is set
703
+ */
704
+ if (this.min != 0) {
705
+ RG.Text2(this, {'font':text_font,
706
+ 'size':text_size,
707
+ 'x':position == 'left' ? (this.gutterLeft - 5) : (ca.width - this.gutterRight + 5),
708
+ 'y':ca.height - this.gutterBottom,
709
+ 'text':RG.number_format(this, this.min.toFixed(decimals), units_pre, units_post),
710
+ 'valign':yAlignment,
711
+ 'halign':xAlignment,
712
+ 'tag': 'scale'
713
+ });
714
+ }
715
+ }
716
+ };
717
+
718
+
719
+
720
+
721
+ /**
722
+ * Draws titles
723
+ */
724
+ this.drawTitles =
725
+ this.DrawTitles = function ()
726
+ {
727
+ var text_size = prop['chart.text.size'];
728
+ var text_font = prop['chart.text.font'];
729
+ var title_size = prop['chart.title.size'] ? prop['chart.title.size'] : text_size + 2;
730
+
731
+ // Draw the title text
732
+ if (prop['chart.title'].length > 0) {
733
+
734
+ co.fillStyle = prop['chart.title.color'];
735
+
736
+ RG.Text2(this, {'font':prop['chart.title.font'] ? prop['chart.title.font'] : text_font,
737
+ 'size':title_size,
738
+ 'x':this.gutterLeft + ((ca.width - this.gutterLeft - this.gutterRight) / 2),
739
+ 'y':this.gutterTop - 5,
740
+ 'text':prop['chart.title'],
741
+ 'valign':'bottom',
742
+ 'halign':'center',
743
+ 'bold': prop['chart.title.bold'],
744
+ 'tag': 'title'
745
+ });
746
+ }
747
+
748
+ // Draw side title
749
+ if (typeof(prop['chart.title.side']) == 'string') {
750
+
751
+ co.fillStyle = prop['chart.title.side.color'];
752
+
753
+ RG.Text2(this, {'font':prop['chart.title.side.font'],
754
+ 'size':prop['chart.title.side.size'],
755
+ 'x':prop['chart.labels.position'] == 'right' ? this.gutterLeft - 10 : (ca.width - this.gutterRight) + 10,
756
+ 'y':this.gutterTop + (this.height / 2),
757
+ 'text': prop['chart.title.side'],
758
+ 'valign':'bottom',
759
+ 'halign':'center',
760
+ 'angle': prop['chart.labels.position'] == 'right' ? 270 : 90,
761
+ 'bold': prop['chart.title.side.bold'],
762
+ 'tag': 'title.side'
763
+ });
764
+ }
765
+ };
766
+
767
+
768
+
769
+
770
+ /**
771
+ * Returns the focused bar
772
+ *
773
+ * @param event e The event object
774
+ */
775
+ this.getShape =
776
+ this.getBar = function (e)
777
+ {
778
+ var mouseCoords = RG.getMouseXY(e)
779
+
780
+ for (var i=0,len=this.coords.length; i<len; i++) {
781
+
782
+ var mouseCoords = RG.getMouseXY(e);
783
+ var mouseX = mouseCoords[0];
784
+ var mouseY = mouseCoords[1];
785
+ var left = this.coords[i][0];
786
+ var top = this.coords[i][1];
787
+ var width = this.coords[i][2];
788
+ var height = this.coords[i][3];
789
+ var idx = i;
790
+
791
+ if (mouseX >= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) {
792
+
793
+ var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i);
794
+
795
+ return {0: this, 'object': this,
796
+ 1: left, 'x': left,
797
+ 2: top, 'y': top,
798
+ 3: width, 'width': width,
799
+ 4: height, 'height': height,
800
+ 5: i, 'index': i,
801
+ 'tooltip': tooltip };
802
+ }
803
+ }
804
+ };
805
+
806
+
807
+
808
+
809
+ /**
810
+ * This function returns the value that the mouse is positioned at, regardless of
811
+ * the actual indicated value.
812
+ *
813
+ * @param object e The event object
814
+ */
815
+ this.getValue = function (e)
816
+ {
817
+ var mouseCoords = RG.getMouseXY(e);
818
+ var mouseX = mouseCoords[0];
819
+ var mouseY = mouseCoords[1];
820
+
821
+ var value = (this.height - (mouseY - this.gutterTop)) / this.height;
822
+ value *= this.max - this.min;
823
+ value += this.min;
824
+
825
+ // Bounds checking
826
+ if (value > this.max) value = this.max;
827
+ if (value < this.min) value = this.min;
828
+
829
+ return value;
830
+ };
831
+
832
+
833
+
834
+
835
+ /**
836
+ * Each object type has its own Highlight() function which highlights the appropriate shape
837
+ *
838
+ * @param object shape The shape to highlight
839
+ */
840
+ this.highlight =
841
+ this.Highlight = function (shape)
842
+ {
843
+ // Add the new highlight
844
+ RG.Highlight.Rect(this, shape);
845
+ };
846
+
847
+
848
+
849
+
850
+ /**
851
+ * The getObjectByXY() worker method. Don't call this call:
852
+ *
853
+ * RGraph.ObjectRegistry.getObjectByXY(e)
854
+ *
855
+ * @param object e The event object
856
+ */
857
+ this.getObjectByXY = function (e)
858
+ {
859
+ var mouseXY = RG.getMouseXY(e);
860
+
861
+ if (
862
+ mouseXY[0] > this.gutterLeft
863
+ && mouseXY[0] < (ca.width - this.gutterRight)
864
+ && mouseXY[1] >= this.gutterTop
865
+ && mouseXY[1] <= (ca.height - this.gutterBottom)
866
+ ) {
867
+
868
+ return this;
869
+ }
870
+ };
871
+
872
+
873
+
874
+
875
+ /**
876
+ * This function allows the VProgress to be adjustable.
877
+ * UPDATE: Not any more
878
+ */
879
+ this.allowAdjusting =
880
+ this.AllowAdjusting = function () {return;};
881
+
882
+
883
+
884
+
885
+ /**
886
+ * This method handles the adjusting calculation for when the mouse is moved
887
+ *
888
+ * @param object e The event object
889
+ */
890
+ this.adjusting_mousemove =
891
+ this.Adjusting_mousemove = function (e)
892
+ {
893
+ /**
894
+ * Handle adjusting for the HProgress
895
+ */
896
+ if (prop['chart.adjustable'] && RG.Registry.Get('chart.adjusting') && RG.Registry.Get('chart.adjusting').uid == this.uid) {
897
+
898
+ var mouseXY = RG.getMouseXY(e);
899
+ var value = this.getValue(e);
900
+
901
+ if (typeof value === 'number') {
902
+
903
+ // Fire the onadjust event
904
+ RG.FireCustomEvent(this, 'onadjust');
905
+
906
+ this.value = Number(value.toFixed(prop['chart.scale.decimals']));
907
+ RG.RedrawCanvas(this.canvas);
908
+ }
909
+ }
910
+ };
911
+
912
+
913
+
914
+
915
+ /**
916
+ * Draws chart.labels.specific
917
+ */
918
+ this.drawSpecificLabels =
919
+ this.DrawSpecificLabels = function ()
920
+ {
921
+ var labels = prop['chart.labels.specific'];
922
+
923
+ if (labels) {
924
+
925
+ var font = prop['chart.text.font'];
926
+ var size = prop['chart.text.size'];
927
+ var halign = prop['chart.labels.position'] == 'right' ? 'left' : 'right';
928
+ var step = this.height / (labels.length - 1);
929
+
930
+ co.beginPath();
931
+
932
+ co.fillStyle = prop['chart.text.color'];
933
+
934
+ for (var i=0; i<labels.length; ++i) {
935
+
936
+ RG.Text2(this,{'font':font,
937
+ 'size':size,
938
+ 'x': prop['chart.labels.position'] == 'right' ? ca.width - this.gutterRight + 7 : this.gutterLeft - 7,
939
+ 'y':(this.height + this.gutterTop) - (step * i),
940
+ 'text':labels[i],
941
+ 'valign':'center',
942
+ 'halign':halign,
943
+ 'tag': 'labels.specific'
944
+ });
945
+ }
946
+ co.fill();
947
+ }
948
+ };
949
+
950
+
951
+
952
+
953
+ /**
954
+ * This function positions a tooltip when it is displayed
955
+ *
956
+ * @param obj object The chart object
957
+ * @param int x The X coordinate specified for the tooltip
958
+ * @param int y The Y coordinate specified for the tooltip
959
+ * @param objec tooltip The tooltips DIV element
960
+ */
961
+ this.positionTooltip = function (obj, x, y, tooltip, idx)
962
+ {
963
+ var coordX = obj.coords[tooltip.__index__][0];
964
+ var coordY = obj.coords[tooltip.__index__][1];
965
+ var coordW = obj.coords[tooltip.__index__][2];
966
+ var coordH = obj.coords[tooltip.__index__][3];
967
+ var canvasXY = RG.getCanvasXY(obj.canvas);
968
+ var gutterLeft = obj.gutterLeft;
969
+ var gutterTop = obj.gutterTop;
970
+ var width = tooltip.offsetWidth;
971
+ var height = tooltip.offsetHeight;
972
+
973
+ // Set the top position
974
+ tooltip.style.left = 0;
975
+ tooltip.style.top = canvasXY[1] + coordY - height - 7 + 'px';
976
+
977
+ // By default any overflow is hidden
978
+ tooltip.style.overflow = '';
979
+
980
+ // The arrow
981
+ var img = new Image();
982
+ img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAFCAYAAACjKgd3AAAARUlEQVQYV2NkQAN79+797+RkhC4M5+/bd47B2dmZEVkBCgcmgcsgbAaA9GA1BCSBbhAuA/AagmwQPgMIGgIzCD0M0AMMAEFVIAa6UQgcAAAAAElFTkSuQmCC';
983
+ img.style.position = 'absolute';
984
+ img.id = '__rgraph_tooltip_pointer__';
985
+ img.style.top = (tooltip.offsetHeight - 2) + 'px';
986
+ tooltip.appendChild(img);
987
+
988
+ // Reposition the tooltip if at the edges:
989
+
990
+ // LEFT edge
991
+ if ((canvasXY[0] + coordX + (coordW / 2) - (width / 2)) < 10) {
992
+ tooltip.style.left = (canvasXY[0] + coordX - (width * 0.1)) + (coordW / 2) + 'px';
993
+ img.style.left = ((width * 0.1) - 8.5) + 'px';
994
+
995
+ // RIGHT edge
996
+ } else if ((canvasXY[0] + coordX + (coordW / 2) + (width / 2)) > doc.body.offsetWidth) {
997
+ tooltip.style.left = canvasXY[0] + coordX - (width * 0.9) + (coordW / 2) + 'px';
998
+ img.style.left = ((width * 0.9) - 8.5) + 'px';
999
+
1000
+ // Default positioning - CENTERED
1001
+ } else {
1002
+ tooltip.style.left = (canvasXY[0] + coordX + (coordW / 2) - (width * 0.5)) + 'px';
1003
+ img.style.left = ((width * 0.5) - 8.5) + 'px';
1004
+ }
1005
+ };
1006
+
1007
+
1008
+
1009
+
1010
+ /**
1011
+ * This function returns the appropriate Y coordinate for the given Y value
1012
+ *
1013
+ * @param int value The Y value you want the coordinate for
1014
+ * @returm int The coordinate
1015
+ */
1016
+ this.getYCoord = function (value)
1017
+ {
1018
+ if (value > this.max || value < this.min) {
1019
+ return null;
1020
+ }
1021
+
1022
+ var barHeight = ca.height - prop['chart.gutter.top'] - prop['chart.gutter.bottom'];
1023
+ var coord = ((value - this.min) / (this.max - this.min)) * barHeight;
1024
+ coord = ca.height - coord - prop['chart.gutter.bottom'];
1025
+
1026
+ return coord;
1027
+ };
1028
+
1029
+
1030
+
1031
+
1032
+ /**
1033
+ * This returns true/false as to whether the cursor is over the chart area.
1034
+ * The cursor does not necessarily have to be over the bar itself.
1035
+ */
1036
+ this.overChartArea = function (e)
1037
+ {
1038
+ var mouseXY = RGraph.getMouseXY(e);
1039
+ var mouseX = mouseXY[0];
1040
+ var mouseY = mouseXY[1];
1041
+
1042
+ if ( mouseX >= this.gutterLeft
1043
+ && mouseX <= (ca.width - this.gutterRight)
1044
+ && mouseY >= this.gutterTop
1045
+ && mouseY <= (ca.height - this.gutterBottom)
1046
+ ) {
1047
+
1048
+ return true;
1049
+ }
1050
+
1051
+ return false;
1052
+ };
1053
+
1054
+
1055
+
1056
+
1057
+ /**
1058
+ *
1059
+ */
1060
+ this.parseColors = function ()
1061
+ {
1062
+ // Save the original colors so that they can be restored when the canvas is reset
1063
+ if (this.original_colors.length === 0) {
1064
+ this.original_colors['chart.colors'] = RG.array_clone(prop['chart.colors']);
1065
+ this.original_colors['chart.tickmarks.color'] = RG.array_clone(prop['chart.tickmarks.color']);
1066
+ this.original_colors['chart.strokestyle.inner'] = RG.array_clone(prop['chart.strokestyle.inner']);
1067
+ this.original_colors['chart.strokestyle.outer'] = RG.array_clone(prop['chart.strokestyle.outer']);
1068
+ this.original_colors['chart.highlight.fill'] = RG.array_clone(prop['chart.highlight.fill']);
1069
+ this.original_colors['chart.highlight.stroke'] = RG.array_clone(prop['chart.highlight.stroke']);
1070
+ this.original_colors['chart.highlight.color'] = RG.array_clone(prop['chart.highlight.color']);
1071
+ }
1072
+
1073
+ var colors = prop['chart.colors'];
1074
+
1075
+ for (var i=0,len=colors.length; i<len; ++i) {
1076
+ colors[i] = this.parseSingleColorForGradient(colors[i]);
1077
+ }
1078
+
1079
+ prop['chart.tickmarks.color'] = this.parseSingleColorForGradient(prop['chart.tickmarks.color']);
1080
+ prop['chart.strokestyle.inner'] = this.parseSingleColorForGradient(prop['chart.strokestyle.inner']);
1081
+ prop['chart.strokestyle.outer'] = this.parseSingleColorForGradient(prop['chart.strokestyle.outer']);
1082
+ prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
1083
+ prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
1084
+ prop['chart.background.color'] = this.parseSingleColorForGradient(prop['chart.background.color']);
1085
+ };
1086
+
1087
+
1088
+
1089
+
1090
+ /**
1091
+ * Use this function to reset the object to the post-constructor state. Eg reset colors if
1092
+ * need be etc
1093
+ */
1094
+ this.reset = function ()
1095
+ {
1096
+ };
1097
+
1098
+
1099
+
1100
+
1101
+ /**
1102
+ * This parses a single color value
1103
+ */
1104
+ this.parseSingleColorForGradient = function (color)
1105
+ {
1106
+ if (!color || typeof color != 'string') {
1107
+ return color;
1108
+ }
1109
+
1110
+ if (color.match(/^gradient\((.*)\)$/i)) {
1111
+ var parts = RegExp.$1.split(':');
1112
+
1113
+ // Create the gradient
1114
+ var grad = co.createLinearGradient(0, ca.height - prop['chart.gutter.bottom'], 0, prop['chart.gutter.top']);
1115
+
1116
+ var diff = 1 / (parts.length - 1);
1117
+
1118
+ grad.addColorStop(0, RG.trim(parts[0]));
1119
+
1120
+ for (var j=1,len=parts.length; j<len; ++j) {
1121
+ grad.addColorStop(j * diff, RG.trim(parts[j]));
1122
+ }
1123
+
1124
+ return grad ? grad : color;
1125
+ }
1126
+
1127
+ return grad ? grad : color;
1128
+ };
1129
+
1130
+
1131
+
1132
+
1133
+ /**
1134
+ * Draws the bevel effect
1135
+ */
1136
+ this.drawBevel =
1137
+ this.DrawBevel = function ()
1138
+ {
1139
+ // In case of multiple segments - this adds up all the lengths
1140
+ for (var i=0,len=0; i<this.coords.length; ++i) len += this.coords[i][3];
1141
+
1142
+ co.save();
1143
+ // Draw a path to clip to
1144
+ co.beginPath();
1145
+ co.rect(this.coords[0][0], this.coords[this.coords.length - 1][1] - 1, this.coords[0][2], len);
1146
+ co.clip();
1147
+
1148
+ // Now draw the rect with a shadow
1149
+ co.beginPath();
1150
+
1151
+ co.shadowColor = 'black';
1152
+ co.shadowOffsetX = 0;
1153
+ co.shadowOffsetY = 0;
1154
+ co.shadowBlur = 15;
1155
+
1156
+ co.lineWidth = 2;
1157
+ co.rect(this.coords[0][0] - 1, this.coords[this.coords.length - 1][1] - 1, this.coords[0][2] + 2, len + 2);
1158
+
1159
+ co.stroke();
1160
+
1161
+ co.restore();
1162
+ };
1163
+
1164
+
1165
+
1166
+
1167
+ /**
1168
+ * This function handles highlighting an entire data-series for the interactive
1169
+ * key
1170
+ *
1171
+ * @param int index The index of the data series to be highlighted
1172
+ */
1173
+ this.interactiveKeyHighlight = function (index)
1174
+ {
1175
+ var coords = this.coords[index];
1176
+
1177
+ co.beginPath();
1178
+
1179
+ co.strokeStyle = prop['chart.key.interactive.highlight.chart.stroke'];
1180
+ co.lineWidth = 2;
1181
+ co.fillStyle = prop['chart.key.interactive.highlight.chart.fill'];
1182
+
1183
+ co.rect(coords[0], coords[1], coords[2], coords[3]);
1184
+ co.fill();
1185
+ co.stroke();
1186
+
1187
+ // Reset the linewidth
1188
+ co.lineWidth = 1;
1189
+ };
1190
+
1191
+
1192
+
1193
+
1194
+ /**
1195
+ * Using a function to add events makes it easier to facilitate method chaining
1196
+ *
1197
+ * @param string type The type of even to add
1198
+ * @param function func
1199
+ */
1200
+ this.on = function (type, func)
1201
+ {
1202
+ if (type.substr(0,2) !== 'on') {
1203
+ type = 'on' + type;
1204
+ }
1205
+
1206
+ this[type] = func;
1207
+
1208
+ return this;
1209
+ };
1210
+
1211
+
1212
+
1213
+
1214
+ /**
1215
+ * This function runs once only
1216
+ * (put at the end of the file (before any effects))
1217
+ */
1218
+ this.firstDrawFunc = function ()
1219
+ {
1220
+ };
1221
+
1222
+
1223
+
1224
+
1225
+ /**
1226
+ * HProgress Grow effect (which is also the VPogress Grow effect)
1227
+ *
1228
+ * @param object obj The chart object
1229
+ */
1230
+ this.grow = function ()
1231
+ {
1232
+ var obj = this;
1233
+ var canvas = obj.canvas;
1234
+ var context = obj.context;
1235
+ var initial_value = obj.currentValue;
1236
+ var opt = arguments[0] || {};
1237
+ var numFrames = opt.frames || 30;
1238
+ var frame = 0
1239
+ var callback = arguments[1] || function () {};
1240
+
1241
+ if (typeof obj.value === 'object') {
1242
+
1243
+ if (RGraph.is_null(obj.currentValue)) {
1244
+ obj.currentValue = [];
1245
+ for (var i=0; i<obj.value.length; ++i) {
1246
+ obj.currentValue[i] = 0;
1247
+ }
1248
+ }
1249
+
1250
+ var diff = [];
1251
+ var increment = [];
1252
+
1253
+ for (var i=0; i<obj.value.length; ++i) {
1254
+ diff[i] = obj.value[i] - Number(obj.currentValue[i]);
1255
+ increment[i] = diff[i] / numFrames;
1256
+ }
1257
+
1258
+ if (initial_value == null) {
1259
+ initial_value = [];
1260
+ for (var i=0; i< obj.value.length; ++i) {
1261
+ initial_value[i] = 0;
1262
+ }
1263
+ }
1264
+
1265
+ } else {
1266
+
1267
+ var diff = obj.value - Number(obj.currentValue);
1268
+ var increment = diff / numFrames;
1269
+ }
1270
+
1271
+
1272
+
1273
+
1274
+
1275
+
1276
+ function iterator ()
1277
+ {
1278
+ frame++;
1279
+
1280
+ if (frame <= numFrames) {
1281
+
1282
+ if (typeof obj.value == 'object') {
1283
+ obj.value = [];
1284
+ for (var i=0; i<initial_value.length; ++i) {
1285
+ obj.value[i] = initial_value[i] + (increment[i] * frame);
1286
+ }
1287
+ } else {
1288
+ obj.value = initial_value + (increment * frame);
1289
+ }
1290
+
1291
+ RGraph.clear(obj.canvas);
1292
+ RGraph.redrawCanvas(obj.canvas);
1293
+
1294
+ RGraph.Effects.updateCanvas(iterator);
1295
+ } else {
1296
+ callback();
1297
+ }
1298
+ }
1299
+
1300
+ iterator();
1301
+
1302
+ return this;
1303
+ };
1304
+
1305
+
1306
+
1307
+ RG.att(ca);
1308
+
1309
+
1310
+
1311
+ /**
1312
+ * The chart is now always registered
1313
+ */
1314
+ RG.Register(this);
1315
+
1316
+
1317
+
1318
+
1319
+ /**
1320
+ * This is the 'end' of the constructor so if the first argument
1321
+ * contains configuration data - handle that.
1322
+ */
1323
+ if (parseConfObjectForOptions) {
1324
+ RG.parseObjectStyleConfig(this, conf.options);
1325
+ }
1326
+ };