rgraph-rails 4.62 → 4.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +3 -4
  3. data/lib/rgraph-rails/version.rb +1 -1
  4. data/vendor/assets/javascripts/RGraph.bar.js +240 -3742
  5. data/vendor/assets/javascripts/RGraph.bipolar.js +165 -2005
  6. data/vendor/assets/javascripts/RGraph.common.annotate.js +35 -395
  7. data/vendor/assets/javascripts/RGraph.common.context.js +30 -595
  8. data/vendor/assets/javascripts/RGraph.common.core.js +418 -5359
  9. data/vendor/assets/javascripts/RGraph.common.csv.js +20 -276
  10. data/vendor/assets/javascripts/RGraph.common.deprecated.js +35 -450
  11. data/vendor/assets/javascripts/RGraph.common.dynamic.js +88 -1395
  12. data/vendor/assets/javascripts/RGraph.common.effects.js +90 -1545
  13. data/vendor/assets/javascripts/RGraph.common.key.js +52 -753
  14. data/vendor/assets/javascripts/RGraph.common.resizing.js +37 -563
  15. data/vendor/assets/javascripts/RGraph.common.sheets.js +29 -352
  16. data/vendor/assets/javascripts/RGraph.common.tooltips.js +32 -450
  17. data/vendor/assets/javascripts/RGraph.common.zoom.js +14 -219
  18. data/vendor/assets/javascripts/RGraph.cornergauge.js +71 -0
  19. data/vendor/assets/javascripts/RGraph.drawing.background.js +34 -570
  20. data/vendor/assets/javascripts/RGraph.drawing.circle.js +33 -544
  21. data/vendor/assets/javascripts/RGraph.drawing.image.js +51 -755
  22. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +37 -645
  23. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +36 -633
  24. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +35 -514
  25. data/vendor/assets/javascripts/RGraph.drawing.poly.js +37 -559
  26. data/vendor/assets/javascripts/RGraph.drawing.rect.js +33 -548
  27. data/vendor/assets/javascripts/RGraph.drawing.text.js +36 -664
  28. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +50 -812
  29. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +51 -856
  30. data/vendor/assets/javascripts/RGraph.fuel.js +58 -964
  31. data/vendor/assets/javascripts/RGraph.funnel.js +55 -984
  32. data/vendor/assets/javascripts/RGraph.gantt.js +77 -1354
  33. data/vendor/assets/javascripts/RGraph.gauge.js +85 -1421
  34. data/vendor/assets/javascripts/RGraph.hbar.js +162 -2788
  35. data/vendor/assets/javascripts/RGraph.hprogress.js +80 -1401
  36. data/vendor/assets/javascripts/RGraph.line.js +249 -4248
  37. data/vendor/assets/javascripts/RGraph.meter.js +74 -1280
  38. data/vendor/assets/javascripts/RGraph.modaldialog.js +19 -301
  39. data/vendor/assets/javascripts/RGraph.odo.js +71 -1264
  40. data/vendor/assets/javascripts/RGraph.pie.js +137 -2288
  41. data/vendor/assets/javascripts/RGraph.radar.js +110 -1847
  42. data/vendor/assets/javascripts/RGraph.rose.js +108 -1977
  43. data/vendor/assets/javascripts/RGraph.rscatter.js +80 -1432
  44. data/vendor/assets/javascripts/RGraph.scatter.js +172 -3163
  45. data/vendor/assets/javascripts/RGraph.semicircularprogress.js +60 -1120
  46. data/vendor/assets/javascripts/RGraph.svg.bar.js +66 -1735
  47. data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +21 -246
  48. data/vendor/assets/javascripts/RGraph.svg.common.core.js +255 -3937
  49. data/vendor/assets/javascripts/RGraph.svg.common.csv.js +20 -276
  50. data/vendor/assets/javascripts/RGraph.svg.common.fx.js +68 -1303
  51. data/vendor/assets/javascripts/RGraph.svg.common.key.js +19 -205
  52. data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +29 -352
  53. data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +22 -273
  54. data/vendor/assets/javascripts/RGraph.svg.funnel.js +32 -0
  55. data/vendor/assets/javascripts/RGraph.svg.hbar.js +59 -1400
  56. data/vendor/assets/javascripts/RGraph.svg.line.js +70 -1580
  57. data/vendor/assets/javascripts/RGraph.svg.pie.js +55 -1131
  58. data/vendor/assets/javascripts/RGraph.svg.radar.js +57 -1502
  59. data/vendor/assets/javascripts/RGraph.svg.rose.js +66 -1817
  60. data/vendor/assets/javascripts/RGraph.svg.scatter.js +58 -1261
  61. data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +28 -865
  62. data/vendor/assets/javascripts/RGraph.svg.waterfall.js +45 -1252
  63. data/vendor/assets/javascripts/RGraph.thermometer.js +63 -1136
  64. data/vendor/assets/javascripts/RGraph.vprogress.js +83 -1470
  65. data/vendor/assets/javascripts/RGraph.waterfall.js +83 -1347
  66. metadata +5 -4
  67. data/vendor/assets/javascripts/financial-data.js +0 -1067
@@ -1,1348 +1,84 @@
1
- // version: 2017-05-08
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 licensed under the Open Source MIT license. That means that it's |
9
- * | totally free to use! |
10
- * o--------------------------------------------------------------------------------o
11
- */
12
1
 
13
- RGraph = window.RGraph || {isRGraph: true};
14
-
15
-
16
-
17
-
18
- /**
19
- * The bar chart constructor
20
- *
21
- * @param object canvas The canvas object
22
- * @param array data The chart data
23
- */
24
- RGraph.Waterfall = function (conf)
25
- {
26
- /**
27
- * Allow for object config style
28
- */
29
- if ( typeof conf === 'object'
30
- && typeof conf.data === 'object'
31
- && typeof conf.id === 'string') {
32
-
33
- var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
34
-
35
- } else {
36
-
37
- var conf = {
38
- id: conf,
39
- data: arguments[1]
40
- };
41
- }
42
-
43
-
44
-
45
-
46
- this.id = conf.id;
47
- this.canvas = document.getElementById(this.id);
48
- this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null;
49
- this.canvas.__object__ = this;
50
- this.type = 'waterfall';
51
- this.max = 0;
52
- this.data = conf.data;
53
- this.isRGraph = true;
54
- this.coords = [];
55
- this.uid = RGraph.CreateUID();
56
- this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
57
- this.colorsParsed = false;
58
- this.coordsText = [];
59
- this.original_colors = [];
60
- this.firstDraw = true; // After the first draw this will be false
61
-
62
-
63
- // Various config
64
- this.properties =
65
- {
66
- 'chart.background.barcolor1': 'rgba(0,0,0,0)',
67
- 'chart.background.barcolor2': 'rgba(0,0,0,0)',
68
- 'chart.background.grid': true,
69
- 'chart.background.grid.color': '#ddd',
70
- 'chart.background.grid.width': 1,
71
- 'chart.background.grid.hsize': 20,
72
- 'chart.background.grid.vsize': 20,
73
- 'chart.background.grid.vlines': true,
74
- 'chart.background.grid.hlines': true,
75
- 'chart.background.grid.border': true,
76
- 'chart.background.grid.autofit':true,
77
- 'chart.background.grid.autofit.align': true,
78
- 'chart.background.grid.autofit.numhlines': 5,
79
- 'chart.background.grid.autofit.numvlines': 20,
80
- 'chart.background.image': null,
81
- 'chart.background.hbars': null,
82
- 'chart.linewidth': 1,
83
- 'chart.axis.linewidth': 1,
84
- 'chart.xaxispos': 'bottom',
85
- 'chart.numxticks': null,
86
- 'chart.numyticks': 10,
87
- 'chart.hmargin': 5,
88
- 'chart.strokestyle': '#666',
89
- 'chart.axis.color': 'black',
90
- 'chart.gutter.left': 25,
91
- 'chart.gutter.right': 25,
92
- 'chart.gutter.top': 25,
93
- 'chart.gutter.bottom': 25,
94
- 'chart.labels': [],
95
- 'chart.labels.bold': false,
96
- 'chart.labels.offsetx': 0,
97
- 'chart.labels.offsety': 0,
98
- 'chart.ylabels.offsetx': 0,
99
- 'chart.ylabels.offsety': 0,
100
- 'chart.ylabels': true,
101
- 'chart.text.color': 'black',
102
- 'chart.text.size': 12,
103
- 'chart.text.angle': 0,
104
- 'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
105
- 'chart.text.accessible': true,
106
- 'chart.text.accessible.overflow': 'visible',
107
- 'chart.text.accessible.pointerevents': true,
108
- 'chart.ymax': null,
109
- 'chart.title': '',
110
- 'chart.title.color': 'black',
111
- 'chart.title.background': null,
112
- 'chart.title.hpos': null,
113
- 'chart.title.vpos': null,
114
- 'chart.title.bold': true,
115
- 'chart.title.font': null,
116
- 'chart.title.xaxis': '',
117
- 'chart.title.yaxis': '',
118
- 'chart.title.yaxis.bold': true,
119
- 'chart.title.yaxis.size': null,
120
- 'chart.title.yaxis.font': null,
121
- 'chart.title.yaxis.color': null,
122
- 'chart.title.xaxis.pos': null,
123
- 'chart.title.yaxis.pos': null,
124
- 'chart.title.yaxis.align': 'left',
125
- 'chart.title.xaxis.bold': true,
126
- 'chart.title.xaxis.size': null,
127
- 'chart.title.xaxis.font': null,
128
- 'chart.title.xaxis.color': null,
129
- 'chart.title.yaxis.x': null,
130
- 'chart.title.yaxis.y': null,
131
- 'chart.title.xaxis.x': null,
132
- 'chart.title.xaxis.y': null,
133
- 'chart.title.x': null,
134
- 'chart.title.y': null,
135
- 'chart.title.halign': null,
136
- 'chart.title.valign': null,
137
- 'chart.colors': ['green','red','blue'],
138
- 'chart.shadow': false,
139
- 'chart.shadow.color': '#666',
140
- 'chart.shadow.offsetx': 3,
141
- 'chart.shadow.offsety': 3,
142
- 'chart.shadow.blur': 3,
143
- 'chart.tooltips': null,
144
- 'chart.tooltips.effect': 'fade',
145
- 'chart.tooltips.css.class': 'RGraph_tooltip',
146
- 'chart.tooltips.event': 'onclick',
147
- 'chart.tooltips.highlight': true,
148
- 'chart.tooltips.override': null,
149
- 'chart.highlight.stroke': 'rgba(0,0,0,0)',
150
- 'chart.highlight.fill': 'rgba(255,255,255,0.7)',
151
- 'chart.contextmenu': null,
152
- 'chart.units.pre': '',
153
- 'chart.units.post': '',
154
- 'chart.scale.decimals': 0,
155
- 'chart.scale.point': '.',
156
- 'chart.scale.thousand': ',',
157
- 'chart.scale.zerostart': true,
158
- //'chart.scale.formatter': null,
159
- 'chart.crosshairs': false,
160
- 'chart.crosshairs.color': '#333',
161
- 'chart.crosshairs.hline': true,
162
- 'chart.crosshairs.vline': true,
163
- 'chart.annotatable': false,
164
- 'chart.annotate.color': 'black',
165
- 'chart.zoom.factor': 1.5,
166
- 'chart.zoom.fade.in': true,
167
- 'chart.zoom.fade.out': true,
168
- 'chart.zoom.hdir': 'right',
169
- 'chart.zoom.vdir': 'down',
170
- 'chart.zoom.frames': 25,
171
- 'chart.zoom.delay': 16.666,
172
- 'chart.zoom.shadow': true,
173
- 'chart.zoom.background': true,
174
- 'chart.resizable': false,
175
- 'chart.resize.handle.background': null,
176
- 'chart.noaxes': false,
177
- 'chart.noxaxis': false,
178
- 'chart.noyaxis': false,
179
- 'chart.axis.color': 'black',
180
- 'chart.total': true,
181
- 'chart.multiplier.x': 1,
182
- 'chart.multiplier.w': 1,
183
- 'chart.events.click': null,
184
- 'chart.events.mousemove': null,
185
- 'chart.ylabels.count': 5,
186
- 'chart.ymin': 0,
187
- 'chart.clearto': 'rgba(0,0,0,0)'
188
- }
189
-
190
- // Check for support
191
- if (!this.canvas) {
192
- alert('[WATERFALL] No canvas support');
193
- return;
194
- }
195
-
196
- /**
197
- * Create the $ objects
198
- *
199
- * 2/5/016: Now also use this loop to go through the dat conerting
200
- * strings to floats
201
- */
202
- for (var i=0,len=this.data.length; i<=len; ++i) {
203
-
204
- // Create the object for adding event listeners
205
- this['$' + i] = {}
206
-
207
- // Ensure that the data point is numeric
208
- if (typeof this.data[i] === 'string') {
209
- this.data[i] = parseFloat(this.data[i]);
210
- }
211
- }
212
-
213
-
214
- /**
215
- * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
216
- * done already
217
- */
218
- if (!this.canvas.__rgraph_aa_translated__) {
219
- this.context.translate(0.5,0.5);
220
-
221
- this.canvas.__rgraph_aa_translated__ = true;
222
- }
223
-
224
-
225
-
226
-
227
- // Short variable names
228
- var RG = RGraph,
229
- ca = this.canvas,
230
- co = ca.getContext('2d'),
231
- prop = this.properties,
232
- pa2 = RG.path2,
233
- win = window,
234
- doc = document,
235
- ma = Math
236
-
237
-
238
-
239
- /**
240
- * "Decorate" the object with the generic effects if the effects library has been included
241
- */
242
- if (RG.Effects && typeof RG.Effects.decorate === 'function') {
243
- RG.Effects.decorate(this);
244
- }
245
-
246
-
247
-
248
-
249
- /**
250
- * A setter
251
- *
252
- * @param name string The name of the property to set
253
- * @param value mixed The value of the property
254
- */
255
- this.set =
256
- this.Set = function (name, value)
257
- {
258
- var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
259
-
260
- /**
261
- * the number of arguments is only one and it's an
262
- * object - parse it for configuration data and return.
263
- */
264
- if (arguments.length === 1 && typeof name === 'object') {
265
- RG.parseObjectStyleConfig(this, name);
266
- return this;
267
- }
268
-
269
-
270
-
271
-
272
- /**
273
- * This should be done first - prepend the propertyy name with "chart." if necessary
274
- */
275
- if (name.substr(0,6) != 'chart.') {
276
- name = 'chart.' + name;
277
- }
278
-
279
-
280
-
281
- // Convert uppercase letters to dot+lower case letter
282
- while(name.match(/([A-Z])/)) {
283
- name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
284
- }
285
-
286
-
287
-
288
- if (name == 'chart.total' && prop['chart.numxticks'] == null) {
289
- prop['chart.numxticks'] = this.data.length;
290
- }
291
-
292
-
293
-
294
- prop[name.toLowerCase()] = value;
295
-
296
- return this;
297
- };
298
-
299
-
300
-
301
-
302
- /**
303
- * A getter
304
- *
305
- * @param name string The name of the property to get
306
- */
307
- this.get =
308
- this.Get = function (name)
309
- {
310
- /**
311
- * This should be done first - prepend the property name with "chart." if necessary
312
- */
313
- if (name.substr(0,6) != 'chart.') {
314
- name = 'chart.' + name;
315
- }
316
-
317
- // Convert uppercase letters to dot+lower case letter
318
- while(name.match(/([A-Z])/)) {
319
- name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
320
- }
321
-
322
- return prop[name.toLowerCase()];
323
- };
324
-
325
-
326
-
327
-
328
- /**
329
- * The function you call to draw the bar chart
330
- */
331
- this.draw =
332
- this.Draw = function ()
333
- {
334
- /**
335
- * Fire the onbeforedraw event
336
- */
337
- RGraph.fireCustomEvent(this, 'onbeforedraw');
338
-
339
-
340
- /**
341
- * Parse the colors. This allows for simple gradient syntax
342
- */
343
- if (!this.colorsParsed) {
344
- this.parseColors();
345
-
346
- // Don't want to do this again
347
- this.colorsParsed = true;
348
- }
349
-
350
-
351
- /**
352
- * Draw the background image
353
- */
354
- RGraph.DrawBackgroundImage(this);
355
-
356
- /**
357
- * This is new in May 2011 and facilitates indiviual gutter settings,
358
- * eg chart.gutter.left
359
- */
360
- this.gutterLeft = prop['chart.gutter.left'];
361
- this.gutterRight = prop['chart.gutter.right'];
362
- this.gutterTop = prop['chart.gutter.top'];
363
- this.gutterBottom = prop['chart.gutter.bottom'];
364
-
365
- /**
366
- * Stop the coords array from growing uncontrollably
367
- */
368
- this.coords = [];
369
-
370
-
371
-
372
- /**
373
- * Stop this growing uncontrollably
374
- */
375
- this.coordsText = [];
376
-
377
-
378
-
379
-
380
- /**
381
- * This gets used a lot
382
- */
383
- this.centery = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
384
-
385
- /**
386
- * Work out a few things. They need to be here because they depend on things you can change after you instantiate the object
387
- */
388
- this.max = 0;
389
- this.grapharea = ca.height - this.gutterTop - this.gutterBottom;
390
- this.graphwidth = ca.width - this.gutterLeft - this.gutterRight;
391
- this.halfTextHeight = prop['chart.text.size'] / 2;
392
-
393
-
394
- /**
395
- * Work out the maximum value
396
- */
397
- this.max = this.getMax(this.data);
398
-
399
- var decimals = prop['chart.scale.decimals'];
400
-
401
- this.scale2 = RG.getScale2(this, {
402
- max:typeof(prop['chart.ymax']) == 'number' ? prop['chart.ymax'] : this.max,
403
- min:prop['chart.ymin'],
404
- strict: typeof(prop['chart.ymax']) === 'number' ? true : false,
405
- 'scale.decimals':Number(decimals),
406
- 'scale.point':prop['chart.scale.point'],
407
- 'scale.thousand':prop['chart.scale.thousand'],
408
- 'scale.round':prop['chart.scale.round'],
409
- 'units.pre':prop['chart.units.pre'],
410
- 'units.post':prop['chart.units.post'],
411
- 'ylabels.count':prop['chart.ylabels.count']
412
- });
413
-
414
- this.max = this.scale2.max;
415
- this.min = this.scale2.min;
416
-
417
- // Draw the background hbars
418
- RG.drawBars(this)
419
-
420
- // Progressively Draw the chart
421
- RG.Background.draw(this);
422
-
423
- this.DrawAxes();
424
- this.Drawbars();
425
- this.DrawLabels();
426
-
427
- /**
428
- * If the X axis is at the bottom AND ymin is 0 - draw the it
429
- * again so that it appears "on top" of the bars
430
- */
431
- if ( prop['chart.xaxispos'] === 'bottom'
432
- && prop['chart.noaxes'] === false
433
- && prop['chart.noxaxis'] === false
434
- && prop['chart.ymin'] === 0) {
435
-
436
- co.strokeStyle = prop['chart.axis.color'];
437
- co.strokeRect(
438
- prop['chart.gutter.left'],
439
- ca.height - prop['chart.gutter.bottom'],
440
- ca.width - this.gutterLeft - this.gutterRight,
441
- 0
442
- );
443
- }
444
-
445
- /**
446
- * Setup the context menu if required
447
- */
448
- if (prop['chart.contextmenu']) {
449
- RG.ShowContext(this);
450
- }
451
-
452
-
453
- /**
454
- * This function enables resizing
455
- */
456
- if (prop['chart.resizable']) {
457
- RG.AllowResizing(this);
458
- }
459
-
460
-
461
- /**
462
- * This installs the event listeners
463
- */
464
- RG.InstallEventListeners(this);
465
-
466
-
467
-
468
- /**
469
- * Fire the onfirstdraw event
470
- */
471
- if (this.firstDraw) {
472
- RG.fireCustomEvent(this, 'onfirstdraw');
473
- this.firstDraw = false;
474
- this.firstDrawFunc();
475
- }
476
-
477
-
478
-
479
-
480
- /**
481
- * Fire the RGraph ondraw event
482
- */
483
- RG.FireCustomEvent(this, 'ondraw');
484
-
485
- return this;
486
- };
487
-
488
-
489
-
490
-
491
- /**
492
- * Draws the charts axes
493
- */
494
- this.drawAxes =
495
- this.DrawAxes = function ()
496
- {
497
- if (prop['chart.noaxes']) {
498
- return;
499
- }
500
-
501
- co.beginPath();
502
- co.strokeStyle = prop['chart.axis.color'];
503
- co.lineWidth = prop['chart.axis.linewidth'] + 0.001;
504
-
505
- // Draw the Y axis
506
- if (prop['chart.noyaxis'] == false) {
507
- co.moveTo(ma.round(this.gutterLeft), this.gutterTop);
508
- co.lineTo(ma.round(this.gutterLeft), ca.height - this.gutterBottom);
509
- }
510
-
511
- // Draw the X axis
512
- if (prop['chart.noxaxis'] == false) {
513
- // Center X axis
514
- if (prop['chart.xaxispos'] == 'center') {
515
- co.moveTo(this.gutterLeft, ma.round( ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop));
516
- co.lineTo(ca.width - this.gutterRight, ma.round( ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop));
517
- } else {
518
-
519
- var y = ma.floor(this.getYCoord(0));
520
-
521
- co.moveTo(this.gutterLeft, y);
522
- co.lineTo(ca.width - this.gutterRight, y);
523
- }
524
- }
525
-
526
- var numYTicks = prop['chart.numyticks'];
527
-
528
- // Draw the Y tickmarks
529
- if ( prop['chart.noyaxis'] === false
530
- && prop['chart.numyticks'] > 0
531
- ) {
532
-
533
- var yTickGap = (ca.height - this.gutterTop - this.gutterBottom) / numYTicks;
534
-
535
- for (y=this.gutterTop; y < (ca.height - this.gutterBottom); y += yTickGap) {
536
- if (prop['chart.xaxispos'] == 'bottom' || (y != ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop)) {
537
- co.moveTo(this.gutterLeft, ma.round( y));
538
- co.lineTo(this.gutterLeft - 3, ma.round( y));
539
- }
540
- }
541
-
542
- /**
543
- * If the X axis is not being shown, draw an extra tick
544
- */
545
- if ( prop['chart.noxaxis']
546
- || prop['chart.xaxispos'] == 'center'
547
- || prop['chart.ymin'] !== 0
548
- ) {
549
- co.moveTo(this.gutterLeft - 3, Math.round(ca.height - this.gutterBottom));
550
- co.lineTo(this.gutterLeft, Math.round(ca.height - this.gutterBottom));
551
- }
552
- }
553
-
554
-
555
- // Draw the X tickmarks
556
- if (prop['chart.numxticks'] == null) {
557
- prop['chart.numxticks'] = this.data.length + (prop['chart.total'] ? 1 : 0)
558
- }
559
-
560
- if (prop['chart.noxaxis'] == false && prop['chart.numxticks'] > 0) {
561
-
562
- xTickGap = (ca.width - this.gutterLeft - this.gutterRight ) / prop['chart.numxticks'];
563
-
564
- if (prop['chart.xaxispos'] == 'center') {
565
- yStart = ((ca.height - this.gutterBottom - this.gutterTop) / 2) + this.gutterTop - 3;
566
- yEnd = ((ca.height - this.gutterBottom - this.gutterTop) / 2) + this.gutterTop + 3;
567
- } else {
568
- yStart = this.getYCoord(0) - (this.scale2.min < 0 ? 3 : 0);
569
- yEnd = this.getYCoord(0) + 3;
570
- }
571
-
572
- for (x=this.gutterLeft + xTickGap; x<=ca.width - this.gutterRight + 1; x+=xTickGap) {
573
- co.moveTo(ma.round(x), yStart);
574
- co.lineTo(ma.round(x), yEnd);
575
- }
576
-
577
- if (prop['chart.noyaxis']) {
578
- co.moveTo(ma.round( this.gutterLeft), yStart);
579
- co.lineTo(ma.round( this.gutterLeft), yEnd);
580
- }
581
- }
582
-
583
- /**
584
- * If the Y axis is not being shown, draw an extra tick
585
- */
586
- if (prop['chart.noyaxis'] && prop['chart.noxaxis'] == false) {
587
- co.moveTo(ma.round(this.gutterLeft), this.getYCoord(0));
588
- co.lineTo(ma.round(this.gutterLeft), this.getYCoord(0));
589
- }
590
-
591
- co.stroke();
592
- };
593
-
594
-
595
-
596
-
597
- /**
598
- * Draws the labels for the graph
599
- */
600
- this.drawLabels =
601
- this.DrawLabels = function ()
602
- {
603
- var context = co,
604
- numYLabels = 5, // TODO Make this configurable
605
- interval = this.grapharea / numYLabels,
606
- font = prop['chart.text.font'],
607
- size = prop['chart.text.size'],
608
- color = prop['chart.text.color'],
609
- units_pre = prop['chart.units.pre'],
610
- units_post = prop['chart.units.post'],
611
- offsetx = prop['chart.ylabels.offsetx'],
612
- offsety = prop['chart.ylabels.offsety'];
613
-
614
- co.beginPath();
615
- co.fillStyle = color;
616
-
617
- /**
618
- * First, draw the Y labels
619
- */
620
- if (prop['chart.ylabels']) {
621
- if (prop['chart.xaxispos'] == 'center') {
622
-
623
- var halfInterval = interval / 2;
624
- var halfWay = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
625
-
626
- for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
627
- RG.text2(this, {
628
- font:font,
629
- size:size,
630
- x:this.gutterLeft - 5 + offsetx,
631
- y: this.gutterTop + (((this.grapharea/2) / len) * i) + offsety,
632
- text:this.scale2.labels[len - i - 1],
633
- valign:'center',
634
- halign:'right',
635
- tag: 'scale'
636
- });
637
-
638
- RG.text2(this, {
639
- font:font,
640
- size:size,
641
- x:this.gutterLeft - 5 + offsetx,
642
- y: halfWay + (((this.grapharea/2) / len) * (i + 1)) + offsety,
643
- text:this.scale2.labels[i],
644
- valign:'center',
645
- halign:'right',
646
- tag: 'scale'
647
- });
648
- }
649
-
650
- // Draw zero if required
651
- if (prop['chart.scale.zerostart']) {
652
- RG.text2(co, {
653
- x: this.gutterLeft - 5 + offsetx,
654
- y: halfWay,
655
- text: '0',
656
- font: font,
657
- size: size,
658
- valign: 'center',
659
- halign: 'right',
660
- tag: 'scale'
661
- });
662
- }
663
-
664
- } else {
665
-
666
- for (var i=0,len=this.scale2.values.length; i<len; ++i) {
667
-
668
- var y = this.getYCoord(this.scale2.values[i]) + offsety;
669
-
670
- RG.text2(this, {
671
- font:font,
672
- size:size,
673
- x:this.gutterLeft - 5 + offsetx,
674
- y: y,
675
- text:this.scale2.labels[i],
676
- valign:'center',
677
- halign:'right',
678
- tag: 'scale'
679
- });
680
- }
681
-
682
-
683
- // Draw zero if required
684
- if (prop['chart.scale.zerostart'] || prop['chart.ymin'] !== 0) {
685
-
686
- RG.text2(co, {
687
- x: this.gutterLeft - 5 + offsetx,
688
- y: this.getYCoord(prop['chart.ymin'] || 0),
689
- text: RG.numberFormat(this, String(Number(prop['chart.ymin'] || 0).toFixed(prop['chart.ymin'] === 0 ? 0 : prop['chart.scale.decimals'])), prop['chart.units.pre'], prop['chart.units.post']),
690
- font: font,
691
- size: size,
692
- valign: 'center',
693
- halign: 'right',
694
- tag: 'scale'
695
- });
696
- }
697
- }
698
- }
699
-
700
-
701
-
702
- /**
703
- * Now, draw the X labels
704
- */
705
- if (prop['chart.labels'].length > 0) {
706
-
707
- // Recalculate the interval for the X labels
708
- interval = (ca.width - this.gutterLeft - this.gutterRight) / prop['chart.labels'].length;
709
-
710
- var halign = 'center';
711
- var angle = prop['chart.text.angle'];
712
-
713
- if (angle) {
714
- halign = 'right';
715
- angle *= -1;
716
- }
717
-
718
- var labels = prop['chart.labels'],
719
- labelsColor = prop['chart.labels.color'],
720
- bold = prop['chart.labels.bold'],
721
- offsetx = prop['chart.labels.offsetx'],
722
- offsety = prop['chart.labels.offsety']
723
-
724
- for (var i=0,len=labels.length; i<len; i+=1) {
725
- RG.text2(this, {
726
- 'color': labelsColor,
727
- 'font':font,
728
- 'size':size,
729
- 'bold': bold,
730
- 'x':this.gutterLeft + (i * interval) + (interval / 2) + offsetx,
731
- 'y':ca.height - this.gutterBottom + 5 + this.halfTextHeight + offsety,
732
- 'text':labels[i],
733
- 'valign':'center',
734
- 'halign':halign,
735
- 'angle':angle,
736
- 'tag': 'labels'
737
- });
738
- }
739
- }
740
-
741
- co.stroke();
742
- co.fill();
743
- };
744
-
745
-
746
-
747
-
748
- /**
749
- * Draws the bars on to the chart
750
- */
751
- this.drawbars =
752
- this.Drawbars = function ()
753
- {
754
- var context = co,
755
- canvas = ca,
756
- hmargin = prop['chart.hmargin'],
757
- runningTotal = 0;
758
-
759
- co.lineWidth = prop['chart.linewidth'] + 0.001;
760
-
761
- for (var i=0,len=this.data.length; i<len; ++i) {
762
-
763
- co.beginPath();
764
-
765
- co.strokeStyle = prop['chart.strokestyle'];
766
-
767
- var x = ma.round( this.gutterLeft + hmargin + (((this.graphwidth / (this.data.length + (prop['chart.total'] ? 1 : 0))) * i) * prop['chart.multiplier.x']));
768
-
769
- // Must be before the y coord calculation
770
- var h = this.getYCoord(0) - this.getYCoord(ma.abs(this.data[i]));
771
-
772
-
773
-
774
- // Work out the Y coordinate
775
- if (i === 0) {
776
- y = this.getYCoord(0) - h;
777
- } else {
778
- y = this.getYCoord(runningTotal) - h;
779
- }
780
- y = ma.round(y);
781
-
782
-
783
-
784
-
785
-
786
- var w = ((ca.width - this.gutterLeft - this.gutterRight) / (this.data.length + (prop['chart.total'] ? 1 : 0 )) ) - (2 * prop['chart.hmargin']);
787
- w = w * prop['chart.multiplier.w'];
788
-
789
-
790
- // Adjust the coords for negative values
791
- if (this.data[i] < 0) {
792
- y += h;
793
- }
794
-
795
- // Color
796
- co.fillStyle = this.data[i] >= 0 ? prop['chart.colors'][0] : prop['chart.colors'][1];
797
-
798
-
799
- if (prop['chart.shadow']) {
800
- RG.setShadow(this, prop['chart.shadow.color'], prop['chart.shadow.offsetx'], prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
801
- } else {
802
- RG.noShadow(this);
803
- }
804
-
805
- co.rect(x, ma.floor(y), w, ma.floor(h));
806
-
807
- this.coords.push([x, y, w, h]);
808
-
809
-
810
-
811
- runningTotal += this.data[i];
812
-
813
- co.stroke();
814
- co.fill();
815
- }
816
-
817
- // Store the total
818
- this.total = runningTotal;
819
-
820
- if (prop['chart.total']) {
821
-
822
- // This is the height of the final bar
823
- h = this.getYCoord(0) - this.getYCoord(ma.abs(runningTotal));
824
-
825
- /**
826
- * Set the Y (ie the start point) value
827
- */
828
- if (prop['chart.xaxispos'] == 'center') {
829
- y = runningTotal > 0 ? this.getYCoord(0) - h : this.getYCoord(0);
830
- } else {
831
- if (runningTotal > 0) {
832
- y = this.getYCoord(0) - h;
833
- } else {
834
- y = this.getYCoord(0);
835
- }
836
- }
837
-
838
- // This is the X position of the final bar
839
- x = x + (prop['chart.hmargin'] * 2) + w;
840
-
841
-
842
- // Final color
843
- co.fillStyle = prop['chart.colors'][2];
844
-
845
- pa2(co, 'b r % % % % s % f %',
846
- x, y, w, h,
847
- co.strokeStyle,
848
- co.fillStyle
849
- );
850
-
851
- // This is set so that the next iteration of the loop will be able to
852
- // access THIS iterations coordinates
853
- var previousCoords = [x, y, w, ma.abs(h)];
854
-
855
- // Add the coordinates to the coords array (the previousCooords array, at
856
- // this point, is actually THIS iterations coords
857
- this.coords.push(previousCoords);
858
- }
859
-
860
-
861
-
862
-
863
-
864
- // Turn off the shadow
865
- RG.noShadow(this);
866
-
867
-
868
-
869
-
870
-
871
-
872
- /**
873
- * This draws the connecting lines
874
- */
875
- co.lineWidth = 1;
876
- co.strokeStyle = '#666';
877
-
878
- co.beginPath();
879
-
880
- for (var i=1,len=this.coords.length; i<len; i+=1) {
881
-
882
- var prev = this.coords[i - 1],
883
- curr = this.coords[i],
884
- prevData = this.data[i-1]
885
-
886
- // CANNOT be a part of the var chain above
887
- var y = (prevData > 0 ? prev[1] : prev[1] + prev[3]);
888
-
889
-
890
- co.moveTo(prev[0] + prev[2], y);
891
- co.lineTo(curr[0],(prevData > 0 ? prev[1] : prev[1] + prev[3]));
892
-
893
- }
894
-
895
- co.stroke();
896
- };
897
-
898
-
899
-
900
-
901
- /**
902
- * Not used by the class during creating the graph, but is used by event handlers
903
- * to get the coordinates (if any) of the selected bar
904
- *
905
- * @param object e The event object
906
- */
907
- this.getShape =
908
- this.getBar = function (e)
909
- {
910
- /**
911
- * Loop through the bars determining if the mouse is over a bar
912
- */
913
- for (var i=0,len=this.coords.length; i<len; i++) {
914
-
915
- var mouseXY = RG.getMouseXY(e),
916
- mouseX = mouseXY[0],
917
- mouseY = mouseXY[1];
918
-
919
- var left = this.coords[i][0],
920
- top = this.coords[i][1],
921
- width = this.coords[i][2],
922
- height = this.coords[i][3];
923
-
924
- if ( mouseX >= left
925
- && mouseX <= (left + width)
926
- && mouseY >= top
927
- && mouseY <= top + height) {
928
-
929
- var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i);
930
-
931
- return {
932
- 0: this, object: this,
933
- 1: left, x: left,
934
- 2: top, y: top,
935
- 3: width, width: width,
936
- 4: height, height: height,
937
- 5: i, index: i,
938
- tooltip: tooltip
939
- };
940
- }
941
- }
942
-
943
- return null;
944
- };
945
-
946
-
947
-
948
-
949
- /**
950
- * The Waterfall is slightly different to Bar/Line charts so has this function to get the max value
951
- */
952
- this.getMax = function (data)
953
- {
954
- var runningTotal = 0, max = 0;
955
-
956
- for (var i=0,len=data.length; i<len; i+=1) {
957
- runningTotal += data[i];
958
-
959
- max = ma.max(ma.abs(runningTotal), max);
960
- }
961
-
962
- return ma.abs(max);
963
- };
964
-
965
-
966
-
967
-
968
- /**
969
- * This function facilitates the installation of tooltip event listeners if
970
- * tooltips are defined.
971
- */
972
- this.allowTooltips =
973
- this.AllowTooltips = function ()
974
- {
975
- // Preload any tooltip images that are used in the tooltips
976
- RG.PreLoadTooltipImages(this);
977
-
978
-
979
- /**
980
- * This installs the window mousedown event listener that lears any
981
- * highlight that may be visible.
982
- */
983
- RG.InstallWindowMousedownTooltipListener(this);
984
-
985
-
986
- /**
987
- * This installs the canvas mousemove event listener. This function
988
- * controls the pointer shape.
989
- */
990
- RG.InstallCanvasMousemoveTooltipListener(this);
991
-
992
-
993
- /**
994
- * This installs the canvas mouseup event listener. This is the
995
- * function that actually shows the appropriate tooltip (if any).
996
- */
997
- RG.InstallCanvasMouseupTooltipListener(this);
998
- };
999
-
1000
-
1001
-
1002
-
1003
- /**
1004
- * Each object type has its own Highlight() function which highlights the appropriate shape
1005
- *
1006
- * @param object shape The shape to highlight
1007
- */
1008
- this.highlight =
1009
- this.Highlight = function (shape)
1010
- {
1011
- if (typeof prop['chart.highlight.style'] === 'function') {
1012
- (prop['chart.highlight.style'])(shape);
1013
- } else {
1014
- RG.Highlight.Rect(this, shape);
1015
- }
1016
- };
1017
-
1018
-
1019
-
1020
-
1021
- /**
1022
- * The getObjectByXY() worker method. Don't call this call:
1023
- *
1024
- * RGraph.ObjectRegistry.getObjectByXY(e)
1025
- *
1026
- * @param object e The event object
1027
- */
1028
- this.getObjectByXY = function (e)
1029
- {
1030
- var mouseXY = RG.getMouseXY(e);
1031
-
1032
- if (
1033
- mouseXY[0] > this.gutterLeft
1034
- && mouseXY[0] < (ca.width - this.gutterRight)
1035
- && mouseXY[1] > this.gutterTop
1036
- && mouseXY[1] < (ca.height - this.gutterBottom)
1037
- ) {
1038
-
1039
- return this;
1040
- }
1041
- };
1042
-
1043
-
1044
-
1045
-
1046
- /**
1047
- * This function positions a tooltip when it is displayed
1048
- *
1049
- * @param obj object The chart object
1050
- * @param int x The X coordinate specified for the tooltip
1051
- * @param int y The Y coordinate specified for the tooltip
1052
- * @param objec tooltip The tooltips DIV element
1053
- *
1054
- this.positionTooltip = function (obj, x, y, tooltip, idx)
1055
- {
1056
- var coordX = obj.coords[tooltip.__index__][0];
1057
- var coordY = obj.coords[tooltip.__index__][1];
1058
- var coordW = obj.coords[tooltip.__index__][2];
1059
- var coordH = obj.coords[tooltip.__index__][3];
1060
- var canvasXY = RG.getCanvasXY(obj.canvas);
1061
- var mouseXY = RG.getMouseXY(window.event);
1062
- var gutterLeft = obj.gutterLeft;
1063
- var gutterTop = obj.gutterTop;
1064
- var width = tooltip.offsetWidth;
1065
- var height = tooltip.offsetHeight;
1066
- var value = obj.data[idx];
1067
-
1068
- // Change the value to be the total if necessary
1069
- if (tooltip.__index__ == obj.data.length) {
1070
- value = obj.total;
1071
- }
1072
-
1073
- // Set the top position
1074
- tooltip.style.left = 0;
1075
- tooltip.style.top = window.event.pageY - height - 5 + 'px';
1076
-
1077
-
1078
- // By default any overflow is hidden
1079
- tooltip.style.overflow = '';
1080
-
1081
-
1082
- // Reposition the tooltip if at the edges:
1083
-
1084
- // LEFT edge
1085
- if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
1086
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
1087
-
1088
- // RIGHT edge
1089
- } else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
1090
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
1091
-
1092
- // Default positioning - CENTERED
1093
- } else {
1094
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
1095
- }
1096
- };*/
1097
-
1098
-
1099
-
1100
-
1101
- /**
1102
- * This method returns the appropriate Y coord for the given value
1103
- *
1104
- * @param number value The value
1105
- */
1106
- this.getYCoord = function (value)
1107
- {
1108
- if (prop['chart.xaxispos'] == 'center') {
1109
-
1110
- if (value < (-1 * this.max)) {
1111
- return null;
1112
- }
1113
-
1114
- var coord = (value / this.max) * (this.grapharea / 2);
1115
- return this.gutterTop + (this.grapharea / 2) - coord;
1116
-
1117
- } else {
1118
-
1119
- var coord = ( (value - this.scale2.min) / (this.max - this.scale2.min) ) * this.grapharea;
1120
- coord = coord + this.gutterBottom;
1121
-
1122
- return ca.height - coord;
1123
- }
1124
- };
1125
-
1126
-
1127
-
1128
-
1129
- /**
1130
- * This allows for easy specification of gradients
1131
- */
1132
- this.parseColors = function ()
1133
- {
1134
- // Save the original colors so that they can be restored when the canvas is reset
1135
- if (this.original_colors.length === 0) {
1136
- this.original_colors['chart.colors'] = RG.array_clone(prop['chart.colors']);
1137
- this.original_colors['chart.key.colors'] = RG.array_clone(prop['chart.key.colors']);
1138
- this.original_colors['chart.crosshairs.color'] = RG.array_clone(prop['chart.crosshairs.color']);
1139
- this.original_colors['chart.highlight.stroke'] = RG.array_clone(prop['chart.highlight.stroke']);
1140
- this.original_colors['chart.highlight.fill'] = RG.array_clone(prop['chart.highlight.fill']);
1141
- this.original_colors['chart.background.barcolor1'] = RG.array_clone(prop['chart.background.barcolor1']);
1142
- this.original_colors['chart.background.barcolor2'] = RG.array_clone(prop['chart.background.barcolor2']);
1143
- this.original_colors['chart.background.grid.color'] = RG.array_clone(prop['chart.background.grid.color']);
1144
- this.original_colors['chart.strokestyle'] = RG.array_clone(prop['chart.strokestyle']);
1145
- this.original_colors['chart.axis.color'] = RG.array_clone(prop['chart.axis.color']);
1146
- }
1147
-
1148
-
1149
-
1150
-
1151
-
1152
-
1153
-
1154
-
1155
- // chart.colors
1156
- var colors = prop['chart.colors'];
1157
-
1158
- if (colors) {
1159
- for (var i=0,len=colors.length; i<len; ++i) {
1160
- colors[i] = this.parseSingleColorForGradient(colors[i]);
1161
- }
1162
- }
1163
-
1164
- // chart.key.colors
1165
- var colors = prop['chart.key.colors'];
1166
-
1167
- if (colors) {
1168
- for (var i=0,len=colors.length; i<len; ++i) {
1169
- colors[i] = this.parseSingleColorForGradient(colors[i]);
1170
- }
1171
- }
1172
-
1173
- prop['chart.crosshairs.color'] = this.parseSingleColorForGradient(prop['chart.crosshairs.color']);
1174
- prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
1175
- prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
1176
- prop['chart.background.barcolor1'] = this.parseSingleColorForGradient(prop['chart.background.barcolor1']);
1177
- prop['chart.background.barcolor2'] = this.parseSingleColorForGradient(prop['chart.background.barcolor2']);
1178
- prop['chart.background.grid.color'] = this.parseSingleColorForGradient(prop['chart.background.grid.color']);
1179
- prop['chart.strokestyle'] = this.parseSingleColorForGradient(prop['chart.strokestyle']);
1180
- prop['chart.axis.color'] = this.parseSingleColorForGradient(prop['chart.axis.color']);
1181
- };
1182
-
1183
-
1184
-
1185
-
1186
- /**
1187
- * Use this function to reset the object to the post-constructor state. Eg reset colors if
1188
- * need be etc
1189
- */
1190
- this.reset = function ()
1191
- {
1192
- };
1193
-
1194
-
1195
-
1196
-
1197
- /**
1198
- * This parses a single color value
1199
- *
1200
- * @param string color The color to parse for gradients
1201
- */
1202
- this.parseSingleColorForGradient = function (color)
1203
- {
1204
- if (!color || typeof color != 'string') {
1205
- return color;
1206
- }
1207
-
1208
- if (typeof color === 'string' && color.match(/^gradient\((.*)\)$/i)) {
1209
-
1210
- var parts = RegExp.$1.split(':');
1211
-
1212
- // Create the gradient
1213
-
1214
- var grad = co.createLinearGradient(0,ca.height - prop['chart.gutter.bottom'], 0, prop['chart.gutter.top']);
1215
-
1216
- var diff = 1 / (parts.length - 1);
1217
-
1218
- grad.addColorStop(0, RG.trim(parts[0]));
1219
-
1220
- for (var j=1,len=parts.length; j<len; ++j) {
1221
- grad.addColorStop(j * diff, RG.trim(parts[j]));
1222
- }
1223
- }
1224
-
1225
- return grad ? grad : color;
1226
- };
1227
-
1228
-
1229
-
1230
-
1231
- /**
1232
- * Using a function to add events makes it easier to facilitate method chaining
1233
- *
1234
- * @param string type The type of even to add
1235
- * @param function func
1236
- */
1237
- this.on = function (type, func)
1238
- {
1239
- if (type.substr(0,2) !== 'on') {
1240
- type = 'on' + type;
1241
- }
1242
-
1243
- if (typeof this[type] !== 'function') {
1244
- this[type] = func;
1245
- } else {
1246
- RG.addCustomEventListener(this, type, func);
1247
- }
1248
-
1249
- return this;
1250
- };
1251
-
1252
-
1253
-
1254
-
1255
- /**
1256
- * This function runs once only
1257
- * (put at the end of the file (before any effects))
1258
- */
1259
- this.firstDrawFunc = function ()
1260
- {
1261
- };
1262
-
1263
-
1264
-
1265
-
1266
- /**
1267
- * Waterfall Grow
1268
- *
1269
- * @param object Options. You can pass frames here - which should be a number
1270
- * @param function An optional function which is called when the animation is finished
1271
- */
1272
- this.grow = function ()
1273
- {
1274
- var opt = arguments[0] || {};
1275
- var callback = arguments[1] || function () {};
1276
- var frames = opt.frames || 30;
1277
- var numFrame = 0;
1278
- var obj = this;
1279
- var data = RG.array_clone(obj.data);
1280
-
1281
- //Reset The data to zeros
1282
- for (var i=0,len=obj.data.length; i<len; ++i) {
1283
- obj.data[i] /= frames;
1284
- }
1285
-
1286
- /**
1287
- * Fix the scale
1288
- */
1289
- if (obj.Get('chart.ymax') == null) {
1290
- var max = obj.getMax(data);
1291
- var scale2 = RG.getScale2(obj, {'max':max});
1292
- obj.Set('chart.ymax', scale2.max);
1293
- }
1294
-
1295
- //obj.Set('chart.multiplier.x', 0);
1296
- //obj.Set('chart.multiplier.w', 0);
1297
-
1298
- function iterator ()
1299
- {
1300
- for (var i=0; i<obj.data.length; ++i) {
1301
-
1302
- // This produces a very slight easing effect
1303
- obj.data[i] = data[i] * RG.Effects.getEasingMultiplier(frames, numFrame);
1304
- }
1305
-
1306
- RGraph.clear(obj.canvas);
1307
- RGraph.redrawCanvas(obj.canvas);
1308
-
1309
- if (++numFrame < frames) {
1310
- RGraph.Effects.updateCanvas(iterator);
1311
- } else {
1312
- callback(obj);
1313
- }
1314
- }
1315
-
1316
- iterator();
1317
-
1318
- return this;
1319
- };
1320
-
1321
-
1322
-
1323
-
1324
-
1325
- RG.att(ca);
1326
-
1327
-
1328
- /**
1329
- * Now, because canvases can support multiple charts, canvases must always be registered
1330
- */
1331
- RG.Register(this);
1332
-
1333
-
1334
-
1335
-
1336
- /**
1337
- * This is the 'end' of the constructor so if the first argument
1338
- * contains configuration data - handle that.
1339
- */
1340
- if (parseConfObjectForOptions) {
1341
- RG.parseObjectStyleConfig(this, conf.options);
1342
- }
1343
-
1344
-
1345
-
1346
-
1347
- return this;
1348
- };
2
+ RGraph=window.RGraph||{isRGraph:true};RGraph.Waterfall=function(conf)
3
+ {if(typeof conf==='object'&&typeof conf.data==='object'&&typeof conf.id==='string'){var parseConfObjectForOptions=true;}else{var conf={id:conf,data:arguments[1]};}
4
+ this.id=conf.id;this.canvas=document.getElementById(this.id);this.context=this.canvas.getContext?this.canvas.getContext("2d"):null;this.canvas.__object__=this;this.type='waterfall';this.max=0;this.data=conf.data;this.isRGraph=true;this.coords=[];this.uid=RGraph.CreateUID();this.canvas.uid=this.canvas.uid?this.canvas.uid:RGraph.CreateUID();this.colorsParsed=false;this.coordsText=[];this.original_colors=[];this.firstDraw=true;this.properties={'chart.background.barcolor1':'rgba(0,0,0,0)','chart.background.barcolor2':'rgba(0,0,0,0)','chart.background.grid':true,'chart.background.grid.color':'#ddd','chart.background.grid.width':1,'chart.background.grid.hsize':20,'chart.background.grid.vsize':20,'chart.background.grid.vlines':true,'chart.background.grid.hlines':true,'chart.background.grid.border':true,'chart.background.grid.autofit':true,'chart.background.grid.autofit.align':true,'chart.background.grid.autofit.numhlines':5,'chart.background.grid.autofit.numvlines':20,'chart.background.image':null,'chart.background.hbars':null,'chart.linewidth':1,'chart.axis.linewidth':1,'chart.xaxispos':'bottom','chart.numxticks':null,'chart.numyticks':10,'chart.hmargin':5,'chart.strokestyle':'#666','chart.axis.color':'black','chart.gutter.left':25,'chart.gutter.right':25,'chart.gutter.top':25,'chart.gutter.bottom':25,'chart.labels':[],'chart.labels.bold':false,'chart.labels.offsetx':0,'chart.labels.offsety':0,'chart.ylabels.offsetx':0,'chart.ylabels.offsety':0,'chart.ylabels':true,'chart.text.color':'black','chart.text.size':12,'chart.text.angle':0,'chart.text.font':'Segoe UI, Arial, Verdana, sans-serif','chart.text.accessible':true,'chart.text.accessible.overflow':'visible','chart.text.accessible.pointerevents':true,'chart.ymax':null,'chart.title':'','chart.title.color':'black','chart.title.background':null,'chart.title.hpos':null,'chart.title.vpos':null,'chart.title.bold':true,'chart.title.font':null,'chart.title.xaxis':'','chart.title.yaxis':'','chart.title.yaxis.bold':true,'chart.title.yaxis.size':null,'chart.title.yaxis.font':null,'chart.title.yaxis.color':null,'chart.title.xaxis.pos':null,'chart.title.yaxis.pos':null,'chart.title.yaxis.align':'left','chart.title.xaxis.bold':true,'chart.title.xaxis.size':null,'chart.title.xaxis.font':null,'chart.title.xaxis.color':null,'chart.title.yaxis.x':null,'chart.title.yaxis.y':null,'chart.title.xaxis.x':null,'chart.title.xaxis.y':null,'chart.title.x':null,'chart.title.y':null,'chart.title.halign':null,'chart.title.valign':null,'chart.colors':['green','red','blue'],'chart.colors.sequential':false,'chart.shadow':false,'chart.shadow.color':'#666','chart.shadow.offsetx':3,'chart.shadow.offsety':3,'chart.shadow.blur':3,'chart.tooltips':null,'chart.tooltips.effect':'fade','chart.tooltips.css.class':'RGraph_tooltip','chart.tooltips.event':'onclick','chart.tooltips.highlight':true,'chart.tooltips.override':null,'chart.highlight.stroke':'rgba(0,0,0,0)','chart.highlight.fill':'rgba(255,255,255,0.7)','chart.contextmenu':null,'chart.units.pre':'','chart.units.post':'','chart.scale.decimals':0,'chart.scale.point':'.','chart.scale.thousand':',','chart.scale.zerostart':true,'chart.crosshairs':false,'chart.crosshairs.color':'#333','chart.crosshairs.hline':true,'chart.crosshairs.vline':true,'chart.annotatable':false,'chart.annotate.color':'black','chart.zoom.factor':1.5,'chart.zoom.fade.in':true,'chart.zoom.fade.out':true,'chart.zoom.hdir':'right','chart.zoom.vdir':'down','chart.zoom.frames':25,'chart.zoom.delay':16.666,'chart.zoom.shadow':true,'chart.zoom.background':true,'chart.resizable':false,'chart.resize.handle.background':null,'chart.noaxes':false,'chart.noxaxis':false,'chart.noyaxis':false,'chart.axis.color':'black','chart.total':true,'chart.multiplier.x':1,'chart.multiplier.w':1,'chart.events.click':null,'chart.events.mousemove':null,'chart.ylabels.count':5,'chart.ymin':0,'chart.clearto':'rgba(0,0,0,0)','chart.key':null,'chart.key.background':'white','chart.key.position':'graph','chart.key.halign':'right','chart.key.shadow':false,'chart.key.shadow.color':'#666','chart.key.shadow.blur':3,'chart.key.shadow.offsetx':2,'chart.key.shadow.offsety':2,'chart.key.position.gutter.boxed':false,'chart.key.position.x':null,'chart.key.position.y':null,'chart.key.color.shape':'square','chart.key.rounded':true,'chart.key.linewidth':1,'chart.key.colors':null,'chart.key.interactive':false,'chart.key.interactive.highlight.chart.stroke':'#000','chart.key.interactive.highlight.chart.fill':'rgba(255,255,255,0.7)','chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)','chart.key.text.color':'black',}
5
+ if(!this.canvas){alert('[WATERFALL] No canvas support');return;}
6
+ for(var i=0,len=this.data.length;i<=len;++i){this['$'+i]={}
7
+ if(typeof this.data[i]==='string'){this.data[i]=parseFloat(this.data[i]);}}
8
+ if(!this.canvas.__rgraph_aa_translated__){this.context.translate(0.5,0.5);this.canvas.__rgraph_aa_translated__=true;}
9
+ var RG=RGraph,ca=this.canvas,co=ca.getContext('2d'),prop=this.properties,pa2=RG.path2,win=window,doc=document,ma=Math
10
+ if(RG.Effects&&typeof RG.Effects.decorate==='function'){RG.Effects.decorate(this);}
11
+ this.set=this.Set=function(name,value)
12
+ {var value=typeof arguments[1]==='undefined'?null:arguments[1];if(arguments.length===1&&typeof name==='object'){RG.parseObjectStyleConfig(this,name);return this;}
13
+ if(name.substr(0,6)!='chart.'){name='chart.'+name;}
14
+ while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
15
+ if(name=='chart.total'&&prop['chart.numxticks']==null){prop['chart.numxticks']=this.data.length;}
16
+ prop[name.toLowerCase()]=value;return this;};this.get=this.Get=function(name)
17
+ {if(name.substr(0,6)!='chart.'){name='chart.'+name;}
18
+ while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
19
+ return prop[name.toLowerCase()];};this.draw=this.Draw=function()
20
+ {RGraph.fireCustomEvent(this,'onbeforedraw');if(!this.colorsParsed){this.parseColors();this.colorsParsed=true;}
21
+ RGraph.DrawBackgroundImage(this);this.gutterLeft=prop['chart.gutter.left'];this.gutterRight=prop['chart.gutter.right'];this.gutterTop=prop['chart.gutter.top'];this.gutterBottom=prop['chart.gutter.bottom'];this.coords=[];this.coordsText=[];this.centery=((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop;this.max=0;this.grapharea=ca.height-this.gutterTop-this.gutterBottom;this.graphwidth=ca.width-this.gutterLeft-this.gutterRight;this.halfTextHeight=prop['chart.text.size']/2;this.max=this.getMax(this.data);var decimals=prop['chart.scale.decimals'];this.scale2=RG.getScale2(this,{max:typeof(prop['chart.ymax'])=='number'?prop['chart.ymax']:this.max,min:prop['chart.ymin'],strict:typeof(prop['chart.ymax'])==='number'?true:false,'scale.decimals':Number(decimals),'scale.point':prop['chart.scale.point'],'scale.thousand':prop['chart.scale.thousand'],'scale.round':prop['chart.scale.round'],'units.pre':prop['chart.units.pre'],'units.post':prop['chart.units.post'],'ylabels.count':prop['chart.ylabels.count']});this.max=this.scale2.max;this.min=this.scale2.min;RG.drawBars(this)
22
+ RG.Background.draw(this);this.DrawAxes();this.Drawbars();this.DrawLabels();if(prop['chart.xaxispos']==='bottom'&&prop['chart.noaxes']===false&&prop['chart.noxaxis']===false&&prop['chart.ymin']===0){co.strokeStyle=prop['chart.axis.color'];co.strokeRect(prop['chart.gutter.left'],ca.height-prop['chart.gutter.bottom'],ca.width-this.gutterLeft-this.gutterRight,0);}
23
+ if(prop['chart.contextmenu']){RG.ShowContext(this);}
24
+ if(prop['chart.resizable']){RG.AllowResizing(this);}
25
+ RG.InstallEventListeners(this);if(prop['chart.key']&&prop['chart.key'].length){RG.DrawKey(this,prop['chart.key'],prop['chart.colors']);}
26
+ if(this.firstDraw){this.firstDraw=false;RG.fireCustomEvent(this,'onfirstdraw');this.firstDrawFunc();}
27
+ RG.FireCustomEvent(this,'ondraw');return this;};this.drawAxes=this.DrawAxes=function()
28
+ {if(prop['chart.noaxes']){return;}
29
+ co.beginPath();co.strokeStyle=prop['chart.axis.color'];co.lineWidth=prop['chart.axis.linewidth']+0.001;if(prop['chart.noyaxis']==false){co.moveTo(ma.round(this.gutterLeft),this.gutterTop);co.lineTo(ma.round(this.gutterLeft),ca.height-this.gutterBottom);}
30
+ if(prop['chart.noxaxis']==false){if(prop['chart.xaxispos']=='center'){co.moveTo(this.gutterLeft,ma.round(((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop));co.lineTo(ca.width-this.gutterRight,ma.round(((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop));}else{var y=ma.floor(this.getYCoord(0));co.moveTo(this.gutterLeft,y);co.lineTo(ca.width-this.gutterRight,y);}}
31
+ var numYTicks=prop['chart.numyticks'];if(prop['chart.noyaxis']===false&&prop['chart.numyticks']>0){var yTickGap=(ca.height-this.gutterTop-this.gutterBottom)/numYTicks;for(y=this.gutterTop;y<(ca.height-this.gutterBottom);y+=yTickGap){if(prop['chart.xaxispos']=='bottom'||(y!=((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop)){co.moveTo(this.gutterLeft,ma.round(y));co.lineTo(this.gutterLeft-3,ma.round(y));}}
32
+ if(prop['chart.noxaxis']||prop['chart.xaxispos']=='center'||prop['chart.ymin']!==0){co.moveTo(this.gutterLeft-3,Math.round(ca.height-this.gutterBottom));co.lineTo(this.gutterLeft,Math.round(ca.height-this.gutterBottom));}}
33
+ if(prop['chart.numxticks']==null){prop['chart.numxticks']=this.data.length+(prop['chart.total']?1:0)}
34
+ if(prop['chart.noxaxis']==false&&prop['chart.numxticks']>0){xTickGap=(ca.width-this.gutterLeft-this.gutterRight)/prop['chart.numxticks'];if(prop['chart.xaxispos']=='center'){yStart=((ca.height-this.gutterBottom-this.gutterTop)/2)+this.gutterTop-3;yEnd=((ca.height-this.gutterBottom-this.gutterTop)/2)+this.gutterTop+3;}else{yStart=this.getYCoord(0)-(this.scale2.min<0?3:0);yEnd=this.getYCoord(0)+3;}
35
+ for(x=this.gutterLeft+xTickGap;x<=ca.width-this.gutterRight+1;x+=xTickGap){co.moveTo(ma.round(x),yStart);co.lineTo(ma.round(x),yEnd);}
36
+ if(prop['chart.noyaxis']){co.moveTo(ma.round(this.gutterLeft),yStart);co.lineTo(ma.round(this.gutterLeft),yEnd);}}
37
+ if(prop['chart.noyaxis']&&prop['chart.noxaxis']==false){co.moveTo(ma.round(this.gutterLeft),this.getYCoord(0));co.lineTo(ma.round(this.gutterLeft),this.getYCoord(0));}
38
+ co.stroke();};this.drawLabels=this.DrawLabels=function()
39
+ {var context=co,numYLabels=5,interval=this.grapharea/numYLabels,font=prop['chart.text.font'],size=prop['chart.text.size'],color=prop['chart.text.color'],units_pre=prop['chart.units.pre'],units_post=prop['chart.units.post'],offsetx=prop['chart.ylabels.offsetx'],offsety=prop['chart.ylabels.offsety'];co.beginPath();co.fillStyle=color;if(prop['chart.ylabels']){if(prop['chart.xaxispos']=='center'){var halfInterval=interval/2;var halfWay=((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop;for(var i=0,len=this.scale2.labels.length;i<len;++i){RG.text2(this,{font:font,size:size,x:this.gutterLeft-5+offsetx,y:this.gutterTop+(((this.grapharea/2)/len)*i)+offsety,text:this.scale2.labels[len-i-1],valign:'center',halign:'right',tag:'scale'});RG.text2(this,{font:font,size:size,x:this.gutterLeft-5+offsetx,y:halfWay+(((this.grapharea/2)/len)*(i+1))+offsety,text:this.scale2.labels[i],valign:'center',halign:'right',tag:'scale'});}
40
+ if(prop['chart.scale.zerostart']){RG.text2(co,{x:this.gutterLeft-5+offsetx,y:halfWay,text:'0',font:font,size:size,valign:'center',halign:'right',tag:'scale'});}}else{for(var i=0,len=this.scale2.values.length;i<len;++i){var y=this.getYCoord(this.scale2.values[i])+offsety;RG.text2(this,{font:font,size:size,x:this.gutterLeft-5+offsetx,y:y,text:this.scale2.labels[i],valign:'center',halign:'right',tag:'scale'});}
41
+ if(prop['chart.scale.zerostart']||prop['chart.ymin']!==0){RG.text2(co,{x:this.gutterLeft-5+offsetx,y:this.getYCoord(prop['chart.ymin']||0),text:RG.numberFormat(this,String(Number(prop['chart.ymin']||0).toFixed(prop['chart.ymin']===0?0:prop['chart.scale.decimals'])),prop['chart.units.pre'],prop['chart.units.post']),font:font,size:size,valign:'center',halign:'right',tag:'scale'});}}}
42
+ if(prop['chart.labels'].length>0){interval=(ca.width-this.gutterLeft-this.gutterRight)/prop['chart.labels'].length;var halign='center';var angle=prop['chart.text.angle'];if(angle){halign='right';angle*=-1;}
43
+ var labels=prop['chart.labels'],labelsColor=prop['chart.labels.color'],bold=prop['chart.labels.bold'],offsetx=prop['chart.labels.offsetx'],offsety=prop['chart.labels.offsety']
44
+ for(var i=0,len=labels.length;i<len;i+=1){RG.text2(this,{'color':labelsColor,'font':font,'size':size,'bold':bold,'x':this.gutterLeft+(i*interval)+(interval/2)+offsetx,'y':ca.height-this.gutterBottom+5+this.halfTextHeight+offsety,'text':labels[i],'valign':'center','halign':halign,'angle':angle,'tag':'labels'});}}
45
+ co.stroke();co.fill();};this.drawbars=this.Drawbars=function()
46
+ {var context=co,canvas=ca,hmargin=prop['chart.hmargin'],runningTotal=0;co.lineWidth=prop['chart.linewidth']+0.001;for(var i=0,len=this.data.length,seq=0;i<len;++i,++seq){co.beginPath();co.strokeStyle=prop['chart.strokestyle'];var x=ma.round(this.gutterLeft+hmargin+(((this.graphwidth/(this.data.length+(prop['chart.total']?1:0)))*i)*prop['chart.multiplier.x']));var h=this.getYCoord(0)-this.getYCoord(ma.abs(this.data[i]));if(i===0){y=this.getYCoord(0)-h;}else{y=this.getYCoord(runningTotal)-h;}
47
+ y=ma.round(y);var w=((ca.width-this.gutterLeft-this.gutterRight)/(this.data.length+(prop['chart.total']?1:0)))-(2*prop['chart.hmargin']);w=w*prop['chart.multiplier.w'];if(this.data[i]<0){y+=h;}
48
+ co.fillStyle=this.data[i]>=0?prop['chart.colors'][0]:prop['chart.colors'][1];if(prop['chart.colors.sequential']){co.fillStyle=prop['chart.colors'][seq];}
49
+ if(prop['chart.shadow']){RG.setShadow(this,prop['chart.shadow.color'],prop['chart.shadow.offsetx'],prop['chart.shadow.offsety'],prop['chart.shadow.blur']);}else{RG.noShadow(this);}
50
+ co.rect(x,ma.floor(y),w,ma.floor(h));this.coords.push([x,y,w,h]);runningTotal+=this.data[i];co.stroke();co.fill();}
51
+ this.total=runningTotal;if(prop['chart.total']){h=this.getYCoord(0)-this.getYCoord(ma.abs(runningTotal));if(prop['chart.xaxispos']=='center'){y=runningTotal>0?this.getYCoord(0)-h:this.getYCoord(0);}else{if(runningTotal>0){y=this.getYCoord(0)-h;}else{y=this.getYCoord(0);}}
52
+ x=x+(prop['chart.hmargin']*2)+w;co.fillStyle=prop['chart.colors'][2];if(prop['chart.colors.sequential']){co.fillStyle=prop['chart.colors'][seq]}
53
+ pa2(co,'b r % % % % s % f %',x,y,w,h,co.strokeStyle,co.fillStyle);var previousCoords=[x,y,w,ma.abs(h)];this.coords.push(previousCoords);}
54
+ RG.noShadow(this);co.lineWidth=1;co.strokeStyle='#666';co.beginPath();for(var i=1,len=this.coords.length;i<len;i+=1){var prev=this.coords[i-1],curr=this.coords[i],prevData=this.data[i-1]
55
+ var y=(prevData>0?prev[1]:prev[1]+prev[3]);co.moveTo(prev[0]+prev[2],y);co.lineTo(curr[0],(prevData>0?prev[1]:prev[1]+prev[3]));}
56
+ co.stroke();};this.getShape=this.getBar=function(e)
57
+ {for(var i=0,len=this.coords.length;i<len;i++){var mouseXY=RG.getMouseXY(e),mouseX=mouseXY[0],mouseY=mouseXY[1];var left=this.coords[i][0],top=this.coords[i][1],width=this.coords[i][2],height=this.coords[i][3];if(mouseX>=left&&mouseX<=(left+width)&&mouseY>=top&&mouseY<=top+height){var tooltip=RG.parseTooltipText(prop['chart.tooltips'],i);return{0:this,object:this,1:left,x:left,2:top,y:top,3:width,width:width,4:height,height:height,5:i,index:i,tooltip:tooltip};}}
58
+ return null;};this.getMax=function(data)
59
+ {var runningTotal=0,max=0;for(var i=0,len=data.length;i<len;i+=1){runningTotal+=data[i];max=ma.max(ma.abs(runningTotal),max);}
60
+ return ma.abs(max);};this.allowTooltips=this.AllowTooltips=function()
61
+ {RG.PreLoadTooltipImages(this);RG.InstallWindowMousedownTooltipListener(this);RG.InstallCanvasMousemoveTooltipListener(this);RG.InstallCanvasMouseupTooltipListener(this);};this.highlight=this.Highlight=function(shape)
62
+ {if(typeof prop['chart.highlight.style']==='function'){(prop['chart.highlight.style'])(shape);}else{RG.Highlight.Rect(this,shape);}};this.getObjectByXY=function(e)
63
+ {var mouseXY=RG.getMouseXY(e);if(mouseXY[0]>this.gutterLeft&&mouseXY[0]<(ca.width-this.gutterRight)&&mouseXY[1]>this.gutterTop&&mouseXY[1]<(ca.height-this.gutterBottom)){return this;}};this.getYCoord=function(value)
64
+ {if(prop['chart.xaxispos']=='center'){if(value<(-1*this.max)){return null;}
65
+ var coord=(value/this.max)*(this.grapharea/2);return this.gutterTop+(this.grapharea/2)-coord;}else{var coord=((value-this.scale2.min)/(this.max-this.scale2.min))*this.grapharea;coord=coord+this.gutterBottom;return ca.height-coord;}};this.parseColors=function()
66
+ {if(this.original_colors.length===0){this.original_colors['chart.colors']=RG.array_clone(prop['chart.colors']);this.original_colors['chart.key.colors']=RG.array_clone(prop['chart.key.colors']);this.original_colors['chart.crosshairs.color']=RG.array_clone(prop['chart.crosshairs.color']);this.original_colors['chart.highlight.stroke']=RG.array_clone(prop['chart.highlight.stroke']);this.original_colors['chart.highlight.fill']=RG.array_clone(prop['chart.highlight.fill']);this.original_colors['chart.background.barcolor1']=RG.array_clone(prop['chart.background.barcolor1']);this.original_colors['chart.background.barcolor2']=RG.array_clone(prop['chart.background.barcolor2']);this.original_colors['chart.background.grid.color']=RG.array_clone(prop['chart.background.grid.color']);this.original_colors['chart.strokestyle']=RG.array_clone(prop['chart.strokestyle']);this.original_colors['chart.axis.color']=RG.array_clone(prop['chart.axis.color']);}
67
+ var colors=prop['chart.colors'];if(colors){for(var i=0,len=colors.length;i<len;++i){colors[i]=this.parseSingleColorForGradient(colors[i]);}}
68
+ var colors=prop['chart.key.colors'];if(colors){for(var i=0,len=colors.length;i<len;++i){colors[i]=this.parseSingleColorForGradient(colors[i]);}}
69
+ prop['chart.crosshairs.color']=this.parseSingleColorForGradient(prop['chart.crosshairs.color']);prop['chart.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.stroke']);prop['chart.highlight.fill']=this.parseSingleColorForGradient(prop['chart.highlight.fill']);prop['chart.background.barcolor1']=this.parseSingleColorForGradient(prop['chart.background.barcolor1']);prop['chart.background.barcolor2']=this.parseSingleColorForGradient(prop['chart.background.barcolor2']);prop['chart.background.grid.color']=this.parseSingleColorForGradient(prop['chart.background.grid.color']);prop['chart.strokestyle']=this.parseSingleColorForGradient(prop['chart.strokestyle']);prop['chart.axis.color']=this.parseSingleColorForGradient(prop['chart.axis.color']);};this.reset=function()
70
+ {};this.parseSingleColorForGradient=function(color)
71
+ {if(!color||typeof color!='string'){return color;}
72
+ if(typeof color==='string'&&color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':');var grad=co.createLinearGradient(0,ca.height-prop['chart.gutter.bottom'],0,prop['chart.gutter.top']);var diff=1/(parts.length-1);grad.addColorStop(0,RG.trim(parts[0]));for(var j=1,len=parts.length;j<len;++j){grad.addColorStop(j*diff,RG.trim(parts[j]));}}
73
+ return grad?grad:color;};this.on=function(type,func)
74
+ {if(type.substr(0,2)!=='on'){type='on'+type;}
75
+ if(typeof this[type]!=='function'){this[type]=func;}else{RG.addCustomEventListener(this,type,func);}
76
+ return this;};this.firstDrawFunc=function()
77
+ {};this.grow=function()
78
+ {var opt=arguments[0]||{};var callback=arguments[1]||function(){};var frames=opt.frames||30;var numFrame=0;var obj=this;var data=RG.array_clone(obj.data);for(var i=0,len=obj.data.length;i<len;++i){obj.data[i]/=frames;}
79
+ if(obj.Get('chart.ymax')==null){var max=obj.getMax(data);var scale2=RG.getScale2(obj,{'max':max});obj.Set('chart.ymax',scale2.max);}
80
+ function iterator()
81
+ {for(var i=0;i<obj.data.length;++i){obj.data[i]=data[i]*RG.Effects.getEasingMultiplier(frames,numFrame);}
82
+ RGraph.clear(obj.canvas);RGraph.redrawCanvas(obj.canvas);if(++numFrame<frames){RGraph.Effects.updateCanvas(iterator);}else{callback(obj);}}
83
+ iterator();return this;};RG.att(ca);RG.Register(this);if(parseConfObjectForOptions){RG.parseObjectStyleConfig(this,conf.options);}
84
+ return this;};