rgraph-rails 4.62 → 4.64

Sign up to get free protection for your applications and to get access to all the features.
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,2789 +1,163 @@
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
- * The horizontal bar chart constructor. The horizontal bar is a minor variant
17
- * on the bar chart. If you have big labels, this may be useful as there is usually
18
- * more space available for them.
19
- *
20
- * @param object canvas The canvas object
21
- * @param array data The chart data
22
- */
23
- RGraph.HBar = function (conf)
24
- {
25
- /**
26
- * Allow for object config style
27
- */
28
- if ( typeof conf === 'object'
29
- && typeof conf.data === 'object'
30
- && typeof conf.id === 'string') {
31
-
32
- var id = conf.id
33
- var canvas = document.getElementById(id);
34
- var data = conf.data;
35
- var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
36
-
37
- } else {
38
-
39
- var id = conf;
40
- var canvas = document.getElementById(id);
41
- var data = arguments[1];
42
- }
43
-
44
-
45
- this.id = id;
46
- this.canvas = canvas;
47
- this.context = this.canvas.getContext ? this.canvas.getContext("2d", {alpha: (typeof id === 'object' && id.alpha === false) ? false : true}) : null;
48
- this.canvas.__object__ = this;
49
- this.data = data;
50
- this.type = 'hbar';
51
- this.isRGraph = true;
52
- this.uid = RGraph.CreateUID();
53
- this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
54
- this.colorsParsed = false;
55
- this.coords = [];
56
- this.coords2 = [];
57
- this.coordsText = [];
58
- this.original_colors = [];
59
- this.firstDraw = true; // After the first draw this will be false
60
-
61
-
62
-
63
-
64
- this.max = 0;
65
- this.stackedOrGrouped = false;
66
-
67
- // Default properties
68
- this.properties =
69
- {
70
- 'chart.gutter.left': 75,
71
- 'chart.gutter.left.autosize': false,
72
- 'chart.gutter.right': 25,
73
- 'chart.gutter.top': 25,
74
- 'chart.gutter.bottom': 25,
75
- 'chart.background.grid': true,
76
- 'chart.background.grid.color': '#ddd',
77
- 'chart.background.grid.width': 1,
78
- 'chart.background.grid.hsize': 25,
79
- 'chart.background.grid.vsize': 25,
80
- 'chart.background.barcolor1': 'rgba(0,0,0,0)',
81
- 'chart.background.barcolor2': 'rgba(0,0,0,0)',
82
- 'chart.background.grid.hlines': true,
83
- 'chart.background.grid.vlines': true,
84
- 'chart.background.grid.border': true,
85
- 'chart.background.grid.autofit':true,
86
- 'chart.background.grid.autofit.align':true,
87
- 'chart.background.grid.autofit.numhlines': null,
88
- 'chart.background.grid.autofit.numvlines': 5,
89
- 'chart.background.grid.dashed': false,
90
- 'chart.background.grid.dotted': false,
91
- 'chart.background.color': null,
92
- 'chart.linewidth': 1,
93
- 'chart.title': '',
94
- 'chart.title.background': null,
95
- 'chart.title.xaxis': '',
96
- 'chart.title.xaxis.bold': true,
97
- 'chart.title.xaxis.size': null,
98
- 'chart.title.xaxis.font': null,
99
- 'chart.title.yaxis': '',
100
- 'chart.title.yaxis.bold': true,
101
- 'chart.title.yaxis.size': null,
102
- 'chart.title.yaxis.font': null,
103
- 'chart.title.yaxis.color': null,
104
- 'chart.title.xaxis.pos': null,
105
- 'chart.title.yaxis.pos': 0.8,
106
- 'chart.title.yaxis.x': null,
107
- 'chart.title.yaxis.y': null,
108
- 'chart.title.xaxis.x': null,
109
- 'chart.title.xaxis.y': null,
110
- 'chart.title.xaxis.color': null,
111
- 'chart.title.hpos': null,
112
- 'chart.title.vpos': null,
113
- 'chart.title.bold': true,
114
- 'chart.title.font': null,
115
- 'chart.title.x': null,
116
- 'chart.title.y': null,
117
- 'chart.title.halign': null,
118
- 'chart.title.valign': null,
119
- 'chart.text.size': 12,
120
- 'chart.text.color': 'black',
121
- 'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
122
- 'chart.text.accessible': true,
123
- 'chart.text.accessible.overflow': 'visible',
124
- 'chart.text.accessible.pointerevents': true,
125
- 'chart.colors': ['red', 'blue', 'green', 'pink', 'yellow', 'cyan', 'navy', 'gray', 'black'],
126
- 'chart.colors.sequential': false,
127
- 'chart.xlabels.specific': null,
128
- 'chart.labels': [],
129
- 'chart.labels.bold': false,
130
- 'chart.labels.color': null,
131
-
132
- 'chart.labels.above': false,
133
- 'chart.labels.above.decimals': 0,
134
- 'chart.labels.above.specific': null,
135
- 'chart.labels.above.color': null,
136
- 'chart.labels.above.units.pre': '',
137
- 'chart.labels.above.units.post': '',
138
- 'chart.labels.above.font': null,
139
- 'chart.labels.above.size': null,
140
- 'chart.labels.above.bold': false,
141
- 'chart.labels.above.italic': false,
142
-
143
- 'chart.labels.offsetx': 0,
144
- 'chart.labels.offsety': 0,
145
- 'chart.xlabels.offsetx': 0,
146
- 'chart.xlabels.offsety': 0,
147
- 'chart.xlabels': true,
148
- 'chart.xlabels.count': 5,
149
- 'chart.contextmenu': null,
150
- 'chart.key': null,
151
- 'chart.key.background': 'white',
152
- 'chart.key.position': 'graph',
153
- 'chart.key.halign': 'right',
154
- 'chart.key.shadow': false,
155
- 'chart.key.shadow.color': '#666',
156
- 'chart.key.shadow.blur': 3,
157
- 'chart.key.shadow.offsetx': 2,
158
- 'chart.key.shadow.offsety': 2,
159
- 'chart.key.position.gutter.boxed': false,
160
- 'chart.key.position.x': null,
161
- 'chart.key.position.y': null,
162
- 'chart.key.color.shape': 'square',
163
- 'chart.key.rounded': true,
164
- 'chart.key.linewidth': 1,
165
- 'chart.key.colors': null,
166
- 'chart.key.interactive': false,
167
- 'chart.key.interactive.highlight.chart.stroke': 'black',
168
- 'chart.key.interactive.highlight.chart.fill':'rgba(255,255,255,0.7)',
169
- 'chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)',
170
- 'chart.key.text.color': 'black',
171
- 'chart.units.pre': '',
172
- 'chart.units.post': '',
173
- 'chart.units.ingraph': false,
174
- 'chart.strokestyle': 'rgba(0,0,0,0)',
175
- 'chart.xmin': 0,
176
- 'chart.xmax': 0,
177
- 'chart.axis.color': 'black',
178
- 'chart.shadow': false,
179
- 'chart.shadow.color': '#666',
180
- 'chart.shadow.blur': 3,
181
- 'chart.shadow.offsetx': 3,
182
- 'chart.shadow.offsety': 3,
183
- 'chart.vmargin': 2,
184
- 'chart.vmargin.grouped': 2,
185
- 'chart.grouping': 'grouped',
186
- 'chart.tooltips': null,
187
- 'chart.tooltips.event': 'onclick',
188
- 'chart.tooltips.effect': 'fade',
189
- 'chart.tooltips.css.class': 'RGraph_tooltip',
190
- 'chart.tooltips.highlight': true,
191
- 'chart.highlight.fill': 'rgba(255,255,255,0.7)',
192
- 'chart.highlight.stroke': 'rgba(0,0,0,0)',
193
- 'chart.highlight.style': null,
194
- 'chart.annotatable': false,
195
- 'chart.annotate.color': 'black',
196
- 'chart.zoom.factor': 1.5,
197
- 'chart.zoom.fade.in': true,
198
- 'chart.zoom.fade.out': true,
199
- 'chart.zoom.hdir': 'right',
200
- 'chart.zoom.vdir': 'down',
201
- 'chart.zoom.frames': 25,
202
- 'chart.zoom.delay': 16.666,
203
- 'chart.zoom.shadow': true,
204
- 'chart.zoom.background': true,
205
- 'chart.zoom.action': 'zoom',
206
- 'chart.resizable': false,
207
- 'chart.resize.handle.adjust': [0,0],
208
- 'chart.resize.handle.background': null,
209
- 'chart.scale.point': '.',
210
- 'chart.scale.thousand': ',',
211
- 'chart.scale.decimals': null,
212
- 'chart.scale.zerostart': true,
213
- 'chart.noredraw': false,
214
- 'chart.events.click': null,
215
- 'chart.events.mousemove': null,
216
- 'chart.noxaxis': false,
217
- 'chart.noyaxis': false,
218
- 'chart.noaxes': false,
219
- 'chart.noxtickmarks': false,
220
- 'chart.noytickmarks': false,
221
- 'chart.numyticks': data.length,
222
- 'chart.numxticks': 10,
223
- 'chart.variant': 'hbar',
224
- 'chart.variant.threed.angle': 0.1,
225
- 'chart.variant.threed.offsetx': 10,
226
- 'chart.variant.threed.offsety': 5,
227
- 'chart.variant.threed.xaxis': true,
228
- 'chart.variant.threed.yaxis': true,
229
- 'chart.yaxispos': 'left',
230
- 'chart.variant': 'hbar',
231
- 'chart.clearto': 'rgba(0,0,0,0)',
232
- 'chart.adjustable': false,
233
- 'chart.adjustable.only': null
234
- }
235
-
236
- // Check for support
237
- if (!this.canvas) {
238
- alert('[HBAR] No canvas support');
239
- return;
240
- }
241
-
242
- // This loop is used to check for stacked or grouped charts and now
243
- // also to convert strings to numbers. And now also undefined values
244
- // (29/07/2016
245
- for (i=0,len=this.data.length; i<len; ++i) {
246
- if (typeof this.data[i] == 'object' && !RGraph.isNull(this.data[i])) {
247
-
248
- this.stackedOrGrouped = true;
249
-
250
- for (var j=0,len2=this.data[i].length; j<len2; ++j) {
251
- if (typeof this.data[i][j] === 'string') {
252
- this.data[i][j] = parseFloat(this.data[i][j]);
253
- }
254
- }
255
-
256
- } else if (typeof this.data[i] == 'string') {
257
- this.data[i] = parseFloat(this.data[i]) || 0;
258
-
259
- } else if (typeof this.data[i] === 'undefined') {
260
- this.data[i] = null;
261
- }
262
- }
263
-
264
-
265
- /**
266
- * Create the dollar objects so that functions can be added to them
267
- */
268
- var linear_data = RGraph.arrayLinearize(data);
269
- for (var i=0,len=linear_data.length; i<len; ++i) {
270
- this['$' + i] = {};
271
- }
272
-
273
-
274
-
275
- /**
276
- * Create the linear data array
277
- */
278
- this.data_arr = RGraph.arrayLinearize(this.data);
279
-
280
-
281
- /**
282
- * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
283
- * done already
284
- */
285
- if (!this.canvas.__rgraph_aa_translated__) {
286
- this.context.translate(0.5,0.5);
287
-
288
- this.canvas.__rgraph_aa_translated__ = true;
289
- }
290
-
291
-
292
-
293
-
294
- // Short variable names
295
- var RG = RGraph,
296
- ca = this.canvas,
297
- co = ca.getContext('2d'),
298
- prop = this.properties,
299
- pa2 = RG.path2,
300
- win = window,
301
- doc = document,
302
- ma = Math
303
-
304
-
305
-
306
- /**
307
- * "Decorate" the object with the generic effects if the effects library has been included
308
- */
309
- if (RG.Effects && typeof RG.Effects.decorate === 'function') {
310
- RG.Effects.decorate(this);
311
- }
312
-
313
-
314
-
315
-
316
- /**
317
- * A setter
318
- *
319
- * @param name string The name of the property to set
320
- * @param value mixed The value of the property
321
- */
322
- this.set =
323
- this.Set = function (name)
324
- {
325
- var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
326
-
327
- /**
328
- * the number of arguments is only one and it's an
329
- * object - parse it for configuration data and return.
330
- */
331
- if (arguments.length === 1 && typeof name === 'object') {
332
- RG.parseObjectStyleConfig(this, name);
333
- return this;
334
- }
335
-
336
-
337
-
338
-
339
- /**
340
- * This should be done first - prepend the propertyy name with "chart." if necessary
341
- */
342
- if (name.substr(0,6) != 'chart.') {
343
- name = 'chart.' + name;
344
- }
345
-
346
-
347
-
348
- // Convert uppercase letters to dot+lower case letter
349
- while(name.match(/([A-Z])/)) {
350
- name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
351
- }
352
-
353
- if (name == 'chart.labels.abovebar') {
354
- name = 'chart.labels.above';
355
- }
356
-
357
- prop[name] = value;
358
-
359
- return this;
360
- };
361
-
362
-
363
-
364
-
365
- /**
366
- * A getter
367
- *
368
- * @param name string The name of the property to get
369
- */
370
- this.get =
371
- this.Get = function (name)
372
- {
373
- /**
374
- * This should be done first - prepend the property name with "chart." if necessary
375
- */
376
- if (name.substr(0,6) != 'chart.') {
377
- name = 'chart.' + name;
378
- }
379
-
380
- // Convert uppercase letters to dot+lower case letter
381
- while(name.match(/([A-Z])/)) {
382
- name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
383
- }
384
-
385
-
386
- if (name == 'chart.labels.abovebar') {
387
- name = 'chart.labels.above';
388
- }
389
-
390
- return prop[name];
391
- };
392
-
393
-
394
-
395
-
396
- /**
397
- * The function you call to draw the bar chart
398
- */
399
- this.draw =
400
- this.Draw = function ()
401
- {
402
- /**
403
- * Fire the onbeforedraw event
404
- */
405
- RG.fireCustomEvent(this, 'onbeforedraw');
406
-
407
-
408
- //
409
- // Check that the bHBar isn't stacked with adjusting enabled
410
- //
411
- if (prop['chart.adjustable'] && prop['chart.grouping'] === 'stacked') {
412
- alert('[RGRAPH] The HBar does not support stacked charts with adjusting');
413
- }
414
-
415
- //
416
- // If the chart is 3d then angle it it
417
- //
418
-
419
- if (prop['chart.variant'] === '3d') {
420
-
421
- if (prop['chart.text.accessible']) {
422
- // Nada
423
- } else {
424
- co.setTransform(1,prop['chart.variant.threed.angle'],0,1,0.5,0.5);
425
- }
426
-
427
- // Enlarge the gutter if its 25
428
- if (prop['chart.gutter.bottom'] === 25) {
429
- this.set('gutterBottom', 80);
430
- }
431
- }
432
-
433
-
434
-
435
-
436
- /**
437
- * Parse the colors. This allows for simple gradient syntax
438
- */
439
- if (!this.colorsParsed) {
440
- this.parseColors();
441
-
442
- // Don't want to do this again
443
- this.colorsParsed = true;
444
- }
445
-
446
-
447
-
448
-
449
-
450
-
451
- /**
452
- * Accomodate autosizing the left gutter
453
- */
454
- if (prop['chart.gutter.left.autosize']) {
455
- var len = 0;
456
- var labels = prop['chart.labels'];
457
- var font = prop['chart.text.font'];
458
- var size = prop['chart.text.size'];
459
-
460
- for (var i=0; i<labels.length; i+=1) {
461
- var length = RG.measureText(labels[i], false, font, size)[0] || 0
462
- len = ma.max(len, length);
463
- }
464
-
465
- prop['chart.gutter.left'] = len + 10;
466
- }
467
-
468
-
469
-
470
-
471
-
472
-
473
-
474
-
475
-
476
-
477
-
478
-
479
-
480
- /**
481
- * This is new in May 2011 and facilitates indiviual gutter settings,
482
- * eg chart.gutter.left
483
- */
484
- this.gutterLeft = prop['chart.gutter.left'];
485
- this.gutterRight = prop['chart.gutter.right'];
486
- this.gutterTop = prop['chart.gutter.top'];
487
- this.gutterBottom = prop['chart.gutter.bottom'];
488
-
489
-
490
-
491
-
492
- /**
493
- * Stop the coords array from growing uncontrollably
494
- */
495
- this.coords = [];
496
- this.coords2 = [];
497
- this.coordsText = [];
498
- this.max = 0;
499
-
500
- /**
501
- * Check for chart.xmin in stacked charts
502
- */
503
- if (prop['chart.xmin'] > 0 && prop['chart.grouping'] == 'stacked') {
504
- alert('[HBAR] Using chart.xmin is not supported with stacked charts, resetting chart.xmin to zero');
505
- this.Set('chart.xmin', 0);
506
- }
507
-
508
- /**
509
- * Work out a few things. They need to be here because they depend on things you can change before you
510
- * call Draw() but after you instantiate the object
511
- */
512
- this.graphwidth = ca.width - this.gutterLeft - this.gutterRight;
513
- this.graphheight = ca.height - this.gutterTop - this.gutterBottom;
514
- this.halfgrapharea = this.grapharea / 2;
515
- this.halfTextHeight = prop['chart.text.size'] / 2;
516
- this.halfway = ma.round((this.graphwidth / 2) + this.gutterLeft)
517
-
518
-
519
-
520
-
521
-
522
-
523
-
524
-
525
-
526
-
527
- // Progressively Draw the chart
528
- RG.Background.draw(this);
529
-
530
- this.drawbars();
531
- this.drawAxes();
532
- this.drawLabels();
533
-
534
-
535
- // Draw the key if necessary
536
- if (prop['chart.key'] && prop['chart.key'].length) {
537
- RG.DrawKey(this, prop['chart.key'], prop['chart.colors']);
538
- }
539
-
540
-
541
-
542
- /**
543
- * Setup the context menu if required
544
- */
545
- if (prop['chart.contextmenu']) {
546
- RG.ShowContext(this);
547
- }
548
-
549
-
550
-
551
- /**
552
- * Draw "in graph" labels
553
- */
554
- RG.DrawInGraphLabels(this);
555
-
556
-
557
- /**
558
- * This function enables resizing
559
- */
560
- if (prop['chart.resizable']) {
561
- RG.AllowResizing(this);
562
- }
563
-
564
-
565
- /**
566
- * This installs the event listeners
567
- */
568
- RG.InstallEventListeners(this);
569
-
570
-
571
- /**
572
- * Fire the onfirstdraw event
573
- */
574
- if (this.firstDraw) {
575
- RG.fireCustomEvent(this, 'onfirstdraw');
576
- this.firstDraw = false;
577
- this.firstDrawFunc();
578
- }
579
-
580
-
581
-
582
- /**
583
- * Fire the RGraph ondraw event
584
- */
585
- RG.FireCustomEvent(this, 'ondraw');
586
-
587
- return this;
588
- };
589
-
590
-
591
-
592
- /**
593
- * Used in chaining. Runs a function there and then - not waiting for
594
- * the events to fire (eg the onbeforedraw event)
595
- *
596
- * @param function func The function to execute
597
- */
598
- this.exec = function (func)
599
- {
600
- func(this);
601
-
602
- return this;
603
- };
604
-
605
-
606
-
607
-
608
- /**
609
- * This draws the axes
610
- */
611
- this.drawAxes =
612
- this.DrawAxes = function ()
613
- {
614
- var halfway = this.halfway
615
-
616
-
617
-
618
-
619
-
620
-
621
- co.beginPath();
622
-
623
- co.lineWidth = prop['chart.axis.linewidth'] ? prop['chart.axis.linewidth'] + 0.001 : 1.001;
624
- co.strokeStyle = prop['chart.axis.color'];
625
-
626
-
627
-
628
-
629
- // Draw the Y axis
630
- if (prop['chart.noyaxis'] == false && prop['chart.noaxes'] == false) {
631
- if (prop['chart.yaxispos'] == 'center') {
632
- co.moveTo(halfway, this.gutterTop);
633
- co.lineTo(halfway, ca.height - this.gutterBottom);
634
-
635
- } else if (prop['chart.yaxispos'] == 'right') {
636
- co.moveTo(ca.width - this.gutterRight, this.gutterTop);
637
- co.lineTo(ca.width - this.gutterRight, ca.height - this.gutterBottom);
638
-
639
- } else {
640
- co.moveTo(this.gutterLeft, this.gutterTop);
641
- co.lineTo(this.gutterLeft, ca.height - this.gutterBottom);
642
- }
643
- }
644
-
645
- // Draw the X axis
646
- if (prop['chart.noxaxis'] == false && prop['chart.noaxes'] == false) {
647
- co.moveTo(this.gutterLeft +0.001, ca.height - this.gutterBottom + 0.001);
648
- co.lineTo(ca.width - this.gutterRight + 0.001, ca.height - this.gutterBottom + 0.001);
649
- }
650
-
651
- // Draw the Y tickmarks
652
- if ( prop['chart.noytickmarks'] == false
653
- && prop['chart.noyaxis'] == false
654
- && prop['chart.numyticks'] > 0
655
- && prop['chart.noaxes'] == false
656
- ) {
657
-
658
- var yTickGap = (ca.height - this.gutterTop - this.gutterBottom) / (prop['chart.numyticks'] > 0 ? prop['chart.numyticks'] : this.data.length);
659
-
660
- for (y=this.gutterTop; y<(ca.height - this.gutterBottom - 1); y+=yTickGap) {
661
- if (prop['chart.yaxispos'] == 'center') {
662
- co.moveTo(halfway + 3, ma.round(y));
663
- co.lineTo(halfway - 3, ma.round(y));
664
-
665
- } else if (prop['chart.yaxispos'] == 'right') {
666
- co.moveTo(ca.width - this.gutterRight, ma.round(y));
667
- co.lineTo(ca.width - this.gutterRight + 3, ma.round(y));
668
-
669
- } else {
670
- co.moveTo(this.gutterLeft, ma.round(y));
671
- co.lineTo( this.gutterLeft - 3, ma.round(y));
672
- }
673
- }
674
-
675
- // If the X axis isn't being shown draw the end tick
676
- if (prop['chart.noxaxis'] == true) {
677
- if (prop['chart.yaxispos'] == 'center') {
678
- co.moveTo(halfway + 3, ma.round(y));
679
- co.lineTo(halfway - 3, ma.round(y));
680
-
681
- } else if (prop['chart.yaxispos'] == 'right') {
682
- co.moveTo(ca.width - this.gutterRight, ma.round(y));
683
- co.lineTo(ca.width - this.gutterRight + 3, ma.round(y));
684
-
685
- } else {
686
- co.moveTo(this.gutterLeft, ma.round(y));
687
- co.lineTo( this.gutterLeft - 3, ma.round(y));
688
- }
689
- }
690
- }
691
-
692
-
693
- // Draw the X tickmarks
694
- if ( prop['chart.noxtickmarks'] == false
695
- && prop['chart.noxaxis'] == false
696
- && prop['chart.numxticks'] > 0
697
- && prop['chart.noaxes'] == false) {
698
-
699
- xTickGap = (ca.width - this.gutterLeft - this.gutterRight ) / prop['chart.numxticks'];
700
- yStart = ca.height - this.gutterBottom;
701
- yEnd = (ca.height - this.gutterBottom) + 3;
702
-
703
-
704
-
705
-
706
-
707
- var i = prop['chart.numxticks']
708
-
709
- while(i--) {
710
-
711
- var x = ca.width - this.gutterRight - (i * xTickGap);
712
-
713
- if (prop['chart.yaxispos'] === 'right') {
714
- x -= xTickGap;
715
- }
716
-
717
- co.moveTo(ma.round(x), yStart);
718
- co.lineTo(ma.round(x), yEnd);
719
- }
720
-
721
-
722
-
723
- if (prop['chart.yaxispos'] === 'center') {
724
- var i = 5; while (i--) {
725
- var x = this.gutterLeft + (xTickGap * i);
726
-
727
- co.moveTo(ma.round(x), yStart);
728
- co.lineTo(ma.round(x), yEnd);
729
-
730
- }
731
- }
732
-
733
-
734
-
735
-
736
-
737
- // If the Y axis isn't being shown draw the end tick
738
- if (prop['chart.noyaxis'] == true) {
739
- co.moveTo(this.gutterLeft, ma.round(yStart));
740
- co.lineTo( this.gutterLeft, ma.round(yEnd));
741
- }
742
- }
743
- co.stroke();
744
-
745
- /**
746
- * Reset the linewidth
747
- */
748
- co.lineWidth = 1;
749
- };
750
-
751
-
752
-
753
-
754
- /**
755
- * This draws the labels for the graph
756
- */
757
- this.drawLabels =
758
- this.DrawLabels = function ()
759
- {
760
- var units_pre = prop['chart.units.pre'],
761
- units_post = prop['chart.units.post'],
762
- text_size = prop['chart.text.size'],
763
- font = prop['chart.text.font'],
764
- offsetx = prop['chart.xlabels.offsetx'],
765
- offsety = prop['chart.xlabels.offsety']
766
-
767
-
768
-
769
- /**
770
- * Set the units to blank if they're to be used for ingraph labels only
771
- */
772
- if (prop['chart.units.ingraph']) {
773
- units_pre = '';
774
- units_post = '';
775
- }
776
-
777
-
778
- /**
779
- * Draw the X axis labels
780
- */
781
- if (prop['chart.xlabels']) {
782
-
783
- /**
784
- * Specific X labels
785
- */
786
- if (RG.isArray(prop['chart.xlabels.specific'])) {
787
-
788
- if (prop['chart.yaxispos'] == 'center') {
789
-
790
- var halfGraphWidth = this.graphwidth / 2;
791
- var labels = prop['chart.xlabels.specific'];
792
- var interval = (this.graphwidth / 2) / (labels.length - 1);
793
-
794
- co.fillStyle = prop['chart.text.color'];
795
-
796
- for (var i=0; i<labels.length; i+=1) {
797
- RG.text2(this, {
798
- 'font':font,
799
- 'size':text_size,
800
- 'x':this.gutterLeft + halfGraphWidth + (interval * i) + offsetx,
801
- 'y':ca.height - this.gutterBottom + offsetx,
802
- 'text':labels[i],
803
- 'valign':'top',
804
- 'halign':'center',
805
- 'tag': 'scale'
806
- });
807
- }
808
-
809
- for (var i=(labels.length - 1); i>0; i-=1) {
810
- RG.Text2(this, {
811
- 'font':font,
812
- 'size':text_size,
813
- 'x':this.gutterLeft + (interval * (labels.length - i - 1)) + offsetx,
814
- 'y':ca.height - this.gutterBottom + offsety,
815
- 'text':labels[i],
816
- 'valign':'top',
817
- 'halign':'center',
818
- 'tag': 'scale'
819
- });
820
- }
821
-
822
- } else if (prop['chart.yaxispos'] == 'right') {
823
-
824
- var labels = prop['chart.xlabels.specific'];
825
- var interval = this.graphwidth / (labels.length - 1);
826
-
827
- co.fillStyle = prop['chart.text.color'];
828
-
829
- for (var i=0; i<labels.length; i+=1) {
830
- RG.text2(this, {
831
- 'font': font,
832
- 'size': text_size,
833
- 'x': this.gutterLeft + (interval * i) + offsetx,
834
- 'y': ca.height - this.gutterBottom + offsety,
835
- 'text': labels[labels.length - i - 1],
836
- 'valign':'top',
837
- 'halign':'center',
838
- 'tag': 'scale'
839
- });
840
- }
841
-
842
- } else {
843
-
844
- var labels = prop['chart.xlabels.specific'];
845
- var interval = this.graphwidth / (labels.length - 1);
846
-
847
- co.fillStyle = prop['chart.text.color'];
848
-
849
- for (var i=0; i<labels.length; i+=1) {
850
- RG.text2(this, {
851
- font: font,
852
- size: text_size,
853
- x: this.gutterLeft + (interval * i) + offsetx,
854
- y: ca.height - this.gutterBottom + offsety,
855
- text: labels[i],
856
- valign:'top',
857
- halign:'center',
858
- tag: 'scale'
859
- });
860
- }
861
- }
862
-
863
- /**
864
- * Draw an X scale
865
- */
866
- } else {
867
-
868
- var gap = 7;
869
-
870
- co.beginPath();
871
- co.fillStyle = prop['chart.text.color'];
872
-
873
-
874
- if (prop['chart.yaxispos'] == 'center') {
875
-
876
- for (var i=0; i<this.scale2.labels.length; ++i) {
877
- RG.text2(this, {
878
- 'font':font,
879
- 'size':text_size,
880
- 'x':this.gutterLeft + (this.graphwidth / 2) - ((this.graphwidth / 2) * ((i+1)/this.scale2.labels.length)) + offsetx,
881
- 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap + offsety,
882
- 'text':'-' + this.scale2.labels[i],
883
- 'valign':'center',
884
- 'halign':'center',
885
- 'tag': 'scale'
886
- });
887
- }
888
-
889
- for (var i=0; i<this.scale2.labels.length; ++i) {
890
- RG.text2(this, {
891
- 'font':font,
892
- 'size':text_size,
893
- 'x':this.gutterLeft + ((this.graphwidth / 2) * ((i+1)/this.scale2.labels.length)) + (this.graphwidth / 2) + offsetx,
894
- 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap + offsety,
895
- 'text':this.scale2.labels[i],
896
- 'valign':'center',
897
- 'halign':'center',
898
- 'tag': 'scale'
899
- });
900
- }
901
-
902
- }else if (prop['chart.yaxispos'] == 'right') {
903
-
904
-
905
- for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
906
- RG.Text2(this, {
907
- 'font':font,
908
- 'size':text_size,
909
- 'x':this.gutterLeft + (i * (this.graphwidth / len)) + offsetx,
910
- 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap + offsety,
911
- 'text':'-' + this.scale2.labels[len - 1 - i],
912
- 'valign':'center',
913
- 'halign':'center',
914
- 'tag': 'scale'
915
- });
916
- }
917
-
918
-
919
- } else {
920
- for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
921
- RG.Text2(this, {
922
- 'font':font,
923
- 'size':text_size,
924
- 'x':this.gutterLeft + (this.graphwidth * ((i+1)/len)) + offsetx,
925
- 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap + offsety,
926
- 'text':this.scale2.labels[i],
927
- 'valign':'center',
928
- 'halign':'center',
929
- 'tag': 'scale'
930
- });
931
- }
932
- }
933
-
934
- /**
935
- * If xmin is not zero - draw that
936
- */
937
- if (prop['chart.xmin'] > 0 || prop['chart.noyaxis'] == true || prop['chart.scale.zerostart'] || prop['chart.noaxes']) {
938
-
939
- var x = prop['chart.yaxispos'] == 'center' ? this.gutterLeft + (this.graphwidth / 2): this.gutterLeft;
940
-
941
- /**
942
- * Y axis on the right
943
- */
944
- if (prop['chart.yaxispos'] === 'right') {
945
- var x = ca.width - this.gutterRight;
946
- }
947
-
948
- RG.text2(this, {
949
- 'font':font,
950
- 'size':text_size,
951
- 'x':x + offsetx,
952
- 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap + offsety,
953
- 'text':RG.numberFormat(this, prop['chart.xmin'].toFixed(prop['chart.xmin'] === 0 ? 0 : prop['chart.scale.decimals']), units_pre, units_post),
954
- 'valign':'center',
955
- 'halign':'center',
956
- 'tag': 'scale'
957
- });
958
- }
959
-
960
- co.fill();
961
- co.stroke();
962
- }
963
- }
964
-
965
-
966
-
967
-
968
-
969
-
970
-
971
- /**
972
- * The Y axis labels
973
- */
974
- if (typeof prop['chart.labels'] == 'object') {
975
-
976
- var xOffset = prop['chart.variant'] === '3d' && prop['chart.yaxispos'] === 'right' ? 15 : 5,
977
- font = prop['chart.text.font'],
978
- color = prop['chart.labels.color'] || prop['chart.text.color'],
979
- bold = prop['chart.labels.bold'],
980
- offsetx = prop['chart.labels.offsetx'],
981
- offsety = prop['chart.labels.offsety']
982
-
983
-
984
- // Draw the X axis labels
985
- co.fillStyle = color;
986
-
987
- // How high is each bar
988
- var barHeight = (ca.height - this.gutterTop - this.gutterBottom ) / prop['chart.labels'].length;
989
-
990
- // Reset the yTickGap
991
- yTickGap = (ca.height - this.gutterTop - this.gutterBottom) / prop['chart.labels'].length
992
-
993
- /**
994
- * If the Y axis is on the right set the alignment and the X position, otherwise on the left
995
- */
996
- if (prop['chart.yaxispos'] === 'right') {
997
- var x = ca.width - this.gutterRight + xOffset;
998
- var halign = 'left'
999
- } else {
1000
- var x = this.gutterLeft - xOffset;
1001
- var halign = 'right'
1002
- }
1003
-
1004
- // Draw the X tickmarks
1005
- var i=0;
1006
- for (y=this.gutterTop + (yTickGap / 2); y<=ca.height - this.gutterBottom; y+=yTickGap) {
1007
-
1008
- RG.text2(this, {
1009
- 'font': font,
1010
- 'size': prop['chart.text.size'],
1011
- 'bold': bold,
1012
- 'x': x + offsetx,
1013
- 'y': y + offsety,
1014
- 'text': String(prop['chart.labels'][i++]),
1015
- 'halign': halign,
1016
- 'valign': 'center',
1017
- 'tag': 'labels'
1018
- });
1019
- }
1020
- }
1021
- };
1022
-
1023
-
1024
-
1025
-
1026
- /**
1027
- * This function draws the bars. It also draw 3D axes as the axes drawing bit
1028
- * is don AFTER the bars are drawn
1029
- */
1030
- this.drawbars =
1031
- this.Drawbars = function ()
1032
- {
1033
- co.lineWidth = prop['chart.linewidth'];
1034
- co.strokeStyle = prop['chart.strokestyle'];
1035
- co.fillStyle = prop['chart.colors'][0];
1036
-
1037
- var prevX = 0,
1038
- prevY = 0;
1039
-
1040
-
1041
- /**
1042
- * Work out the max value
1043
- */
1044
- if (prop['chart.xmax']) {
1045
-
1046
- this.scale2 = RG.getScale2(this, {
1047
- 'max':prop['chart.xmax'],
1048
- 'min':prop['chart.xmin'],
1049
- 'scale.decimals':Number(prop['chart.scale.decimals']),
1050
- 'scale.point':prop['chart.scale.point'],
1051
- 'scale.thousand':prop['chart.scale.thousand'],
1052
- 'scale.round':prop['chart.scale.round'],
1053
- 'units.pre':prop['chart.units.pre'],
1054
- 'units.post':prop['chart.units.post'],
1055
- 'ylabels.count':prop['chart.xlabels.count'],
1056
- 'strict':true
1057
- });
1058
-
1059
- this.max = this.scale2.max;
1060
-
1061
- } else {
1062
-
1063
- var grouping = prop['chart.grouping'];
1064
-
1065
- for (i=0; i<this.data.length; ++i) {
1066
- if (typeof(this.data[i]) == 'object') {
1067
- var value = grouping == 'grouped' ? Number(RG.array_max(this.data[i], true)) : Number(RG.array_sum(this.data[i])) ;
1068
- } else {
1069
- var value = Number(ma.abs(this.data[i]));
1070
- }
1071
-
1072
- this.max = ma.max(Math.abs(this.max), Math.abs(value));
1073
- }
1074
-
1075
- this.scale2 = RG.getScale2(this, {
1076
- 'max':this.max,
1077
- 'min':prop['chart.xmin'],
1078
- 'scale.decimals':Number(prop['chart.scale.decimals']),
1079
- 'scale.point':prop['chart.scale.point'],
1080
- 'scale.thousand':prop['chart.scale.thousand'],
1081
- 'scale.round':prop['chart.scale.round'],
1082
- 'units.pre':prop['chart.units.pre'],
1083
- 'units.post':prop['chart.units.post'],
1084
- 'ylabels.count':prop['chart.xlabels.count']
1085
- });
1086
-
1087
-
1088
- this.max = this.scale2.max;
1089
- this.min = this.scale2.min;
1090
- }
1091
-
1092
- if (prop['chart.scale.decimals'] == null && Number(this.max) == 1) {
1093
- this.Set('chart.scale.decimals', 1);
1094
- }
1095
-
1096
- /**
1097
- * This is here to facilitate sequential colors
1098
- */
1099
- var colorIdx = 0;
1100
-
1101
- //
1102
- // For grouped bars we need to calculate the number of bars
1103
- //
1104
- this.numbars = RG.arrayLinearize(this.data).length;
1105
-
1106
-
1107
-
1108
-
1109
- /**
1110
- * if the chart is adjustable fix the scale so that it doesn't change.
1111
- *
1112
- * It's here (after the scale generation) so that the max value can be
1113
- * set to the maximum scale value)
1114
- */
1115
- if (prop['chart.adjustable'] && !prop['chart.xmax']) {
1116
- this.set('chart.xmax', this.scale2.max);
1117
- }
1118
-
1119
-
1120
-
1121
- // Draw the 3d axes if necessary
1122
- if (prop['chart.variant'] === '3d') {
1123
- RG.draw3DAxes(this);
1124
- }
1125
-
1126
-
1127
-
1128
-
1129
-
1130
-
1131
- /**
1132
- * The bars are drawn HERE
1133
- */
1134
- var graphwidth = (ca.width - this.gutterLeft - this.gutterRight);
1135
- var halfwidth = graphwidth / 2;
1136
-
1137
- for (i=(len=this.data.length-1); i>=0; --i) {
1138
-
1139
- // Work out the width and height
1140
- var width = ma.abs((this.data[i] / this.max) * graphwidth);
1141
- var height = this.graphheight / this.data.length;
1142
-
1143
- var orig_height = height;
1144
-
1145
- var x = this.gutterLeft;
1146
- var y = this.gutterTop + (i * height);
1147
- var vmargin = prop['chart.vmargin'];
1148
-
1149
- // Account for the Y axis being on the right hand side
1150
- if (prop['chart.yaxispos'] === 'right') {
1151
- x = ca.width - this.gutterRight - ma.abs(width);
1152
- }
1153
-
1154
- // Account for negative lengths - Some browsers (eg Chrome) don't like a negative value
1155
- if (width < 0) {
1156
- x -= width;
1157
- width = ma.abs(width);
1158
- }
1159
-
1160
- /**
1161
- * Turn on the shadow if need be
1162
- */
1163
- if (prop['chart.shadow']) {
1164
- co.shadowColor = prop['chart.shadow.color'];
1165
- co.shadowBlur = prop['chart.shadow.blur'];
1166
- co.shadowOffsetX = prop['chart.shadow.offsetx'];
1167
- co.shadowOffsetY = prop['chart.shadow.offsety'];
1168
- }
1169
-
1170
- /**
1171
- * Draw the bar
1172
- */
1173
- co.beginPath();
1174
-
1175
- // Standard (non-grouped and non-stacked) bars here
1176
- if (typeof this.data[i] == 'number' || RG.isNull(this.data[i])) {
1177
-
1178
- var barHeight = height - (2 * vmargin),
1179
- barWidth = ((this.data[i] - prop['chart.xmin']) / (this.max - prop['chart.xmin'])) * this.graphwidth,
1180
- barX = this.gutterLeft;
1181
-
1182
- // Account for Y axis pos
1183
- if (prop['chart.yaxispos'] == 'center') {
1184
- barWidth /= 2;
1185
- barX += halfwidth;
1186
-
1187
- if (this.data[i] < 0) {
1188
- barWidth = (ma.abs(this.data[i]) - prop['chart.xmin']) / (this.max - prop['chart.xmin']);
1189
- barWidth = barWidth * (this.graphwidth / 2);
1190
- barX = ((this.graphwidth / 2) + this.gutterLeft) - barWidth;
1191
- }
1192
-
1193
- } else if (prop['chart.yaxispos'] == 'right') {
1194
-
1195
- barWidth = ma.abs(barWidth);
1196
- barX = ca.width - this.gutterRight - barWidth;
1197
-
1198
- }
1199
-
1200
- // Set the fill color
1201
- co.strokeStyle = prop['chart.strokestyle'];
1202
- co.fillStyle = prop['chart.colors'][0];
1203
-
1204
- // Sequential colors
1205
- ++colorIdx;
1206
- if (prop['chart.colors.sequential'] && typeof colorIdx === 'number') {
1207
- if (prop['chart.colors'][this.numbars - colorIdx]) {
1208
- co.fillStyle = prop['chart.colors'][this.numbars - colorIdx];
1209
- } else {
1210
- co.fillStyle = prop['chart.colors'][prop['chart.colors'].length - 1];
1211
- }
1212
- }
1213
-
1214
-
1215
-
1216
-
1217
-
1218
-
1219
-
1220
-
1221
-
1222
-
1223
-
1224
-
1225
-
1226
-
1227
-
1228
-
1229
- co.strokeRect(barX, this.gutterTop + (i * height) + prop['chart.vmargin'], barWidth, barHeight);
1230
- co.fillRect(barX, this.gutterTop + (i * height) + prop['chart.vmargin'], barWidth, barHeight);
1231
-
1232
-
1233
-
1234
-
1235
-
1236
-
1237
-
1238
-
1239
-
1240
-
1241
-
1242
-
1243
-
1244
-
1245
-
1246
-
1247
-
1248
-
1249
-
1250
-
1251
-
1252
-
1253
-
1254
-
1255
- this.coords.push([
1256
- barX,
1257
- y + vmargin,
1258
- barWidth,
1259
- height - (2 * vmargin),
1260
- co.fillStyle,
1261
- this.data[i],
1262
- true
1263
- ]);
1264
-
1265
-
1266
-
1267
-
1268
-
1269
-
1270
- // Draw the 3D effect using the coords that have just been stored
1271
- if (prop['chart.variant'] === '3d' && typeof this.data[i] == 'number') {
1272
-
1273
-
1274
- var prevStrokeStyle = co.strokeStyle,
1275
- prevFillStyle = co.fillStyle;
1276
-
1277
- /**
1278
- * Turn off the shadow for the 3D bits
1279
- */
1280
- RG.noShadow(this);
1281
-
1282
- // DRAW THE 3D BITS HERE
1283
- var barX = barX,
1284
- barY = y + vmargin,
1285
- barW = barWidth,
1286
- barH = height - (2 * vmargin),
1287
- offsetX = prop['chart.variant.threed.offsetx'],
1288
- offsetY = prop['chart.variant.threed.offsety'],
1289
- value = this.data[i];
1290
-
1291
-
1292
- pa2(
1293
- co,
1294
- [
1295
- 'b',
1296
- 'm', barX, barY,
1297
- 'l', barX + offsetX - (prop['chart.yaxispos'] == 'left' && value < 0 ? offsetX : 0), barY - offsetY,
1298
- 'l', barX + barW + offsetX - (prop['chart.yaxispos'] == 'center' && value < 0 ? offsetX : 0), barY - offsetY,
1299
- 'l', barX + barW, barY,
1300
- 'c',
1301
- 's', co.strokeStyle,
1302
- 'f', co.fillStyle,
1303
- 'f','rgba(255,255,255,0.6)'//Fill again to lighten it
1304
- ]
1305
- );
1306
-
1307
- if ( prop['chart.yaxispos'] !== 'right'
1308
- && !(prop['chart.yaxispos'] === 'center' && value < 0)
1309
- && value >= 0
1310
- && !RG.isNull(value)
1311
- ) {
1312
-
1313
- pa2(
1314
- co,
1315
- [
1316
- 'b',
1317
- 'fs', prevFillStyle,
1318
- 'm', barX + barW, barY,
1319
- 'l', barX + barW + offsetX, barY - offsetY,
1320
- 'l', barX + barW + offsetX, barY - offsetY + barH,
1321
- 'l', barX + barW, barY + barH,
1322
- 'c',
1323
- 's', co.strokeStyle,
1324
- 'f', prevFillStyle,
1325
- 'f', 'rgba(0,0,0,0.25)'
1326
- ]
1327
- );
1328
- }
1329
-
1330
- }
1331
-
1332
-
1333
-
1334
-
1335
-
1336
-
1337
- /**
1338
- * Stacked bar chart
1339
- */
1340
- } else if (typeof(this.data[i]) == 'object' && prop['chart.grouping'] == 'stacked') {
1341
-
1342
- if (prop['chart.yaxispos'] == 'center') {
1343
- alert('[HBAR] You can\'t have a stacked chart with the Y axis in the center, change it to grouped');
1344
- } else if (prop['chart.yaxispos'] == 'right') {
1345
- var x = ca.width - this.gutterRight
1346
- }
1347
-
1348
- var barHeight = height - (2 * vmargin);
1349
-
1350
- if (typeof this.coords2[i] == 'undefined') {
1351
- this.coords2[i] = [];
1352
- }
1353
-
1354
- for (j=0; j<this.data[i].length; ++j) {
1355
-
1356
- // The previous 3D segments would have turned the shadow off - so turn it back on
1357
- if (prop['chart.shadow'] && prop['chart.variant'] === '3d') {
1358
- co.shadowColor = prop['chart.shadow.color'];
1359
- co.shadowBlur = prop['chart.shadow.blur'];
1360
- co.shadowOffsetX = prop['chart.shadow.offsetx'];
1361
- co.shadowOffsetY = prop['chart.shadow.offsety'];
1362
- }
1363
-
1364
- //
1365
- // Ensure the number is positive
1366
- //(even though having the X axis on the right implies a
1367
- //negative value)
1368
- //
1369
- if (!RG.isNull(this.data[i][j])) this.data[i][j] = ma.abs(this.data[i][j]);
1370
-
1371
-
1372
- var last = (j === (this.data[i].length - 1) );
1373
-
1374
- // Set the fill/stroke colors
1375
- co.strokeStyle = prop['chart.strokestyle'];
1376
-
1377
- // Sequential colors
1378
- ++colorIdx;
1379
- if (prop['chart.colors.sequential'] && typeof colorIdx === 'number') {
1380
- if (prop['chart.colors'][this.numbars - colorIdx]) {
1381
- co.fillStyle = prop['chart.colors'][this.numbars - colorIdx];
1382
- } else {
1383
- co.fillStyle = prop['chart.colors'][prop['chart.colors'].length - 1];
1384
- }
1385
- } else if (prop['chart.colors'][j]) {
1386
- co.fillStyle = prop['chart.colors'][j];
1387
- }
1388
-
1389
-
1390
- var width = (((this.data[i][j]) / (this.max))) * this.graphwidth;
1391
- var totalWidth = (RG.arraySum(this.data[i]) / this.max) * this.graphwidth;
1392
-
1393
- if (prop['chart.yaxispos'] === 'right') {
1394
- x -= width;
1395
- }
1396
-
1397
-
1398
-
1399
- co.strokeRect(x, this.gutterTop + prop['chart.vmargin'] + (this.graphheight / this.data.length) * i, width, height - (2 * vmargin) );
1400
- co.fillRect(x, this.gutterTop + prop['chart.vmargin'] + (this.graphheight / this.data.length) * i, width, height - (2 * vmargin) );
1401
-
1402
-
1403
- /**
1404
- * Store the coords for tooltips
1405
- */
1406
-
1407
- // The last property of this array is a boolean which tells you whether the value is the last or not
1408
- this.coords.push([
1409
- x,
1410
- y + vmargin,
1411
- width,
1412
- height - (2 * vmargin),
1413
- co.fillStyle,
1414
- RG.array_sum(this.data[i]),
1415
- j == (this.data[i].length - 1)
1416
- ]);
1417
-
1418
- this.coords2[i].push([
1419
- x,
1420
- y + vmargin,
1421
- width,
1422
- height - (2 * vmargin),
1423
- co.fillStyle,
1424
- RG.array_sum(this.data[i]),
1425
- j == (this.data[i].length - 1)
1426
- ]);
1427
-
1428
-
1429
-
1430
-
1431
-
1432
-
1433
- // 3D effect
1434
- if (prop['chart.variant'] === '3d') {
1435
-
1436
- /**
1437
- * Turn off the shadow for the 3D bits
1438
- */
1439
- RG.noShadow(this);
1440
-
1441
- var prevStrokeStyle = co.strokeStyle,
1442
- prevFillStyle = co.fillStyle;
1443
-
1444
- // DRAW THE 3D BITS HERE
1445
- var barX = x,
1446
- barY = y + vmargin,
1447
- barW = width,
1448
- barH = height - (2 * vmargin),
1449
- offsetX = prop['chart.variant.threed.offsetx'],
1450
- offsetY = prop['chart.variant.threed.offsety'],
1451
- value = this.data[i][j];
1452
-
1453
- if (!RG.isNull(value)) {
1454
- pa2(
1455
- co,
1456
- [
1457
- 'b',
1458
- 'm', barX, barY,
1459
- 'l', barX + offsetX, barY - offsetY,
1460
- 'l', barX + barW + offsetX, barY - offsetY,
1461
- 'l', barX + barW, barY,
1462
- 'c',
1463
- 's', co.strokeStyle,
1464
- 'f', co.fillStyle,
1465
- 'f','rgba(255,255,255,0.6)'//Fill again to lighten it
1466
- ]
1467
- );
1468
- }
1469
-
1470
- if ( prop['chart.yaxispos'] !== 'right'
1471
- && !(prop['chart.yaxispos'] === 'center' && value < 0)
1472
- && !RG.isNull(value)
1473
- ) {
1474
-
1475
- pa2(
1476
- co,
1477
- [
1478
- 'fs', prevFillStyle,
1479
- 'b',
1480
- 'm', barX + barW, barY,
1481
- 'l', barX + barW + offsetX, barY - offsetY,
1482
- 'l', barX + barW + offsetX, barY - offsetY + barH,
1483
- 'l', barX + barW, barY + barH,
1484
- 'c',
1485
- 's', co.strokeStyle,
1486
- 'f', prevFillStyle,
1487
- 'f', 'rgba(0,0,0,0.25)'
1488
- ]
1489
- );
1490
- }
1491
-
1492
- co.beginPath();
1493
- co.strokeStyle = prevStrokeStyle;
1494
- co.fillStyle = prevFillStyle;
1495
- }
1496
-
1497
-
1498
-
1499
-
1500
-
1501
-
1502
- if (prop['chart.yaxispos'] !== 'right') {
1503
- x += width;
1504
- }
1505
- }
1506
-
1507
-
1508
-
1509
-
1510
-
1511
-
1512
-
1513
-
1514
- /**
1515
- * A grouped bar chart
1516
- */
1517
- } else if (typeof(this.data[i]) == 'object' && prop['chart.grouping'] == 'grouped') {
1518
-
1519
- var vmarginGrouped = prop['chart.vmargin.grouped'];
1520
- var individualBarHeight = ((height - (2 * vmargin) - ((this.data[i].length - 1) * vmarginGrouped)) / this.data[i].length)
1521
-
1522
- if (typeof this.coords2[i] == 'undefined') {
1523
- this.coords2[i] = [];
1524
- }
1525
-
1526
- for (j=(this.data[i].length - 1); j>=0; --j) {
1527
-
1528
- /**
1529
- * Turn on the shadow if need be
1530
- */
1531
- if (prop['chart.shadow']) {
1532
- RG.setShadow(this, prop['chart.shadow.color'], prop['chart.shadow.offsetx'], prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
1533
- }
1534
-
1535
- // Set the fill/stroke colors
1536
- co.strokeStyle = prop['chart.strokestyle'];
1537
-
1538
- // Sequential colors
1539
- ++colorIdx;
1540
- if (prop['chart.colors.sequential'] && typeof colorIdx === 'number') {
1541
- if (prop['chart.colors'][this.numbars - colorIdx]) {
1542
- co.fillStyle = prop['chart.colors'][this.numbars - colorIdx];
1543
- } else {
1544
- co.fillStyle = prop['chart.colors'][prop['chart.colors'].length - 1];
1545
- }
1546
- } else if (prop['chart.colors'][j]) {
1547
- co.fillStyle = prop['chart.colors'][j];
1548
- }
1549
-
1550
-
1551
-
1552
- var startY = this.gutterTop + (height * i) + (individualBarHeight * j) + vmargin + (vmarginGrouped * j);
1553
- var width = ((this.data[i][j] - prop['chart.xmin']) / (this.max - prop['chart.xmin'])) * (ca.width - this.gutterLeft - this.gutterRight );
1554
- var startX = this.gutterLeft;
1555
-
1556
-
1557
-
1558
- // Account for the Y axis being in the middle
1559
- if (prop['chart.yaxispos'] == 'center') {
1560
- width /= 2;
1561
- startX += halfwidth;
1562
-
1563
- // Account for the Y axis being on the right
1564
- } else if (prop['chart.yaxispos'] == 'right') {
1565
- width = ma.abs(width);
1566
- startX = ca.width - this.gutterRight - ma.abs(width);;
1567
- }
1568
-
1569
- if (width < 0) {
1570
- startX += width;
1571
- width *= -1;
1572
- }
1573
-
1574
- co.strokeRect(startX, startY, width, individualBarHeight);
1575
- co.fillRect(startX, startY, width, individualBarHeight);
1576
-
1577
-
1578
-
1579
-
1580
-
1581
-
1582
- this.coords.push([
1583
- startX,
1584
- startY,
1585
- width,
1586
- individualBarHeight,
1587
- co.fillStyle,
1588
- this.data[i][j],
1589
- true
1590
- ]);
1591
-
1592
- this.coords2[i].push([
1593
- startX,
1594
- startY,
1595
- width,
1596
- individualBarHeight,
1597
- co.fillStyle,
1598
- this.data[i][j],
1599
- true
1600
- ]);
1601
-
1602
-
1603
-
1604
-
1605
-
1606
-
1607
-
1608
-
1609
-
1610
-
1611
-
1612
-
1613
- // 3D effect
1614
- if (prop['chart.variant'] === '3d') {
1615
-
1616
- /**
1617
- * Turn off the shadow for the 3D bits
1618
- */
1619
- RG.noShadow(this);
1620
-
1621
- var prevStrokeStyle = co.strokeStyle,
1622
- prevFillStyle = co.fillStyle;
1623
-
1624
- // DRAW THE 3D BITS HERE
1625
- var barX = startX,
1626
- barY = startY,
1627
- barW = width,
1628
- barH = individualBarHeight,
1629
- offsetX = prop['chart.variant.threed.offsetx'],
1630
- offsetY = prop['chart.variant.threed.offsety'],
1631
- value = this.data[i][j];
1632
-
1633
- pa2(
1634
- co,
1635
- [
1636
- 'b',
1637
- 'm', barX, barY,
1638
- 'l', barX + offsetX, barY - offsetY,
1639
- 'l', barX + barW + offsetX - (value < 0 ? offsetX : 0), barY - offsetY,
1640
- 'l', barX + barW, barY,
1641
- 'c',
1642
- 's', co.strokeStyle,
1643
- 'f', co.fillStyle,
1644
- 'f','rgba(255,255,255,0.6)'//Fill again to lighten it
1645
- ]
1646
- );
1647
-
1648
- if ( prop['chart.yaxispos'] !== 'right'
1649
- && !(prop['chart.yaxispos'] === 'center' && value < 0)
1650
- && value >= 0
1651
- && !RG.isNull(value)
1652
- ) {
1653
-
1654
- pa2(
1655
- co,
1656
- [
1657
- 'fs', prevFillStyle,
1658
- 'b',
1659
- 'm', barX + barW, barY,
1660
- 'l', barX + barW + offsetX, barY - offsetY,
1661
- 'l', barX + barW + offsetX, barY - offsetY + barH,
1662
- 'l', barX + barW, barY + barH,
1663
- 'c',
1664
- 's', co.strokeStyle,
1665
- 'f', prevFillStyle,
1666
- 'f', 'rgba(0,0,0,0.25)'
1667
- ]
1668
- );
1669
- }
1670
-
1671
-
1672
-
1673
-
1674
-
1675
- co.beginPath();
1676
- co.strokeStyle = prevStrokeStyle;
1677
- co.fillStyle = prevFillStyle;
1678
- }
1679
-
1680
-
1681
-
1682
-
1683
-
1684
-
1685
- }
1686
-
1687
- startY += vmargin;
1688
- }
1689
-
1690
- co.closePath();
1691
- }
1692
-
1693
- co.stroke();
1694
- co.fill();
1695
-
1696
- // Under certain circumstances we can cover the shadow
1697
- // overspill with a white rectangle
1698
- if (prop['chart,yaxispos'] === 'right') {
1699
- pa2(co, 'cr % % % %',
1700
- ca.width - this.gutterRight + prop['chart.variant.threed.offsetx'],
1701
- '0',
1702
- this.gutterRight,
1703
- ca.height
1704
- );
1705
- }
1706
-
1707
-
1708
-
1709
-
1710
-
1711
-
1712
- // Draw the 3d axes AGAIN if the Y axis is on the right
1713
- if ( prop['chart.yaxispos'] === 'right'
1714
- && prop['chart.variant'] === '3d'
1715
- ) {
1716
- RG.draw3DYAxis(this);
1717
- }
1718
-
1719
- /**
1720
- * Now the bars are stroke()ed, turn off the shadow
1721
- */
1722
- RG.noShadow(this);
1723
-
1724
-
1725
- //
1726
- // Reverse the coords arrays as the bars are drawn from the borrom up now
1727
- //
1728
- this.coords = RG.arrayReverse(this.coords);
1729
-
1730
- if (prop['chart.grouping'] === 'grouped') {
1731
- for (var i=0; i<this.coords2.length; ++i) {
1732
- this.coords2[i] = RG.arrayReverse(this.coords2[i]);
1733
- }
1734
- }
1735
-
1736
-
1737
- this.redrawBars();
1738
- };
1739
-
1740
-
1741
-
1742
-
1743
- /**
1744
- * This function goes over the bars after they been drawn, so that upwards shadows are underneath the bars
1745
- */
1746
- this.redrawBars =
1747
- this.RedrawBars = function ()
1748
- {
1749
- if (prop['chart.noredraw']) {
1750
- return;
1751
- }
1752
-
1753
- var coords = this.coords;
1754
-
1755
- var font = prop['chart.text.font'],
1756
- size = prop['chart.text.size'],
1757
- color = prop['chart.text.color'];
1758
-
1759
- RG.noShadow(this);
1760
- co.strokeStyle = prop['chart.strokestyle'];
1761
-
1762
- for (var i=0; i<coords.length; ++i) {
1763
-
1764
- if (prop['chart.shadow']) {
1765
-
1766
- pa2(co, 'b lw % r % % % % s % f %',
1767
- prop['chart.linewidth'],
1768
- coords[i][0],
1769
- coords[i][1],
1770
- coords[i][2],
1771
- coords[i][3],
1772
- prop['chart.strokestyle'],
1773
- coords[i][4]
1774
- );
1775
- }
1776
-
1777
- /**
1778
- * Draw labels "above" the bar
1779
- */
1780
- var halign = 'left';
1781
- if (prop['chart.labels.above'] && coords[i][6]) {
1782
-
1783
- var border = (coords[i][0] + coords[i][2] + 7 + co.measureText(prop['chart.labels.above.units.pre'] + this.coords[i][5] + prop['chart.labels.above.units.post']).width) > ca.width ? true : false,
1784
- text = RG.numberFormat(this, (this.coords[i][5]).toFixed(prop['chart.labels.above.decimals']), prop['chart.labels.above.units.pre'], prop['chart.labels.above.units.post']);
1785
-
1786
- RG.noShadow(this);
1787
-
1788
- /**
1789
- * Default to the value - then check for specific labels
1790
- */
1791
-
1792
-
1793
- if (typeof prop['chart.labels.above.specific'] === 'object' && prop['chart.labels.above.specific'] && prop['chart.labels.above.specific'][i]) {
1794
- text = prop['chart.labels.above.specific'][i];
1795
- }
1796
-
1797
- var x = coords[i][0] + coords[i][2] + 5;
1798
- var y = coords[i][1] + (coords[i][3] / 2);
1799
-
1800
- if (prop['chart.yaxispos'] === 'right') {
1801
- x = coords[i][0] - 5;
1802
- halign = 'right';
1803
- } else if (prop['chart.yaxispos'] === 'center' && this.data_arr[i] < 0) {
1804
- x = coords[i][0] - 5;
1805
- halign = 'right';
1806
- }
1807
-
1808
- RG.text2(this, {
1809
- font: typeof prop['chart.labels.above.font'] === 'string' ? prop['chart.labels.above.font'] : font,
1810
- size: typeof prop['chart.labels.above.size'] === 'number' ? prop['chart.labels.above.size'] : size,
1811
- color: typeof prop['chart.labels.above.color'] ==='string' ? prop['chart.labels.above.color'] : color,
1812
- x: x,
1813
- y: y,
1814
- bold: prop['chart.labels.above.bold'],
1815
- italic: prop['chart.labels.above.italic'],
1816
- text: text,
1817
- valign: 'center',
1818
- halign: halign,
1819
- tag: 'labels.above'
1820
- });
1821
- }
1822
- }
1823
- };
1824
-
1825
-
1826
-
1827
-
1828
- /**
1829
- * This function can be used to get the appropriate bar information (if any)
1830
- *
1831
- * @param e Event object
1832
- * @return Appriate bar information (if any)
1833
- */
1834
- this.getShape =
1835
- this.getBar = function (e)
1836
- {
1837
- var mouseXY = RG.getMouseXY(e);
1838
-
1839
- /**
1840
- * Loop through the bars determining if the mouse is over a bar
1841
- */
1842
- for (var i=0,len=this.coords.length; i<len; i++) {
1843
-
1844
- var mouseX = mouseXY[0], // In relation to the canvas
1845
- mouseY = mouseXY[1], // In relation to the canvas
1846
- left = this.coords[i][0],
1847
- top = this.coords[i][1],
1848
- width = this.coords[i][2],
1849
- height = this.coords[i][3],
1850
- idx = i;
1851
-
1852
-
1853
-
1854
- // Recreate the path/rectangle so that it can be tested
1855
- // ** DO NOT STROKE OR FILL IT **
1856
- pa2(co,['b','r',left,top,width,height]);
1857
-
1858
- if (co.isPointInPath(mouseX, mouseY)) {
1859
-
1860
- var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i);
1861
-
1862
- return {
1863
- 0: this, 'object': this,
1864
- 1: left, 'x': left,
1865
- 2: top, 'y': top,
1866
- 3: width, 'width': width,
1867
- 4: height, 'height': height,
1868
- 5: idx, 'index': idx,
1869
- 'tooltip': tooltip
1870
- };
1871
- }
1872
- }
1873
- };
1874
-
1875
-
1876
-
1877
-
1878
- /**
1879
- * When you click on the chart, this method can return the X value at that point. It works for any point on the
1880
- * chart (that is inside the gutters) - not just points within the Bars.
1881
- *
1882
- * @param object e The event object
1883
- */
1884
- this.getValue = function (arg)
1885
- {
1886
- if (arg.length == 2) {
1887
- var mouseX = arg[0];
1888
- var mouseY = arg[1];
1889
- } else {
1890
- var mouseCoords = RG.getMouseXY(arg);
1891
- var mouseX = mouseCoords[0];
1892
- var mouseY = mouseCoords[1];
1893
- }
1894
-
1895
- if ( mouseY < this.gutterTop
1896
- || mouseY > (ca.height - this.gutterBottom)
1897
- || mouseX < this.gutterLeft
1898
- || mouseX > (ca.width - this.gutterRight)
1899
- ) {
1900
- return null;
1901
- }
1902
-
1903
-
1904
-
1905
-
1906
-
1907
- if (prop['chart.yaxispos'] == 'center') {
1908
- var value = ((mouseX - this.gutterLeft) / (this.graphwidth / 2)) * (this.max - prop['chart.xmin']);
1909
- value = value - this.max
1910
-
1911
- // Special case if xmin is defined
1912
- if (prop['chart.xmin'] > 0) {
1913
- value = ((mouseX - this.gutterLeft - (this.graphwidth / 2)) / (this.graphwidth / 2)) * (this.max - prop['chart.xmin']);
1914
- value += prop['chart.xmin'];
1915
-
1916
- if (mouseX < (this.gutterLeft + (this.graphwidth / 2))) {
1917
- value -= (2 * prop['chart.xmin']);
1918
- }
1919
- }
1920
-
1921
-
1922
- // TODO This needs fixing
1923
- } else if (prop['chart.yaxispos'] == 'right') {
1924
- var value = ((mouseX - this.gutterLeft) / this.graphwidth) * (this.scale2.max - prop['chart.xmin']);
1925
- value = this.scale2.max - value;
1926
-
1927
- } else {
1928
- var value = ((mouseX - this.gutterLeft) / this.graphwidth) * (this.scale2.max - prop['chart.xmin']);
1929
- value += prop['chart.xmin'];
1930
- }
1931
-
1932
-
1933
-
1934
-
1935
-
1936
-
1937
- return value;
1938
- };
1939
-
1940
-
1941
-
1942
-
1943
- /**
1944
- * Each object type has its own Highlight() function which highlights the appropriate shape
1945
- *
1946
- * @param object shape The shape to highlight
1947
- */
1948
- this.highlight =
1949
- this.Highlight = function (shape)
1950
- {
1951
- if (typeof prop['chart.highlight.style'] === 'function') {
1952
- (prop['chart.highlight.style'])(shape);
1953
- } else {
1954
- RG.Highlight.Rect(this, shape);
1955
- }
1956
- };
1957
-
1958
-
1959
-
1960
-
1961
- /**
1962
- * The getObjectByXY() worker method. Don't call this call:
1963
- *
1964
- * RG.ObjectRegistry.getObjectByXY(e)
1965
- *
1966
- * @param object e The event object
1967
- */
1968
- this.getObjectByXY = function (e)
1969
- {
1970
- var mouseXY = RG.getMouseXY(e);
1971
-
1972
- // Adjust the mouse Y coordinate for when the bar chart is
1973
- // a 3D variant
1974
- if (prop['chart.variant'] === '3d') {
1975
- var adjustment = prop['chart.variant.threed.angle'] * mouseXY[0];
1976
- mouseXY[1] -= adjustment;
1977
- }
1978
-
1979
-
1980
- if (
1981
- mouseXY[0] >= this.gutterLeft
1982
- && mouseXY[0] <= (ca.width - this.gutterRight)
1983
- && mouseXY[1] >= this.gutterTop
1984
- && mouseXY[1] <= (ca.height - this.gutterBottom)
1985
- ) {
1986
-
1987
- return this;
1988
- }
1989
- };
1990
-
1991
-
1992
-
1993
-
1994
- /**
1995
- * This function positions a tooltip when it is displayed
1996
- *
1997
- * @param obj object The chart object
1998
- * @param int x The X coordinate specified for the tooltip
1999
- * @param int y The Y coordinate specified for the tooltip
2000
- * @param objec tooltip The tooltips DIV element
2001
- *
2002
- this.positionTooltip = function (obj, x, y, tooltip, idx)
2003
- {
2004
- var coordX = obj.coords[tooltip.__index__][0],
2005
- coordY = obj.coords[tooltip.__index__][1],
2006
- coordW = obj.coords[tooltip.__index__][2],
2007
- coordH = obj.coords[tooltip.__index__][3],
2008
- canvasXY = RG.getCanvasXY(obj.canvas),
2009
- gutterLeft = obj.gutterLeft,
2010
- gutterTop = obj.gutterTop,
2011
- width = tooltip.offsetWidth,
2012
- height = tooltip.offsetHeight,
2013
- mouseXY = RG.getMouseXY(window.event);
2014
-
2015
- // If the chart is a 3D version the tooltip Y position needs this
2016
- // adjustment
2017
- if (prop['chart.variant'] === '3d' && coordW) {
2018
- var adjustment = (prop['chart.variant.threed.angle'] * ((coordX + coordW) / 2));
2019
- }
2020
-
2021
-
2022
-
2023
- // Set the top position
2024
- tooltip.style.left = 0;
2025
- tooltip.style.top = window.event.pageY - height - 5 + 'px';
2026
-
2027
- // By default any overflow is hidden
2028
- tooltip.style.overflow = '';
2029
-
2030
- // Reposition the tooltip if at the edges:
2031
-
2032
- // LEFT edge
2033
- if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
2034
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
2035
-
2036
- // RIGHT edge
2037
- } else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
2038
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
2039
-
2040
- // Default positioning - CENTERED
2041
- } else {
2042
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
2043
- }
2044
- };*/
2045
-
2046
-
2047
-
2048
-
2049
- /**
2050
- * Returns the appropriate Y coord for the given value
2051
- *
2052
- * @param number value The value to get the coord for
2053
- */
2054
- this.getXCoord = function (value)
2055
- {
2056
-
2057
- if (prop['chart.yaxispos'] == 'center') {
2058
-
2059
- // Range checking
2060
- if (value > this.max || value < (-1 * this.max)) {
2061
- return null;
2062
- }
2063
-
2064
- var width = (ca.width - prop['chart.gutter.left'] - prop['chart.gutter.right']) / 2;
2065
- var coord = (((value - prop['chart.xmin']) / (this.max - prop['chart.xmin'])) * width) + width;
2066
-
2067
- coord = prop['chart.gutter.left'] + coord;
2068
- } else {
2069
-
2070
- // Range checking
2071
- if (value > this.max || value < 0) {
2072
- return null;
2073
- }
2074
-
2075
- var width = ca.width - prop['chart.gutter.left'] - prop['chart.gutter.right'];
2076
- var coord = ((value - prop['chart.xmin']) / (this.max - prop['chart.xmin'])) * width;
2077
-
2078
- coord = prop['chart.gutter.left'] + coord;
2079
- }
2080
-
2081
- return coord;
2082
- };
2083
-
2084
-
2085
-
2086
-
2087
- /**
2088
- *
2089
- */
2090
- this.parseColors = function ()
2091
- {
2092
- // Save the original colors so that they can be restored when the canvas is reset
2093
- if (this.original_colors.length === 0) {
2094
- //this.original_colors['chart.'] = RG.array_clone(prop['chart.']);
2095
- this.original_colors['chart.colors'] = RG.array_clone(prop['chart.colors']);
2096
- this.original_colors['chart.background.grid.color'] = RG.array_clone(prop['chart.background.grid.color']);
2097
- this.original_colors['chart.background.color'] = RG.array_clone(prop['chart.background.color']);
2098
- this.original_colors['chart.background.barcolor1'] = RG.array_clone(prop['chart.background.barcolor1']);
2099
- this.original_colors['chart.background.barcolor2'] = RG.array_clone(prop['chart.background.barcolor2']);
2100
- this.original_colors['chart.text.color'] = RG.array_clone(prop['chart.text.color']);
2101
- this.original_colors['chart.labels.colors'] = RG.array_clone(prop['chart.labels.colors']);
2102
- this.original_colors['chart.strokestyle'] = RG.array_clone(prop['chart.strokestyle']);
2103
- this.original_colors['chart.axis.color'] = RG.array_clone(prop['chart.axis.color']);
2104
- this.original_colors['chart.highlight.fill'] = RG.array_clone(prop['chart.highlight.fill']);
2105
- this.original_colors['chart.highlight.stroke'] = RG.array_clone(prop['chart.highlight.stroke']);
2106
-
2107
- }
2108
-
2109
- var colors = prop['chart.colors'];
2110
-
2111
- for (var i=0; i<colors.length; ++i) {
2112
- colors[i] = this.parseSingleColorForGradient(colors[i]);
2113
- }
2114
-
2115
- prop['chart.background.grid.color'] = this.parseSingleColorForGradient(prop['chart.background.grid.color']);
2116
- prop['chart.background.color'] = this.parseSingleColorForGradient(prop['chart.background.color']);
2117
- prop['chart.background.barcolor1'] = this.parseSingleColorForGradient(prop['chart.background.barcolor1']);
2118
- prop['chart.background.barcolor2'] = this.parseSingleColorForGradient(prop['chart.background.barcolor2']);
2119
- prop['chart.text.color'] = this.parseSingleColorForGradient(prop['chart.text.color']);
2120
- prop['chart.labels.colors'] = this.parseSingleColorForGradient(prop['chart.labels.colors']);
2121
- prop['chart.strokestyle'] = this.parseSingleColorForGradient(prop['chart.strokestyle']);
2122
- prop['chart.axis.color'] = this.parseSingleColorForGradient(prop['chart.axis.color']);
2123
- prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
2124
- prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
2125
- };
2126
-
2127
-
2128
-
2129
-
2130
- /**
2131
- * Use this function to reset the object to the post-constructor state. Eg reset colors if
2132
- * need be etc
2133
- */
2134
- this.reset = function ()
2135
- {
2136
- };
2137
-
2138
-
2139
-
2140
- /**
2141
- * This parses a single color value
2142
- */
2143
- this.parseSingleColorForGradient = function (color)
2144
- {
2145
- if (!color || typeof(color) != 'string') {
2146
- return color;
2147
- }
2148
-
2149
- if (color.match(/^gradient\((.*)\)$/i)) {
2150
-
2151
- var parts = RegExp.$1.split(':');
2152
-
2153
- if (prop['chart.yaxispos'] === 'right') {
2154
- parts = RG.arrayReverse(parts);
2155
- }
2156
-
2157
- // Create the gradient
2158
- var grad = co.createLinearGradient(prop['chart.gutter.left'],0,ca.width - prop['chart.gutter.right'],0);
2159
-
2160
- var diff = 1 / (parts.length - 1);
2161
-
2162
- grad.addColorStop(0, RG.trim(parts[0]));
2163
-
2164
- for (var j=1; j<parts.length; ++j) {
2165
- grad.addColorStop(j * diff, RG.trim(parts[j]));
2166
- }
2167
- }
2168
-
2169
- return grad ? grad : color;
2170
- };
2171
-
2172
-
2173
-
2174
-
2175
- /**
2176
- * This function handles highlighting an entire data-series for the interactive
2177
- * key
2178
- *
2179
- * @param int index The index of the data series to be highlighted
2180
- */
2181
- this.interactiveKeyHighlight = function (index)
2182
- {
2183
- var obj = this;
2184
-
2185
- this.coords2.forEach(function (value, idx, arr)
2186
- {
2187
- var shape = obj.coords2[idx][index]
2188
- var pre_linewidth = co.lineWidth;
2189
- co.lineWidth = 2;
2190
- co.fillStyle = prop['chart.key.interactive.highlight.chart.fill'];
2191
- co.strokeStyle = prop['chart.key.interactive.highlight.chart.stroke'];
2192
- co.fillRect(shape[0], shape[1], shape[2], shape[3]);
2193
- co.strokeRect(shape[0], shape[1], shape[2], shape[3]);
2194
-
2195
- // Reset the lineWidth
2196
- co.lineWidth = pre_linewidth;
2197
- });
2198
- };
2199
-
2200
-
2201
-
2202
-
2203
- /**
2204
- * Using a function to add events makes it easier to facilitate method chaining
2205
- *
2206
- * @param string type The type of even to add
2207
- * @param function func
2208
- */
2209
- this.on = function (type, func)
2210
- {
2211
- if (type.substr(0,2) !== 'on') {
2212
- type = 'on' + type;
2213
- }
2214
-
2215
- if (typeof this[type] !== 'function') {
2216
- this[type] = func;
2217
- } else {
2218
- RG.addCustomEventListener(this, type, func);
2219
- }
2220
-
2221
- return this;
2222
- };
2223
-
2224
-
2225
-
2226
-
2227
- /**
2228
- * This function runs once only
2229
- * (put at the end of the file (before any effects))
2230
- */
2231
- this.firstDrawFunc = function ()
2232
- {
2233
- };
2234
-
2235
-
2236
-
2237
-
2238
- /**
2239
- * This retrives the bar based on the X coordinate only.
2240
- *
2241
- * @param object e The event object
2242
- * @param object OPTIONAL You can pass in the bar object instead of the
2243
- * function using "this"
2244
- */
2245
- this.getShapeByY = function (e)
2246
- {
2247
- var mouseXY = RG.getMouseXY(e);
2248
-
2249
-
2250
- // This facilitates you being able to pass in the bar object as a parameter instead of
2251
- // the function getting it from itself
2252
- var obj = arguments[1] ? arguments[1] : this;
2253
-
2254
-
2255
- /**
2256
- * Loop through the bars determining if the mouse is over a bar
2257
- */
2258
- for (var i=0,len=obj.coords.length; i<len; i++) {
2259
-
2260
- if (obj.coords[i].length == 0) {
2261
- continue;
2262
- }
2263
-
2264
- var mouseX = mouseXY[0],
2265
- mouseY = mouseXY[1],
2266
- left = obj.coords[i][0],
2267
- top = obj.coords[i][1],
2268
- width = obj.coords[i][2],
2269
- height = obj.coords[i][3];
2270
-
2271
- if (mouseY >= top && mouseY <= (top + height)) {
2272
-
2273
- if (prop['chart.tooltips']) {
2274
- var tooltip = RG.parseTooltipText ? RG.parseTooltipText(prop['chart.tooltips'], i) : prop['chart.tooltips'][i];
2275
- }
2276
-
2277
- return {
2278
- 0: obj, object: obj,
2279
- 1: left, x: left,
2280
- 2: top, y: top,
2281
- 3: width, width: width,
2282
- 4: height, height: height,
2283
- 5: i, index: i,
2284
- tooltip: tooltip
2285
- };
2286
- }
2287
- }
2288
-
2289
- return null;
2290
- };
2291
-
2292
-
2293
-
2294
-
2295
- /**
2296
- * This method handles the adjusting calculation for when the mouse is moved
2297
- *
2298
- * @param object e The event object
2299
- */
2300
- this.adjusting_mousemove =
2301
- this.Adjusting_mousemove = function (e)
2302
- {
2303
- /**
2304
- * Handle adjusting for the Bar
2305
- */
2306
- if (prop['chart.adjustable'] && RG.Registry.get('chart.adjusting') && RG.Registry.get('chart.adjusting').uid == this.uid) {
2307
-
2308
- // Rounding the value to the given number of decimals make the chart step
2309
- var value = Number(this.getValue(e)),
2310
- shape = RG.Registry.get('chart.adjusting.shape');
2311
-
2312
- if (shape) {
2313
-
2314
- RG.Registry.Set('chart.adjusting.shape', shape);
2315
-
2316
- if (this.stackedOrGrouped && prop['chart.grouping'] == 'grouped') {
2317
-
2318
- var indexes = RG.sequentialIndexToGrouped(shape['index'], this.data);
2319
-
2320
- if (typeof this.data[indexes[0]] == 'number') {
2321
- this.data[indexes[0]] = Number(value);
2322
- } else if (!RG.is_null(this.data[indexes[0]])) {
2323
- this.data[indexes[0]][indexes[1]] = Number(value);
2324
- }
2325
- } else if (typeof this.data[shape['index']] == 'number') {
2326
-
2327
- this.data[shape['index']] = Number(value);
2328
- }
2329
-
2330
- RG.redrawCanvas(e.target);
2331
- RG.fireCustomEvent(this, 'onadjust');
2332
- }
2333
- }
2334
- };
2335
-
2336
-
2337
-
2338
-
2339
- /**
2340
- * Grow
2341
- *
2342
- * The HBar chart Grow effect gradually increases the values of the bars
2343
- *
2344
- * @param object OPTIONAL Options for the effect. You can pass frames here
2345
- * @param function OPTIONAL A callback function
2346
- */
2347
- this.grow = function ()
2348
- {
2349
- var obj = this,
2350
- opt = arguments[0] || {},
2351
- frames = opt.frames || 30,
2352
- frame = 0,
2353
- callback = arguments[1] || function () {},
2354
- labelsAbove = prop['chart.labels.above'];
2355
-
2356
- this.set('labelsAbove', false);
2357
-
2358
-
2359
- // Save the data
2360
- obj.original_data = RG.arrayClone(obj.data);
2361
-
2362
-
2363
- // Stop the scale from changing by setting chart.xmax (if it's not already set)
2364
- if (prop['chart.xmax'] == 0) {
2365
-
2366
- var xmax = 0;
2367
-
2368
- for (var i=0; i<obj.data.length; ++i) {
2369
- if (RG.isArray(obj.data[i]) && prop['chart.grouping'] == 'stacked') {
2370
- xmax = ma.max(xmax, RG.arraySum(obj.data[i]));
2371
- } else if (RG.isArray(obj.data[i]) && prop['chart.grouping'] == 'grouped') {
2372
- xmax = ma.max(xmax, RG.arrayMax(obj.data[i]));
2373
- } else {
2374
- xmax = ma.max(xmax, ma.abs(RG.arrayMax(obj.data[i])));
2375
- }
2376
- }
2377
-
2378
- var scale2 = RG.getScale2(obj, {'max':xmax});
2379
- obj.Set('chart.xmax', scale2.max);
2380
- }
2381
-
2382
- function iterator ()
2383
- {
2384
- // Alter the Bar chart data depending on the frame
2385
- for (var j=0,len=obj.original_data.length; j<len; ++j) {
2386
-
2387
- // This stops the animation from being completely linear
2388
- var easingFactor = RG.Effects.getEasingMultiplier(frames, frame);
2389
-
2390
- if (typeof obj.data[j] === 'object' && obj.data[j]) {
2391
- for (var k=0,len2=obj.data[j].length; k<len2; ++k) {
2392
- obj.data[j][k] = RG.isNull(obj.data[j][k]) ? null : obj.original_data[j][k] * easingFactor;
2393
- }
2394
- } else {
2395
- obj.data[j] = RG.isNull(obj.data[j]) ? null : obj.original_data[j] * easingFactor;
2396
- }
2397
- }
2398
-
2399
-
2400
-
2401
- RG.redrawCanvas(obj.canvas);
2402
-
2403
- if (frame < frames) {
2404
- frame += 1;
2405
- RG.Effects.updateCanvas(iterator);
2406
- } else {
2407
-
2408
- if (labelsAbove) {
2409
- obj.set('labelsAbove', true);
2410
- RG.redraw();
2411
- }
2412
-
2413
- callback(obj);
2414
- }
2415
- }
2416
-
2417
- iterator();
2418
-
2419
- return this;
2420
- };
2421
-
2422
-
2423
-
2424
-
2425
-
2426
-
2427
-
2428
-
2429
- /**
2430
- * Grow
2431
- *
2432
- * The HBar chart Grow effect gradually increases the values of the bars
2433
- *
2434
- * @param object An object of options - eg: {frames: 30}
2435
- * @param function A function to call when the effect is complete
2436
- */
2437
- this.grow = function ()
2438
- {
2439
- // Callback
2440
- var opt = arguments[0] || {},
2441
- frames = opt.frames || 30,
2442
- frame = 0,
2443
- callback = arguments[1] || function () {},
2444
- obj = this,
2445
- labelsAbove = this.get('labelsAbove')
2446
-
2447
-
2448
-
2449
-
2450
- this.original_data = RG.arrayClone(this.data);
2451
-
2452
-
2453
-
2454
- // Stop the scale from changing by setting chart.xmax (if it's not already set)
2455
- if (prop['chart.xmax'] == 0) {
2456
-
2457
- var xmax = 0;
2458
-
2459
- for (var i=0; i<obj.data.length; ++i) {
2460
- if (RG.isArray(obj.data[i]) && prop['chart.grouping'] == 'stacked') {
2461
- xmax = ma.max(xmax, RG.arraySum(obj.data[i]));
2462
- } else if (RG.isArray(obj.data[i]) && prop['chart.grouping'] == 'grouped') {
2463
- xmax = ma.max(xmax, RG.arrayMax(obj.data[i]));
2464
- } else {
2465
- xmax = ma.max(xmax, ma.abs(RG.arrayMax(obj.data[i])));
2466
- }
2467
- }
2468
-
2469
- var scale2 = RG.getScale2(obj, {'max':xmax});
2470
- obj.Set('chart.xmax', scale2.max);
2471
- }
2472
-
2473
-
2474
- // Go through the data and change string arguments of the format +/-[0-9]
2475
- // to absolute numbers
2476
- if (RG.isArray(opt.data)) {
2477
-
2478
- var xmax = 0;
2479
-
2480
- for (var i=0; i<opt.data.length; ++i) {
2481
- if (typeof opt.data[i] === 'object') {
2482
- for (var j=0; j<opt.data[i].length; ++j) {
2483
- if (typeof opt.data[i][j] === 'string'&& opt.data[i][j].match(/(\+|\-)([0-9]+)/)) {
2484
- if (RegExp.$1 === '+') {
2485
- opt.data[i][j] = this.original_data[i][j] + parseInt(RegExp.$2);
2486
- } else {
2487
- opt.data[i][j] = this.original_data[i][j] - parseInt(RegExp.$2);
2488
- }
2489
- }
2490
-
2491
- xmax = ma.max(xmax, opt.data[i][j]);
2492
- }
2493
- } else if (typeof opt.data[i] === 'string' && opt.data[i].match(/(\+|\-)([0-9]+)/)) {
2494
- if (RegExp.$1 === '+') {
2495
- opt.data[i] = this.original_data[i] + parseFloat(RegExp.$2);
2496
- } else {
2497
- opt.data[i] = this.original_data[i] - parseFloat(RegExp.$2);
2498
- }
2499
-
2500
- xmax = ma.max(xmax, opt.data[i]);
2501
- } else {
2502
- xmax = ma.max(xmax, opt.data[i]);
2503
- }
2504
- }
2505
-
2506
-
2507
- var scale = RG.getScale2(this, {'max':xmax});
2508
- if (typeof this.get('chart.xmax') === 'null') {
2509
- this.set('chart.xmax', scale.max);
2510
- }
2511
- }
2512
-
2513
-
2514
-
2515
-
2516
-
2517
-
2518
- //
2519
- // turn off the labelsAbove option whilst animating
2520
- //
2521
- this.set('labelsAbove', false);
2522
-
2523
-
2524
-
2525
-
2526
-
2527
-
2528
- // Stop the scale from changing by setting chart.xmax (if it's not already set)
2529
- if (RG.isNull(prop['chart.xmax'])) {
2530
-
2531
- var xmax = 0;
2532
-
2533
- for (var i=0; i<obj.data.length; ++i) {
2534
- if (RG.isArray(this.data[i]) && prop['chart.grouping'] === 'stacked') {
2535
- xmax = ma.max(xmax, ma.abs(RG.arraySum(this.data[i])));
2536
-
2537
- } else if (RG.isArray(this.data[i]) && prop['chart.grouping'] === 'grouped') {
2538
-
2539
- for (var j=0,group=[]; j<this.data[i].length; j++) {
2540
- group.push(ma.abs(this.data[i][j]));
2541
- }
2542
-
2543
- xmax = ma.max(xmax, ma.abs(RG.arrayMax(group)));
2544
-
2545
- } else {
2546
- xmax = ma.max(xmax, ma.abs(this.data[i]));
2547
- }
2548
- }
2549
-
2550
- var scale = RG.getScale2(this, {'max':xmax});
2551
- this.Set('chart.xmax', scale.max);
2552
- }
2553
-
2554
- // You can give an xmax to the grow function
2555
- if (typeof opt.xmax === 'number') {
2556
- obj.set('xmax', opt.xmax);
2557
- }
2558
-
2559
-
2560
-
2561
- var iterator = function ()
2562
- {
2563
- var easingMultiplier = RG.Effects.getEasingMultiplier(frames, frame);
2564
-
2565
- // Alter the Bar chart data depending on the frame
2566
- for (var j=0,len=obj.original_data.length; j<len; ++j) {
2567
- if (typeof obj.data[j] === 'object' && !RG.isNull(obj.data[j])) {
2568
- for (var k=0,len2=obj.data[j].length; k<len2; ++k) {
2569
- if (obj.firstDraw || !opt.data) {
2570
- obj.data[j][k] = easingMultiplier * obj.original_data[j][k];
2571
- } else if (opt.data && opt.data.length === obj.original_data.length) {
2572
- var diff = opt.data[j][k] - obj.original_data[j][k];
2573
- obj.data[j][k] = (easingMultiplier * diff) + obj.original_data[j][k];
2574
- }
2575
- }
2576
- } else {
2577
-
2578
- if (obj.firstDraw || !opt.data) {
2579
- obj.data[j] = easingMultiplier * obj.original_data[j];
2580
- } else if (opt.data && opt.data.length === obj.original_data.length) {
2581
- var diff = opt.data[j] - obj.original_data[j];
2582
- obj.data[j] = (easingMultiplier * diff) + obj.original_data[j];
2583
- }
2584
- }
2585
- }
2586
-
2587
-
2588
-
2589
-
2590
- //RGraph.clear(obj.canvas);
2591
- RG.redrawCanvas(obj.canvas);
2592
-
2593
-
2594
-
2595
-
2596
- if (frame < frames) {
2597
- frame += 1;
2598
-
2599
- RG.Effects.updateCanvas(iterator);
2600
-
2601
- // Call the callback function
2602
- } else {
2603
-
2604
-
2605
-
2606
-
2607
-
2608
- // Do some housekeeping if new data was specified thats done in
2609
- // the constructor - but needs to be redone because new data
2610
- // has been specified
2611
- if (RG.isArray(opt.data)) {
2612
-
2613
- var linear_data = RG.arrayLinearize(data);
2614
-
2615
- for (var i=0; i<linear_data.length; ++i) {
2616
- if (!obj['$' + i]) {
2617
- obj['$' + i] = {};
2618
- }
2619
- }
2620
- }
2621
-
2622
-
2623
-
2624
- obj.data = data;
2625
- obj.original_data = RG.arrayClone(data);
2626
-
2627
-
2628
-
2629
-
2630
-
2631
- if (labelsAbove) {
2632
- obj.set('labelsAbove', true);
2633
- RG.redraw();
2634
- }
2635
- callback(obj);
2636
- }
2637
- };
2638
-
2639
- iterator();
2640
-
2641
- return this;
2642
- };
2643
-
2644
-
2645
-
2646
-
2647
-
2648
-
2649
-
2650
-
2651
- /**
2652
- * (new) Bar chart Wave effect. This is a rewrite that should be smoother
2653
- * because it just uses a single loop and not setTimeout
2654
- *
2655
- * @param object OPTIONAL An object map of options. You specify 'frames' here to give the number of frames in the effect
2656
- * @param function OPTIONAL A function that will be called when the effect is complete
2657
- */
2658
- this.wave = function ()
2659
- {
2660
- var obj = this,
2661
- opt = arguments[0] || {};
2662
- opt.frames = opt.frames || 60;
2663
- opt.startFrames = [];
2664
- opt.counters = [];
2665
-
2666
- var framesperbar = opt.frames / 3,
2667
- frame = -1,
2668
- callback = arguments[1] || function () {},
2669
- original = RG.arrayClone(obj.data),
2670
- labelsAbove = prop['chart.labels.above'];
2671
-
2672
- this.set('labelsAbove', false);
2673
-
2674
- for (var i=0,len=obj.data.length; i<len; i+=1) {
2675
- opt.startFrames[i] = ((opt.frames / 2) / (obj.data.length - 1)) * i;
2676
-
2677
- if (typeof obj.data[i] === 'object' && obj.data[i]) {
2678
- opt.counters[i] = [];
2679
- for (var j=0; j<obj.data[i].length; j++) {
2680
- opt.counters[i][j] = 0;
2681
- }
2682
- } else {
2683
- opt.counters[i] = 0;
2684
- }
2685
- }
2686
-
2687
- /**
2688
- * This stops the chart from jumping
2689
- */
2690
- obj.draw();
2691
- obj.Set('xmax', obj.scale2.max);
2692
- RG.clear(obj.canvas);
2693
-
2694
- function iterator ()
2695
- {
2696
- ++frame;
2697
-
2698
- for (var i=0,len=obj.data.length; i<len; i+=1) {
2699
- if (frame > opt.startFrames[i]) {
2700
- if (typeof obj.data[i] === 'number') {
2701
-
2702
- obj.data[i] = ma.min(
2703
- ma.abs(original[i]),
2704
- ma.abs(original[i] * ( (opt.counters[i]++) / framesperbar))
2705
- );
2706
-
2707
- // Make the number negative if the original was
2708
- if (original[i] < 0) {
2709
- obj.data[i] *= -1;
2710
- }
2711
- } else if (!RG.isNull(obj.data[i])) {
2712
- for (var j=0,len2=obj.data[i].length; j<len2; j+=1) {
2713
-
2714
- obj.data[i][j] = ma.min(
2715
- ma.abs(original[i][j]),
2716
- ma.abs(original[i][j] * ( (opt.counters[i][j]++) / framesperbar))
2717
- );
2718
-
2719
- // Make the number negative if the original was
2720
- if (original[i][j] < 0) {
2721
- obj.data[i][j] *= -1;
2722
- }
2723
- }
2724
- }
2725
- } else {
2726
- obj.data[i] = typeof obj.data[i] === 'object' && obj.data[i] ? RG.arrayPad([], obj.data[i].length, 0) : (RG.isNull(obj.data[i]) ? null : 0);
2727
- }
2728
- }
2729
-
2730
-
2731
- if (frame >= opt.frames) {
2732
-
2733
- if (labelsAbove) {
2734
- obj.set('labelsAbove', true);
2735
- RG.redrawCanvas(obj.canvas);
2736
- }
2737
-
2738
- callback(obj);
2739
- } else {
2740
- RG.redrawCanvas(obj.canvas);
2741
- RG.Effects.updateCanvas(iterator);
2742
- }
2743
- }
2744
-
2745
- iterator();
2746
-
2747
- return this;
2748
- };
2749
-
2750
-
2751
-
2752
-
2753
- //
2754
- // Determines whether the given shape is adjustable or not
2755
- //
2756
- // @param object The shape that pertains to the relevant bar
2757
- //
2758
- this.isAdjustable = function (shape)
2759
- {
2760
- if (RG.isNull(prop['chart.adjustable.only'])) {
2761
- return true;
2762
- }
2763
-
2764
- if (RG.isArray(prop['chart.adjustable.only']) && prop['chart.adjustable.only'][shape.index]) {
2765
- return true;
2766
- }
2767
-
2768
- return false;
2769
- };
2770
-
2771
-
2772
-
2773
-
2774
- /**
2775
- * Charts are now always registered
2776
- */
2777
- RG.Register(this);
2778
-
2779
-
2780
-
2781
-
2782
- /**
2783
- * This is the 'end' of the constructor so if the first argument
2784
- * contains configuration data - handle that.
2785
- */
2786
- if (parseConfObjectForOptions) {
2787
- RG.parseObjectStyleConfig(this, conf.options);
2788
- }
2789
- };
2
+ RGraph=window.RGraph||{isRGraph:true};RGraph.HBar=function(conf)
3
+ {if(typeof conf==='object'&&typeof conf.data==='object'&&typeof conf.id==='string'){var id=conf.id
4
+ var canvas=document.getElementById(id);var data=conf.data;var parseConfObjectForOptions=true;}else{var id=conf;var canvas=document.getElementById(id);var data=arguments[1];}
5
+ this.id=id;this.canvas=canvas;this.context=this.canvas.getContext?this.canvas.getContext("2d",{alpha:(typeof id==='object'&&id.alpha===false)?false:true}):null;this.canvas.__object__=this;this.data=data;this.type='hbar';this.isRGraph=true;this.uid=RGraph.CreateUID();this.canvas.uid=this.canvas.uid?this.canvas.uid:RGraph.CreateUID();this.colorsParsed=false;this.coords=[];this.coords2=[];this.coordsText=[];this.original_colors=[];this.firstDraw=true;this.max=0;this.stackedOrGrouped=false;this.properties={'chart.gutter.left':75,'chart.gutter.left.autosize':false,'chart.gutter.right':25,'chart.gutter.top':25,'chart.gutter.bottom':25,'chart.background.grid':true,'chart.background.grid.color':'#ddd','chart.background.grid.width':1,'chart.background.grid.hsize':25,'chart.background.grid.vsize':25,'chart.background.barcolor1':'rgba(0,0,0,0)','chart.background.barcolor2':'rgba(0,0,0,0)','chart.background.grid.hlines':true,'chart.background.grid.vlines':true,'chart.background.grid.border':true,'chart.background.grid.autofit':true,'chart.background.grid.autofit.align':true,'chart.background.grid.autofit.numhlines':null,'chart.background.grid.autofit.numvlines':5,'chart.background.grid.dashed':false,'chart.background.grid.dotted':false,'chart.background.color':null,'chart.linewidth':1,'chart.title':'','chart.title.background':null,'chart.title.xaxis':'','chart.title.xaxis.bold':true,'chart.title.xaxis.size':null,'chart.title.xaxis.font':null,'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':0.8,'chart.title.yaxis.x':null,'chart.title.yaxis.y':null,'chart.title.xaxis.x':null,'chart.title.xaxis.y':null,'chart.title.xaxis.color':null,'chart.title.hpos':null,'chart.title.vpos':null,'chart.title.bold':true,'chart.title.font':null,'chart.title.x':null,'chart.title.y':null,'chart.title.halign':null,'chart.title.valign':null,'chart.text.size':12,'chart.text.color':'black','chart.text.font':'Segoe UI, Arial, Verdana, sans-serif','chart.text.angle':0,'chart.text.accessible':true,'chart.text.accessible.overflow':'visible','chart.text.accessible.pointerevents':true,'chart.colors':['red','blue','green','pink','yellow','cyan','navy','gray','black'],'chart.colors.sequential':false,'chart.xlabels.specific':null,'chart.labels':[],'chart.labels.bold':false,'chart.labels.color':null,'chart.labels.above':false,'chart.labels.above.decimals':0,'chart.labels.above.specific':null,'chart.labels.above.color':null,'chart.labels.above.units.pre':'','chart.labels.above.units.post':'','chart.labels.above.font':null,'chart.labels.above.size':null,'chart.labels.above.bold':false,'chart.labels.above.italic':false,'chart.labels.offsetx':0,'chart.labels.offsety':0,'chart.xlabels.offsetx':0,'chart.xlabels.offsety':0,'chart.xlabels':true,'chart.xlabels.count':5,'chart.contextmenu':null,'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':'black','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','chart.units.pre':'','chart.units.post':'','chart.units.ingraph':false,'chart.strokestyle':'rgba(0,0,0,0)','chart.xmin':0,'chart.xmax':0,'chart.axis.color':'black','chart.shadow':false,'chart.shadow.color':'#666','chart.shadow.blur':3,'chart.shadow.offsetx':3,'chart.shadow.offsety':3,'chart.vmargin':2,'chart.vmargin.grouped':2,'chart.grouping':'grouped','chart.tooltips':null,'chart.tooltips.event':'onclick','chart.tooltips.effect':'fade','chart.tooltips.css.class':'RGraph_tooltip','chart.tooltips.highlight':true,'chart.highlight.fill':'rgba(255,255,255,0.7)','chart.highlight.stroke':'rgba(0,0,0,0)','chart.highlight.style':null,'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.zoom.action':'zoom','chart.resizable':false,'chart.resize.handle.adjust':[0,0],'chart.resize.handle.background':null,'chart.scale.point':'.','chart.scale.thousand':',','chart.scale.decimals':null,'chart.scale.zerostart':true,'chart.noredraw':false,'chart.events.click':null,'chart.events.mousemove':null,'chart.noxaxis':false,'chart.noyaxis':false,'chart.noaxes':false,'chart.noxtickmarks':false,'chart.noytickmarks':false,'chart.numyticks':data.length,'chart.numxticks':10,'chart.variant':'hbar','chart.variant.threed.angle':0.1,'chart.variant.threed.offsetx':10,'chart.variant.threed.offsety':5,'chart.variant.threed.xaxis':true,'chart.variant.threed.yaxis':true,'chart.yaxispos':'left','chart.variant':'hbar','chart.clearto':'rgba(0,0,0,0)','chart.adjustable':false,'chart.adjustable.only':null}
6
+ if(!this.canvas){alert('[HBAR] No canvas support');return;}
7
+ for(i=0,len=this.data.length;i<len;++i){if(typeof this.data[i]=='object'&&!RGraph.isNull(this.data[i])){this.stackedOrGrouped=true;for(var j=0,len2=this.data[i].length;j<len2;++j){if(typeof this.data[i][j]==='string'){this.data[i][j]=parseFloat(this.data[i][j]);}}}else if(typeof this.data[i]=='string'){this.data[i]=parseFloat(this.data[i])||0;}else if(typeof this.data[i]==='undefined'){this.data[i]=null;}}
8
+ var linear_data=RGraph.arrayLinearize(data);for(var i=0,len=linear_data.length;i<len;++i){this['$'+i]={};}
9
+ this.data_arr=RGraph.arrayLinearize(this.data);if(!this.canvas.__rgraph_aa_translated__){this.context.translate(0.5,0.5);this.canvas.__rgraph_aa_translated__=true;}
10
+ var RG=RGraph,ca=this.canvas,co=ca.getContext('2d'),prop=this.properties,pa2=RG.path2,win=window,doc=document,ma=Math
11
+ if(RG.Effects&&typeof RG.Effects.decorate==='function'){RG.Effects.decorate(this);}
12
+ this.set=this.Set=function(name)
13
+ {var value=typeof arguments[1]==='undefined'?null:arguments[1];if(arguments.length===1&&typeof name==='object'){RG.parseObjectStyleConfig(this,name);return this;}
14
+ if(name.substr(0,6)!='chart.'){name='chart.'+name;}
15
+ while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
16
+ if(name=='chart.labels.abovebar'){name='chart.labels.above';}
17
+ prop[name]=value;return this;};this.get=this.Get=function(name)
18
+ {if(name.substr(0,6)!='chart.'){name='chart.'+name;}
19
+ while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
20
+ if(name=='chart.labels.abovebar'){name='chart.labels.above';}
21
+ return prop[name];};this.draw=this.Draw=function()
22
+ {RG.fireCustomEvent(this,'onbeforedraw');if(prop['chart.adjustable']&&prop['chart.grouping']==='stacked'){alert('[RGRAPH] The HBar does not support stacked charts with adjusting');}
23
+ if(prop['chart.variant']==='3d'){if(prop['chart.text.accessible']){}else{co.setTransform(1,prop['chart.variant.threed.angle'],0,1,0.5,0.5);}
24
+ if(prop['chart.gutter.bottom']===25){this.set('gutterBottom',80);}}
25
+ if(!this.colorsParsed){this.parseColors();this.colorsParsed=true;}
26
+ if(prop['chart.gutter.left.autosize']){var len=0;var labels=prop['chart.labels'];var font=prop['chart.text.font'];var size=prop['chart.text.size'];for(var i=0;i<labels.length;i+=1){var length=RG.measureText(labels[i],false,font,size)[0]||0
27
+ len=ma.max(len,length);}
28
+ prop['chart.gutter.left']=len+10;}
29
+ 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.coords2=[];this.coordsText=[];this.max=0;if(prop['chart.xmin']>0&&prop['chart.grouping']=='stacked'){alert('[HBAR] Using chart.xmin is not supported with stacked charts, resetting chart.xmin to zero');this.Set('chart.xmin',0);}
30
+ this.graphwidth=ca.width-this.gutterLeft-this.gutterRight;this.graphheight=ca.height-this.gutterTop-this.gutterBottom;this.halfgrapharea=this.grapharea/2;this.halfTextHeight=prop['chart.text.size']/2;this.halfway=ma.round((this.graphwidth/2)+this.gutterLeft)
31
+ RG.Background.draw(this);this.drawbars();this.drawAxes();this.drawLabels();if(prop['chart.key']&&prop['chart.key'].length){RG.DrawKey(this,prop['chart.key'],prop['chart.colors']);}
32
+ if(prop['chart.contextmenu']){RG.ShowContext(this);}
33
+ RG.DrawInGraphLabels(this);if(prop['chart.resizable']){RG.AllowResizing(this);}
34
+ RG.InstallEventListeners(this);if(this.firstDraw){this.firstDraw=false;RG.fireCustomEvent(this,'onfirstdraw');this.firstDrawFunc();}
35
+ RG.FireCustomEvent(this,'ondraw');return this;};this.exec=function(func)
36
+ {func(this);return this;};this.drawAxes=this.DrawAxes=function()
37
+ {var halfway=this.halfway
38
+ co.beginPath();co.lineWidth=prop['chart.axis.linewidth']?prop['chart.axis.linewidth']+0.001:1.001;co.strokeStyle=prop['chart.axis.color'];if(prop['chart.noyaxis']==false&&prop['chart.noaxes']==false){if(prop['chart.yaxispos']=='center'){co.moveTo(halfway,this.gutterTop);co.lineTo(halfway,ca.height-this.gutterBottom);}else if(prop['chart.yaxispos']=='right'){co.moveTo(ca.width-this.gutterRight,this.gutterTop);co.lineTo(ca.width-this.gutterRight,ca.height-this.gutterBottom);}else{co.moveTo(this.gutterLeft,this.gutterTop);co.lineTo(this.gutterLeft,ca.height-this.gutterBottom);}}
39
+ if(prop['chart.noxaxis']==false&&prop['chart.noaxes']==false){co.moveTo(this.gutterLeft+0.001,ca.height-this.gutterBottom+0.001);co.lineTo(ca.width-this.gutterRight+0.001,ca.height-this.gutterBottom+0.001);}
40
+ if(prop['chart.noytickmarks']==false&&prop['chart.noyaxis']==false&&prop['chart.numyticks']>0&&prop['chart.noaxes']==false){var yTickGap=(ca.height-this.gutterTop-this.gutterBottom)/(prop['chart.numyticks']>0?prop['chart.numyticks']:this.data.length);for(y=this.gutterTop;y<(ca.height-this.gutterBottom-1);y+=yTickGap){if(prop['chart.yaxispos']=='center'){co.moveTo(halfway+3,ma.round(y));co.lineTo(halfway-3,ma.round(y));}else if(prop['chart.yaxispos']=='right'){co.moveTo(ca.width-this.gutterRight,ma.round(y));co.lineTo(ca.width-this.gutterRight+3,ma.round(y));}else{co.moveTo(this.gutterLeft,ma.round(y));co.lineTo(this.gutterLeft-3,ma.round(y));}}
41
+ if(prop['chart.noxaxis']==true){if(prop['chart.yaxispos']=='center'){co.moveTo(halfway+3,ma.round(y));co.lineTo(halfway-3,ma.round(y));}else if(prop['chart.yaxispos']=='right'){co.moveTo(ca.width-this.gutterRight,ma.round(y));co.lineTo(ca.width-this.gutterRight+3,ma.round(y));}else{co.moveTo(this.gutterLeft,ma.round(y));co.lineTo(this.gutterLeft-3,ma.round(y));}}}
42
+ if(prop['chart.noxtickmarks']==false&&prop['chart.noxaxis']==false&&prop['chart.numxticks']>0&&prop['chart.noaxes']==false){xTickGap=(ca.width-this.gutterLeft-this.gutterRight)/prop['chart.numxticks'];yStart=ca.height-this.gutterBottom;yEnd=(ca.height-this.gutterBottom)+3;var i=prop['chart.numxticks']
43
+ while(i--){var x=ca.width-this.gutterRight-(i*xTickGap);if(prop['chart.yaxispos']==='right'){x-=xTickGap;}
44
+ co.moveTo(ma.round(x),yStart);co.lineTo(ma.round(x),yEnd);}
45
+ if(prop['chart.yaxispos']==='center'){var i=5;while(i--){var x=this.gutterLeft+(xTickGap*i);co.moveTo(ma.round(x),yStart);co.lineTo(ma.round(x),yEnd);}}
46
+ if(prop['chart.noyaxis']==true){co.moveTo(this.gutterLeft,ma.round(yStart));co.lineTo(this.gutterLeft,ma.round(yEnd));}}
47
+ co.stroke();co.lineWidth=1;};this.drawLabels=this.DrawLabels=function()
48
+ {var units_pre=prop['chart.units.pre'],units_post=prop['chart.units.post'],text_size=prop['chart.text.size'],font=prop['chart.text.font'],offsetx=prop['chart.xlabels.offsetx'],offsety=prop['chart.xlabels.offsety']
49
+ if(prop['chart.units.ingraph']){units_pre='';units_post='';}
50
+ if(prop['chart.xlabels']){if(RG.isArray(prop['chart.xlabels.specific'])){if(prop['chart.yaxispos']=='center'){var halfGraphWidth=this.graphwidth/2;var labels=prop['chart.xlabels.specific'];var interval=(this.graphwidth/2)/(labels.length-1);co.fillStyle=prop['chart.text.color'];for(var i=0;i<labels.length;i+=1){RG.text2(this,{font:font,size:text_size,x:this.gutterLeft+halfGraphWidth+(interval*i)+offsetx,y:ca.height-this.gutterBottom+offsetx,text:labels[i],valign:'top',halign:prop['chart.text.angle']!==0?'right':'center',tag:'scale',angle:-1*prop['chart.text.angle']});}
51
+ for(var i=(labels.length-1);i>0;i-=1){RG.Text2(this,{'font':font,'size':text_size,'x':this.gutterLeft+(interval*(labels.length-i-1))+offsetx,'y':ca.height-this.gutterBottom+offsety,'text':labels[i],'valign':'top','halign':prop['chart.text.angle']!==0?'right':'center','tag':'scale',angle:-1*prop['chart.text.angle']});}}else if(prop['chart.yaxispos']=='right'){var labels=prop['chart.xlabels.specific'];var interval=this.graphwidth/(labels.length-1);co.fillStyle=prop['chart.text.color'];for(var i=0;i<labels.length;i+=1){RG.text2(this,{'font':font,'size':text_size,'x':this.gutterLeft+(interval*i)+offsetx,'y':ca.height-this.gutterBottom+offsety,'text':labels[labels.length-i-1],'valign':'top','halign':prop['chart.text.angle']!==0?'right':'center','tag':'scale',angle:-1*prop['chart.text.angle']});}}else{var labels=prop['chart.xlabels.specific'];var interval=this.graphwidth/(labels.length-1);co.fillStyle=prop['chart.text.color'];for(var i=0;i<labels.length;i+=1){RG.text2(this,{font:font,size:text_size,x:this.gutterLeft+(interval*i)+offsetx,y:ca.height-this.gutterBottom+offsety,text:labels[i],valign:'top',halign:prop['chart.text.angle']!==0?'right':'center',tag:'scale',angle:-1*prop['chart.text.angle']});}}}else{var gap=7;co.beginPath();co.fillStyle=prop['chart.text.color'];if(prop['chart.yaxispos']=='center'){for(var i=0;i<this.scale2.labels.length;++i){RG.text2(this,{font:font,size:text_size,x:this.gutterLeft+(this.graphwidth/2)-((this.graphwidth/2)*((i+1)/this.scale2.labels.length))+offsetx,y:this.gutterTop+this.halfTextHeight+this.graphheight+gap+offsety,text:'-'+this.scale2.labels[i],valign:'center',halign:(typeof prop['chart.text.angle']==='number'&&prop['chart.text.angle']!==0)?'right':'center',tag:'scale',angle:-1*prop['chart.text.angle']});}
52
+ for(var i=0;i<this.scale2.labels.length;++i){RG.text2(this,{font:font,size:text_size,x:this.gutterLeft+((this.graphwidth/2)*((i+1)/this.scale2.labels.length))+(this.graphwidth/2)+offsetx,y:this.gutterTop+this.halfTextHeight+this.graphheight+gap+offsety,text:this.scale2.labels[i],valign:'center',halign:prop['chart.text.angle']!==0?'right':'center',tag:'scale',angle:-1*prop['chart.text.angle']});}}else if(prop['chart.yaxispos']=='right'){for(var i=0,len=this.scale2.labels.length;i<len;++i){RG.Text2(this,{'font':font,'size':text_size,'x':this.gutterLeft+(i*(this.graphwidth/len))+offsetx,'y':this.gutterTop+this.halfTextHeight+this.graphheight+gap+offsety,'text':'-'+this.scale2.labels[len-1-i],'valign':'center','halign':prop['chart.text.angle']!==0?'right':'center','tag':'scale',angle:-1*prop['chart.text.angle']});}}else{for(var i=0,len=this.scale2.labels.length;i<len;++i){RG.Text2(this,{font:font,size:text_size,x:this.gutterLeft+(this.graphwidth*((i+1)/len))+offsetx,y:this.gutterTop+this.halfTextHeight+this.graphheight+gap+offsety,text:this.scale2.labels[i],valign:'center',halign:prop['chart.text.angle']!==0?'right':'center',tag:'scale',angle:-1*prop['chart.text.angle']});}}
53
+ if(prop['chart.xmin']>0||prop['chart.noyaxis']==true||prop['chart.scale.zerostart']||prop['chart.noaxes']){var x=prop['chart.yaxispos']=='center'?this.gutterLeft+(this.graphwidth/2):this.gutterLeft;if(prop['chart.yaxispos']==='right'){var x=ca.width-this.gutterRight;}
54
+ RG.text2(this,{'font':font,'size':text_size,'x':x+offsetx,'y':this.gutterTop+this.halfTextHeight+this.graphheight+gap+offsety,'text':RG.numberFormat(this,prop['chart.xmin'].toFixed(prop['chart.xmin']===0?0:prop['chart.scale.decimals']),units_pre,units_post),'valign':'center',halign:prop['chart.text.angle']!==0?'right':'center','tag':'scale',angle:-1*prop['chart.text.angle']});}
55
+ co.fill();co.stroke();}}
56
+ if(typeof prop['chart.labels']=='object'){var xOffset=prop['chart.variant']==='3d'&&prop['chart.yaxispos']==='right'?15:5,font=prop['chart.text.font'],color=prop['chart.labels.color']||prop['chart.text.color'],bold=prop['chart.labels.bold'],offsetx=prop['chart.labels.offsetx'],offsety=prop['chart.labels.offsety']
57
+ co.fillStyle=color;var barHeight=(ca.height-this.gutterTop-this.gutterBottom)/prop['chart.labels'].length;yTickGap=(ca.height-this.gutterTop-this.gutterBottom)/prop['chart.labels'].length
58
+ if(prop['chart.yaxispos']==='right'){var x=ca.width-this.gutterRight+xOffset;var halign='left'}else{var x=this.gutterLeft-xOffset;var halign='right'}
59
+ var i=0;for(y=this.gutterTop+(yTickGap/2);y<=ca.height-this.gutterBottom;y+=yTickGap){RG.text2(this,{'font':font,'size':prop['chart.text.size'],'bold':bold,'x':x+offsetx,'y':y+offsety,'text':String(prop['chart.labels'][i++]),'halign':halign,'valign':'center','tag':'labels'});}}};this.drawbars=this.Drawbars=function()
60
+ {co.lineWidth=prop['chart.linewidth'];co.strokeStyle=prop['chart.strokestyle'];co.fillStyle=prop['chart.colors'][0];var prevX=0,prevY=0;if(prop['chart.xmax']){this.scale2=RG.getScale2(this,{'max':prop['chart.xmax'],'min':prop['chart.xmin'],'scale.decimals':Number(prop['chart.scale.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.xlabels.count'],'strict':true});this.max=this.scale2.max;}else{var grouping=prop['chart.grouping'];for(i=0;i<this.data.length;++i){if(typeof(this.data[i])=='object'){var value=grouping=='grouped'?Number(RG.array_max(this.data[i],true)):Number(RG.array_sum(this.data[i]));}else{var value=Number(ma.abs(this.data[i]));}
61
+ this.max=ma.max(Math.abs(this.max),Math.abs(value));}
62
+ this.scale2=RG.getScale2(this,{'max':this.max,'min':prop['chart.xmin'],'scale.decimals':Number(prop['chart.scale.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.xlabels.count']});this.max=this.scale2.max;this.min=this.scale2.min;}
63
+ if(prop['chart.scale.decimals']==null&&Number(this.max)==1){this.Set('chart.scale.decimals',1);}
64
+ var colorIdx=0;this.numbars=RG.arrayLinearize(this.data).length;if(prop['chart.adjustable']&&!prop['chart.xmax']){this.set('chart.xmax',this.scale2.max);}
65
+ if(prop['chart.variant']==='3d'){RG.draw3DAxes(this);}
66
+ var graphwidth=(ca.width-this.gutterLeft-this.gutterRight);var halfwidth=graphwidth/2;for(i=(len=this.data.length-1);i>=0;--i){var width=ma.abs((this.data[i]/this.max)*graphwidth);var height=this.graphheight/this.data.length;var orig_height=height;var x=this.gutterLeft;var y=this.gutterTop+(i*height);var vmargin=prop['chart.vmargin'];if(prop['chart.yaxispos']==='right'){x=ca.width-this.gutterRight-ma.abs(width);}
67
+ if(width<0){x-=width;width=ma.abs(width);}
68
+ if(prop['chart.shadow']){co.shadowColor=prop['chart.shadow.color'];co.shadowBlur=prop['chart.shadow.blur'];co.shadowOffsetX=prop['chart.shadow.offsetx'];co.shadowOffsetY=prop['chart.shadow.offsety'];}
69
+ co.beginPath();if(typeof this.data[i]=='number'||RG.isNull(this.data[i])){var barHeight=height-(2*vmargin),barWidth=((this.data[i]-prop['chart.xmin'])/(this.max-prop['chart.xmin']))*this.graphwidth,barX=this.gutterLeft;if(prop['chart.yaxispos']=='center'){barWidth/=2;barX+=halfwidth;if(this.data[i]<0){barWidth=(ma.abs(this.data[i])-prop['chart.xmin'])/(this.max-prop['chart.xmin']);barWidth=barWidth*(this.graphwidth/2);barX=((this.graphwidth/2)+this.gutterLeft)-barWidth;}}else if(prop['chart.yaxispos']=='right'){barWidth=ma.abs(barWidth);barX=ca.width-this.gutterRight-barWidth;}
70
+ co.strokeStyle=prop['chart.strokestyle'];co.fillStyle=prop['chart.colors'][0];++colorIdx;if(prop['chart.colors.sequential']&&typeof colorIdx==='number'){if(prop['chart.colors'][this.numbars-colorIdx]){co.fillStyle=prop['chart.colors'][this.numbars-colorIdx];}else{co.fillStyle=prop['chart.colors'][prop['chart.colors'].length-1];}}
71
+ co.strokeRect(barX,this.gutterTop+(i*height)+prop['chart.vmargin'],barWidth,barHeight);co.fillRect(barX,this.gutterTop+(i*height)+prop['chart.vmargin'],barWidth,barHeight);this.coords.push([barX,y+vmargin,barWidth,height-(2*vmargin),co.fillStyle,this.data[i],true]);if(prop['chart.variant']==='3d'&&typeof this.data[i]=='number'){var prevStrokeStyle=co.strokeStyle,prevFillStyle=co.fillStyle;RG.noShadow(this);var barX=barX,barY=y+vmargin,barW=barWidth,barH=height-(2*vmargin),offsetX=prop['chart.variant.threed.offsetx'],offsetY=prop['chart.variant.threed.offsety'],value=this.data[i];pa2(co,['b','m',barX,barY,'l',barX+offsetX-(prop['chart.yaxispos']=='left'&&value<0?offsetX:0),barY-offsetY,'l',barX+barW+offsetX-(prop['chart.yaxispos']=='center'&&value<0?offsetX:0),barY-offsetY,'l',barX+barW,barY,'c','s',co.strokeStyle,'f',co.fillStyle,'f','rgba(255,255,255,0.6)']);if(prop['chart.yaxispos']!=='right'&&!(prop['chart.yaxispos']==='center'&&value<0)&&value>=0&&!RG.isNull(value)){pa2(co,['b','fs',prevFillStyle,'m',barX+barW,barY,'l',barX+barW+offsetX,barY-offsetY,'l',barX+barW+offsetX,barY-offsetY+barH,'l',barX+barW,barY+barH,'c','s',co.strokeStyle,'f',prevFillStyle,'f','rgba(0,0,0,0.25)']);}}}else if(typeof(this.data[i])=='object'&&prop['chart.grouping']=='stacked'){if(prop['chart.yaxispos']=='center'){alert('[HBAR] You can\'t have a stacked chart with the Y axis in the center, change it to grouped');}else if(prop['chart.yaxispos']=='right'){var x=ca.width-this.gutterRight}
72
+ var barHeight=height-(2*vmargin);if(typeof this.coords2[i]=='undefined'){this.coords2[i]=[];}
73
+ for(j=0;j<this.data[i].length;++j){if(prop['chart.shadow']&&prop['chart.variant']==='3d'){co.shadowColor=prop['chart.shadow.color'];co.shadowBlur=prop['chart.shadow.blur'];co.shadowOffsetX=prop['chart.shadow.offsetx'];co.shadowOffsetY=prop['chart.shadow.offsety'];}
74
+ if(!RG.isNull(this.data[i][j]))this.data[i][j]=ma.abs(this.data[i][j]);var last=(j===(this.data[i].length-1));co.strokeStyle=prop['chart.strokestyle'];++colorIdx;if(prop['chart.colors.sequential']&&typeof colorIdx==='number'){if(prop['chart.colors'][this.numbars-colorIdx]){co.fillStyle=prop['chart.colors'][this.numbars-colorIdx];}else{co.fillStyle=prop['chart.colors'][prop['chart.colors'].length-1];}}else if(prop['chart.colors'][j]){co.fillStyle=prop['chart.colors'][j];}
75
+ var width=(((this.data[i][j])/(this.max)))*this.graphwidth;var totalWidth=(RG.arraySum(this.data[i])/this.max)*this.graphwidth;if(prop['chart.yaxispos']==='right'){x-=width;}
76
+ co.strokeRect(x,this.gutterTop+prop['chart.vmargin']+(this.graphheight/this.data.length)*i,width,height-(2*vmargin));co.fillRect(x,this.gutterTop+prop['chart.vmargin']+(this.graphheight/this.data.length)*i,width,height-(2*vmargin));this.coords.push([x,y+vmargin,width,height-(2*vmargin),co.fillStyle,RG.array_sum(this.data[i]),j==(this.data[i].length-1)]);this.coords2[i].push([x,y+vmargin,width,height-(2*vmargin),co.fillStyle,RG.array_sum(this.data[i]),j==(this.data[i].length-1)]);if(prop['chart.variant']==='3d'){RG.noShadow(this);var prevStrokeStyle=co.strokeStyle,prevFillStyle=co.fillStyle;var barX=x,barY=y+vmargin,barW=width,barH=height-(2*vmargin),offsetX=prop['chart.variant.threed.offsetx'],offsetY=prop['chart.variant.threed.offsety'],value=this.data[i][j];if(!RG.isNull(value)){pa2(co,['b','m',barX,barY,'l',barX+offsetX,barY-offsetY,'l',barX+barW+offsetX,barY-offsetY,'l',barX+barW,barY,'c','s',co.strokeStyle,'f',co.fillStyle,'f','rgba(255,255,255,0.6)']);}
77
+ if(prop['chart.yaxispos']!=='right'&&!(prop['chart.yaxispos']==='center'&&value<0)&&!RG.isNull(value)){pa2(co,['fs',prevFillStyle,'b','m',barX+barW,barY,'l',barX+barW+offsetX,barY-offsetY,'l',barX+barW+offsetX,barY-offsetY+barH,'l',barX+barW,barY+barH,'c','s',co.strokeStyle,'f',prevFillStyle,'f','rgba(0,0,0,0.25)']);}
78
+ co.beginPath();co.strokeStyle=prevStrokeStyle;co.fillStyle=prevFillStyle;}
79
+ if(prop['chart.yaxispos']!=='right'){x+=width;}}}else if(typeof(this.data[i])=='object'&&prop['chart.grouping']=='grouped'){var vmarginGrouped=prop['chart.vmargin.grouped'];var individualBarHeight=((height-(2*vmargin)-((this.data[i].length-1)*vmarginGrouped))/this.data[i].length)
80
+ if(typeof this.coords2[i]=='undefined'){this.coords2[i]=[];}
81
+ for(j=(this.data[i].length-1);j>=0;--j){if(prop['chart.shadow']){RG.setShadow(this,prop['chart.shadow.color'],prop['chart.shadow.offsetx'],prop['chart.shadow.offsety'],prop['chart.shadow.blur']);}
82
+ co.strokeStyle=prop['chart.strokestyle'];++colorIdx;if(prop['chart.colors.sequential']&&typeof colorIdx==='number'){if(prop['chart.colors'][this.numbars-colorIdx]){co.fillStyle=prop['chart.colors'][this.numbars-colorIdx];}else{co.fillStyle=prop['chart.colors'][prop['chart.colors'].length-1];}}else if(prop['chart.colors'][j]){co.fillStyle=prop['chart.colors'][j];}
83
+ var startY=this.gutterTop+(height*i)+(individualBarHeight*j)+vmargin+(vmarginGrouped*j);var width=((this.data[i][j]-prop['chart.xmin'])/(this.max-prop['chart.xmin']))*(ca.width-this.gutterLeft-this.gutterRight);var startX=this.gutterLeft;if(prop['chart.yaxispos']=='center'){width/=2;startX+=halfwidth;}else if(prop['chart.yaxispos']=='right'){width=ma.abs(width);startX=ca.width-this.gutterRight-ma.abs(width);;}
84
+ if(width<0){startX+=width;width*=-1;}
85
+ co.strokeRect(startX,startY,width,individualBarHeight);co.fillRect(startX,startY,width,individualBarHeight);this.coords.push([startX,startY,width,individualBarHeight,co.fillStyle,this.data[i][j],true]);this.coords2[i].push([startX,startY,width,individualBarHeight,co.fillStyle,this.data[i][j],true]);if(prop['chart.variant']==='3d'){RG.noShadow(this);var prevStrokeStyle=co.strokeStyle,prevFillStyle=co.fillStyle;var barX=startX,barY=startY,barW=width,barH=individualBarHeight,offsetX=prop['chart.variant.threed.offsetx'],offsetY=prop['chart.variant.threed.offsety'],value=this.data[i][j];pa2(co,['b','m',barX,barY,'l',barX+offsetX,barY-offsetY,'l',barX+barW+offsetX-(value<0?offsetX:0),barY-offsetY,'l',barX+barW,barY,'c','s',co.strokeStyle,'f',co.fillStyle,'f','rgba(255,255,255,0.6)']);if(prop['chart.yaxispos']!=='right'&&!(prop['chart.yaxispos']==='center'&&value<0)&&value>=0&&!RG.isNull(value)){pa2(co,['fs',prevFillStyle,'b','m',barX+barW,barY,'l',barX+barW+offsetX,barY-offsetY,'l',barX+barW+offsetX,barY-offsetY+barH,'l',barX+barW,barY+barH,'c','s',co.strokeStyle,'f',prevFillStyle,'f','rgba(0,0,0,0.25)']);}
86
+ co.beginPath();co.strokeStyle=prevStrokeStyle;co.fillStyle=prevFillStyle;}}
87
+ startY+=vmargin;}
88
+ co.closePath();}
89
+ co.stroke();co.fill();if(prop['chart,yaxispos']==='right'){pa2(co,'cr % % % %',ca.width-this.gutterRight+prop['chart.variant.threed.offsetx'],'0',this.gutterRight,ca.height);}
90
+ if(prop['chart.yaxispos']==='right'&&prop['chart.variant']==='3d'){RG.draw3DYAxis(this);}
91
+ RG.noShadow(this);this.coords=RG.arrayReverse(this.coords);if(prop['chart.grouping']==='grouped'){for(var i=0;i<this.coords2.length;++i){this.coords2[i]=RG.arrayReverse(this.coords2[i]);}}
92
+ this.redrawBars();};this.redrawBars=this.RedrawBars=function()
93
+ {if(prop['chart.noredraw']){return;}
94
+ var coords=this.coords;var font=prop['chart.text.font'],size=prop['chart.text.size'],color=prop['chart.text.color'];RG.noShadow(this);co.strokeStyle=prop['chart.strokestyle'];for(var i=0;i<coords.length;++i){if(prop['chart.shadow']){pa2(co,'b lw % r % % % % s % f %',prop['chart.linewidth'],coords[i][0],coords[i][1],coords[i][2],coords[i][3],prop['chart.strokestyle'],coords[i][4]);}
95
+ var halign='left';if(prop['chart.labels.above']&&coords[i][6]){var border=(coords[i][0]+coords[i][2]+7+co.measureText(prop['chart.labels.above.units.pre']+this.coords[i][5]+prop['chart.labels.above.units.post']).width)>ca.width?true:false,text=RG.numberFormat(this,(this.coords[i][5]).toFixed(prop['chart.labels.above.decimals']),prop['chart.labels.above.units.pre'],prop['chart.labels.above.units.post']);RG.noShadow(this);if(typeof prop['chart.labels.above.specific']==='object'&&prop['chart.labels.above.specific']&&prop['chart.labels.above.specific'][i]){text=prop['chart.labels.above.specific'][i];}
96
+ var x=coords[i][0]+coords[i][2]+5;var y=coords[i][1]+(coords[i][3]/2);if(prop['chart.yaxispos']==='right'){x=coords[i][0]-5;halign='right';}else if(prop['chart.yaxispos']==='center'&&this.data_arr[i]<0){x=coords[i][0]-5;halign='right';}
97
+ RG.text2(this,{font:typeof prop['chart.labels.above.font']==='string'?prop['chart.labels.above.font']:font,size:typeof prop['chart.labels.above.size']==='number'?prop['chart.labels.above.size']:size,color:typeof prop['chart.labels.above.color']==='string'?prop['chart.labels.above.color']:color,x:x,y:y,bold:prop['chart.labels.above.bold'],italic:prop['chart.labels.above.italic'],text:text,valign:'center',halign:halign,tag:'labels.above'});}}};this.getShape=this.getBar=function(e)
98
+ {var mouseXY=RG.getMouseXY(e);for(var i=0,len=this.coords.length;i<len;i++){var mouseX=mouseXY[0],mouseY=mouseXY[1],left=this.coords[i][0],top=this.coords[i][1],width=this.coords[i][2],height=this.coords[i][3],idx=i;pa2(co,['b','r',left,top,width,height]);if(co.isPointInPath(mouseX,mouseY)){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:idx,'index':idx,'tooltip':tooltip};}}};this.getValue=function(arg)
99
+ {if(arg.length==2){var mouseX=arg[0];var mouseY=arg[1];}else{var mouseCoords=RG.getMouseXY(arg);var mouseX=mouseCoords[0];var mouseY=mouseCoords[1];}
100
+ if(mouseY<this.gutterTop||mouseY>(ca.height-this.gutterBottom)||mouseX<this.gutterLeft||mouseX>(ca.width-this.gutterRight)){return null;}
101
+ if(prop['chart.yaxispos']=='center'){var value=((mouseX-this.gutterLeft)/(this.graphwidth/2))*(this.max-prop['chart.xmin']);value=value-this.max
102
+ if(prop['chart.xmin']>0){value=((mouseX-this.gutterLeft-(this.graphwidth/2))/(this.graphwidth/2))*(this.max-prop['chart.xmin']);value+=prop['chart.xmin'];if(mouseX<(this.gutterLeft+(this.graphwidth/2))){value-=(2*prop['chart.xmin']);}}}else if(prop['chart.yaxispos']=='right'){var value=((mouseX-this.gutterLeft)/this.graphwidth)*(this.scale2.max-prop['chart.xmin']);value=this.scale2.max-value;}else{var value=((mouseX-this.gutterLeft)/this.graphwidth)*(this.scale2.max-prop['chart.xmin']);value+=prop['chart.xmin'];}
103
+ return value;};this.highlight=this.Highlight=function(shape)
104
+ {if(typeof prop['chart.highlight.style']==='function'){(prop['chart.highlight.style'])(shape);}else{RG.Highlight.Rect(this,shape);}};this.getObjectByXY=function(e)
105
+ {var mouseXY=RG.getMouseXY(e);if(prop['chart.variant']==='3d'){var adjustment=prop['chart.variant.threed.angle']*mouseXY[0];mouseXY[1]-=adjustment;}
106
+ if(mouseXY[0]>=this.gutterLeft&&mouseXY[0]<=(ca.width-this.gutterRight)&&mouseXY[1]>=this.gutterTop&&mouseXY[1]<=(ca.height-this.gutterBottom)){return this;}};this.getXCoord=function(value)
107
+ {if(prop['chart.yaxispos']=='center'){if(value>this.max||value<(-1*this.max)){return null;}
108
+ var width=(ca.width-prop['chart.gutter.left']-prop['chart.gutter.right'])/2;var coord=(((value-prop['chart.xmin'])/(this.max-prop['chart.xmin']))*width)+width;coord=prop['chart.gutter.left']+coord;}else{if(value>this.max||value<0){return null;}
109
+ var width=ca.width-prop['chart.gutter.left']-prop['chart.gutter.right'];var coord=((value-prop['chart.xmin'])/(this.max-prop['chart.xmin']))*width;coord=prop['chart.gutter.left']+coord;}
110
+ return coord;};this.parseColors=function()
111
+ {if(this.original_colors.length===0){this.original_colors['chart.colors']=RG.array_clone(prop['chart.colors']);this.original_colors['chart.background.grid.color']=RG.array_clone(prop['chart.background.grid.color']);this.original_colors['chart.background.color']=RG.array_clone(prop['chart.background.color']);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.text.color']=RG.array_clone(prop['chart.text.color']);this.original_colors['chart.labels.colors']=RG.array_clone(prop['chart.labels.colors']);this.original_colors['chart.strokestyle']=RG.array_clone(prop['chart.strokestyle']);this.original_colors['chart.axis.color']=RG.array_clone(prop['chart.axis.color']);this.original_colors['chart.highlight.fill']=RG.array_clone(prop['chart.highlight.fill']);this.original_colors['chart.highlight.stroke']=RG.array_clone(prop['chart.highlight.stroke']);}
112
+ var colors=prop['chart.colors'];for(var i=0;i<colors.length;++i){colors[i]=this.parseSingleColorForGradient(colors[i]);}
113
+ prop['chart.background.grid.color']=this.parseSingleColorForGradient(prop['chart.background.grid.color']);prop['chart.background.color']=this.parseSingleColorForGradient(prop['chart.background.color']);prop['chart.background.barcolor1']=this.parseSingleColorForGradient(prop['chart.background.barcolor1']);prop['chart.background.barcolor2']=this.parseSingleColorForGradient(prop['chart.background.barcolor2']);prop['chart.text.color']=this.parseSingleColorForGradient(prop['chart.text.color']);prop['chart.labels.colors']=this.parseSingleColorForGradient(prop['chart.labels.colors']);prop['chart.strokestyle']=this.parseSingleColorForGradient(prop['chart.strokestyle']);prop['chart.axis.color']=this.parseSingleColorForGradient(prop['chart.axis.color']);prop['chart.highlight.fill']=this.parseSingleColorForGradient(prop['chart.highlight.fill']);prop['chart.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.stroke']);};this.reset=function()
114
+ {};this.parseSingleColorForGradient=function(color)
115
+ {if(!color||typeof(color)!='string'){return color;}
116
+ if(color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':');if(prop['chart.yaxispos']==='right'){parts=RG.arrayReverse(parts);}
117
+ var grad=co.createLinearGradient(prop['chart.gutter.left'],0,ca.width-prop['chart.gutter.right'],0);var diff=1/(parts.length-1);grad.addColorStop(0,RG.trim(parts[0]));for(var j=1;j<parts.length;++j){grad.addColorStop(j*diff,RG.trim(parts[j]));}}
118
+ return grad?grad:color;};this.interactiveKeyHighlight=function(index)
119
+ {var obj=this;this.coords2.forEach(function(value,idx,arr)
120
+ {var shape=obj.coords2[idx][index]
121
+ var pre_linewidth=co.lineWidth;co.lineWidth=2;co.fillStyle=prop['chart.key.interactive.highlight.chart.fill'];co.strokeStyle=prop['chart.key.interactive.highlight.chart.stroke'];co.fillRect(shape[0],shape[1],shape[2],shape[3]);co.strokeRect(shape[0],shape[1],shape[2],shape[3]);co.lineWidth=pre_linewidth;});};this.on=function(type,func)
122
+ {if(type.substr(0,2)!=='on'){type='on'+type;}
123
+ if(typeof this[type]!=='function'){this[type]=func;}else{RG.addCustomEventListener(this,type,func);}
124
+ return this;};this.firstDrawFunc=function()
125
+ {};this.getShapeByY=function(e)
126
+ {var mouseXY=RG.getMouseXY(e);var obj=arguments[1]?arguments[1]:this;for(var i=0,len=obj.coords.length;i<len;i++){if(obj.coords[i].length==0){continue;}
127
+ var mouseX=mouseXY[0],mouseY=mouseXY[1],left=obj.coords[i][0],top=obj.coords[i][1],width=obj.coords[i][2],height=obj.coords[i][3];if(mouseY>=top&&mouseY<=(top+height)){if(prop['chart.tooltips']){var tooltip=RG.parseTooltipText?RG.parseTooltipText(prop['chart.tooltips'],i):prop['chart.tooltips'][i];}
128
+ return{0:obj,object:obj,1:left,x:left,2:top,y:top,3:width,width:width,4:height,height:height,5:i,index:i,tooltip:tooltip};}}
129
+ return null;};this.adjusting_mousemove=this.Adjusting_mousemove=function(e)
130
+ {if(prop['chart.adjustable']&&RG.Registry.get('chart.adjusting')&&RG.Registry.get('chart.adjusting').uid==this.uid){var value=Number(this.getValue(e)),shape=RG.Registry.get('chart.adjusting.shape');if(shape){RG.Registry.Set('chart.adjusting.shape',shape);if(this.stackedOrGrouped&&prop['chart.grouping']=='grouped'){var indexes=RG.sequentialIndexToGrouped(shape['index'],this.data);if(typeof this.data[indexes[0]]=='number'){this.data[indexes[0]]=Number(value);}else if(!RG.is_null(this.data[indexes[0]])){this.data[indexes[0]][indexes[1]]=Number(value);}}else if(typeof this.data[shape['index']]=='number'){this.data[shape['index']]=Number(value);}
131
+ RG.redrawCanvas(e.target);RG.fireCustomEvent(this,'onadjust');}}};this.grow=function()
132
+ {var obj=this,opt=arguments[0]||{},frames=opt.frames||30,frame=0,callback=arguments[1]||function(){},labelsAbove=prop['chart.labels.above'];this.set('labelsAbove',false);obj.original_data=RG.arrayClone(obj.data);if(prop['chart.xmax']==0){var xmax=0;for(var i=0;i<obj.data.length;++i){if(RG.isArray(obj.data[i])&&prop['chart.grouping']=='stacked'){xmax=ma.max(xmax,RG.arraySum(obj.data[i]));}else if(RG.isArray(obj.data[i])&&prop['chart.grouping']=='grouped'){xmax=ma.max(xmax,RG.arrayMax(obj.data[i]));}else{xmax=ma.max(xmax,ma.abs(RG.arrayMax(obj.data[i])));}}
133
+ var scale2=RG.getScale2(obj,{'max':xmax});obj.Set('chart.xmax',scale2.max);}
134
+ function iterator()
135
+ {for(var j=0,len=obj.original_data.length;j<len;++j){var easingFactor=RG.Effects.getEasingMultiplier(frames,frame);if(typeof obj.data[j]==='object'&&obj.data[j]){for(var k=0,len2=obj.data[j].length;k<len2;++k){obj.data[j][k]=RG.isNull(obj.data[j][k])?null:obj.original_data[j][k]*easingFactor;}}else{obj.data[j]=RG.isNull(obj.data[j])?null:obj.original_data[j]*easingFactor;}}
136
+ RG.redrawCanvas(obj.canvas);if(frame<frames){frame+=1;RG.Effects.updateCanvas(iterator);}else{if(labelsAbove){obj.set('labelsAbove',true);RG.redraw();}
137
+ callback(obj);}}
138
+ iterator();return this;};this.grow=function()
139
+ {var opt=arguments[0]||{},frames=opt.frames||30,frame=0,callback=arguments[1]||function(){},obj=this,labelsAbove=this.get('labelsAbove')
140
+ this.original_data=RG.arrayClone(this.data);if(prop['chart.xmax']==0){var xmax=0;for(var i=0;i<obj.data.length;++i){if(RG.isArray(obj.data[i])&&prop['chart.grouping']=='stacked'){xmax=ma.max(xmax,RG.arraySum(obj.data[i]));}else if(RG.isArray(obj.data[i])&&prop['chart.grouping']=='grouped'){xmax=ma.max(xmax,RG.arrayMax(obj.data[i]));}else{xmax=ma.max(xmax,ma.abs(RG.arrayMax(obj.data[i])));}}
141
+ var scale2=RG.getScale2(obj,{'max':xmax});obj.Set('chart.xmax',scale2.max);}
142
+ if(RG.isArray(opt.data)){var xmax=0;for(var i=0;i<opt.data.length;++i){if(typeof opt.data[i]==='object'){for(var j=0;j<opt.data[i].length;++j){if(typeof opt.data[i][j]==='string'&&opt.data[i][j].match(/(\+|\-)([0-9]+)/)){if(RegExp.$1==='+'){opt.data[i][j]=this.original_data[i][j]+parseInt(RegExp.$2);}else{opt.data[i][j]=this.original_data[i][j]-parseInt(RegExp.$2);}}
143
+ xmax=ma.max(xmax,opt.data[i][j]);}}else if(typeof opt.data[i]==='string'&&opt.data[i].match(/(\+|\-)([0-9]+)/)){if(RegExp.$1==='+'){opt.data[i]=this.original_data[i]+parseFloat(RegExp.$2);}else{opt.data[i]=this.original_data[i]-parseFloat(RegExp.$2);}
144
+ xmax=ma.max(xmax,opt.data[i]);}else{xmax=ma.max(xmax,opt.data[i]);}}
145
+ var scale=RG.getScale2(this,{'max':xmax});if(typeof this.get('chart.xmax')==='null'){this.set('chart.xmax',scale.max);}}
146
+ this.set('labelsAbove',false);if(RG.isNull(prop['chart.xmax'])){var xmax=0;for(var i=0;i<obj.data.length;++i){if(RG.isArray(this.data[i])&&prop['chart.grouping']==='stacked'){xmax=ma.max(xmax,ma.abs(RG.arraySum(this.data[i])));}else if(RG.isArray(this.data[i])&&prop['chart.grouping']==='grouped'){for(var j=0,group=[];j<this.data[i].length;j++){group.push(ma.abs(this.data[i][j]));}
147
+ xmax=ma.max(xmax,ma.abs(RG.arrayMax(group)));}else{xmax=ma.max(xmax,ma.abs(this.data[i]));}}
148
+ var scale=RG.getScale2(this,{'max':xmax});this.Set('chart.xmax',scale.max);}
149
+ if(typeof opt.xmax==='number'){obj.set('xmax',opt.xmax);}
150
+ var iterator=function()
151
+ {var easingMultiplier=RG.Effects.getEasingMultiplier(frames,frame);for(var j=0,len=obj.original_data.length;j<len;++j){if(typeof obj.data[j]==='object'&&!RG.isNull(obj.data[j])){for(var k=0,len2=obj.data[j].length;k<len2;++k){if(obj.firstDraw||!opt.data){obj.data[j][k]=easingMultiplier*obj.original_data[j][k];}else if(opt.data&&opt.data.length===obj.original_data.length){var diff=opt.data[j][k]-obj.original_data[j][k];obj.data[j][k]=(easingMultiplier*diff)+obj.original_data[j][k];}}}else{if(obj.firstDraw||!opt.data){obj.data[j]=easingMultiplier*obj.original_data[j];}else if(opt.data&&opt.data.length===obj.original_data.length){var diff=opt.data[j]-obj.original_data[j];obj.data[j]=(easingMultiplier*diff)+obj.original_data[j];}}}
152
+ RG.redrawCanvas(obj.canvas);if(frame<frames){frame+=1;RG.Effects.updateCanvas(iterator);}else{if(RG.isArray(opt.data)){var linear_data=RG.arrayLinearize(data);for(var i=0;i<linear_data.length;++i){if(!obj['$'+i]){obj['$'+i]={};}}}
153
+ obj.data=data;obj.original_data=RG.arrayClone(data);if(labelsAbove){obj.set('labelsAbove',true);RG.redraw();}
154
+ callback(obj);}};iterator();return this;};this.wave=function()
155
+ {var obj=this,opt=arguments[0]||{};opt.frames=opt.frames||60;opt.startFrames=[];opt.counters=[];var framesperbar=opt.frames/3,frame=-1,callback=arguments[1]||function(){},original=RG.arrayClone(obj.data),labelsAbove=prop['chart.labels.above'];this.set('labelsAbove',false);for(var i=0,len=obj.data.length;i<len;i+=1){opt.startFrames[i]=((opt.frames/2)/(obj.data.length-1))*i;if(typeof obj.data[i]==='object'&&obj.data[i]){opt.counters[i]=[];for(var j=0;j<obj.data[i].length;j++){opt.counters[i][j]=0;}}else{opt.counters[i]=0;}}
156
+ obj.draw();obj.Set('xmax',obj.scale2.max);RG.clear(obj.canvas);function iterator()
157
+ {++frame;for(var i=0,len=obj.data.length;i<len;i+=1){if(frame>opt.startFrames[i]){if(typeof obj.data[i]==='number'){obj.data[i]=ma.min(ma.abs(original[i]),ma.abs(original[i]*((opt.counters[i]++)/framesperbar)));if(original[i]<0){obj.data[i]*=-1;}}else if(!RG.isNull(obj.data[i])){for(var j=0,len2=obj.data[i].length;j<len2;j+=1){obj.data[i][j]=ma.min(ma.abs(original[i][j]),ma.abs(original[i][j]*((opt.counters[i][j]++)/framesperbar)));if(original[i][j]<0){obj.data[i][j]*=-1;}}}}else{obj.data[i]=typeof obj.data[i]==='object'&&obj.data[i]?RG.arrayPad([],obj.data[i].length,0):(RG.isNull(obj.data[i])?null:0);}}
158
+ if(frame>=opt.frames){if(labelsAbove){obj.set('labelsAbove',true);RG.redrawCanvas(obj.canvas);}
159
+ callback(obj);}else{RG.redrawCanvas(obj.canvas);RG.Effects.updateCanvas(iterator);}}
160
+ iterator();return this;};this.isAdjustable=function(shape)
161
+ {if(RG.isNull(prop['chart.adjustable.only'])){return true;}
162
+ if(RG.isArray(prop['chart.adjustable.only'])&&prop['chart.adjustable.only'][shape.index]){return true;}
163
+ return false;};RG.Register(this);if(parseConfObjectForOptions){RG.parseObjectStyleConfig(this,conf.options);}};