rgraph-rails 1.0.5 → 1.0.6

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