rgraph-rails 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +1 -0
  3. data/README.md +5 -5
  4. data/lib/rgraph-rails/version.rb +1 -1
  5. data/rgraph-rails.gemspec +2 -2
  6. data/vendor/assets/images/bg.png +0 -0
  7. data/vendor/assets/images/bullet.png +0 -0
  8. data/vendor/assets/images/facebook-large.png +0 -0
  9. data/vendor/assets/images/google-plus-large.png +0 -0
  10. data/vendor/assets/images/logo.png +0 -0
  11. data/vendor/assets/images/meter-image-sd-needle.png +0 -0
  12. data/vendor/assets/images/meter-image-sd.png +0 -0
  13. data/vendor/assets/images/meter-sketch-needle.png +0 -0
  14. data/vendor/assets/images/meter-sketch.png +0 -0
  15. data/vendor/assets/images/odometer-background.png +0 -0
  16. data/vendor/assets/images/rgraph.jpg +0 -0
  17. data/vendor/assets/images/title.png +0 -0
  18. data/vendor/assets/images/twitter-large.png +0 -0
  19. data/vendor/assets/javascripts/RGraph.bar.js +258 -30
  20. data/vendor/assets/javascripts/RGraph.bipolar.js +4 -3
  21. data/vendor/assets/javascripts/RGraph.common.annotate.js +4 -3
  22. data/vendor/assets/javascripts/RGraph.common.context.js +4 -3
  23. data/vendor/assets/javascripts/RGraph.common.core.js +227 -105
  24. data/vendor/assets/javascripts/RGraph.common.csv.js +4 -3
  25. data/vendor/assets/javascripts/RGraph.common.deprecated.js +4 -3
  26. data/vendor/assets/javascripts/RGraph.common.dynamic.js +5 -4
  27. data/vendor/assets/javascripts/RGraph.common.effects.js +4 -3
  28. data/vendor/assets/javascripts/RGraph.common.key.js +4 -3
  29. data/vendor/assets/javascripts/RGraph.common.resizing.js +4 -3
  30. data/vendor/assets/javascripts/RGraph.common.sheets.js +357 -0
  31. data/vendor/assets/javascripts/RGraph.common.tooltips.js +6 -4
  32. data/vendor/assets/javascripts/RGraph.common.zoom.js +4 -3
  33. data/vendor/assets/javascripts/RGraph.drawing.background.js +4 -3
  34. data/vendor/assets/javascripts/RGraph.drawing.circle.js +4 -3
  35. data/vendor/assets/javascripts/RGraph.drawing.image.js +4 -3
  36. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +4 -3
  37. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +4 -3
  38. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +1 -1
  39. data/vendor/assets/javascripts/RGraph.drawing.poly.js +1 -1
  40. data/vendor/assets/javascripts/RGraph.drawing.rect.js +1 -1
  41. data/vendor/assets/javascripts/RGraph.drawing.text.js +1 -1
  42. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +1 -1
  43. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +33 -30
  44. data/vendor/assets/javascripts/RGraph.fuel.js +14 -16
  45. data/vendor/assets/javascripts/RGraph.funnel.js +1 -1
  46. data/vendor/assets/javascripts/RGraph.gantt.js +1 -1
  47. data/vendor/assets/javascripts/RGraph.gauge.js +3 -5
  48. data/vendor/assets/javascripts/RGraph.hbar.js +738 -212
  49. data/vendor/assets/javascripts/RGraph.hprogress.js +30 -33
  50. data/vendor/assets/javascripts/RGraph.line.js +246 -31
  51. data/vendor/assets/javascripts/RGraph.meter.js +72 -36
  52. data/vendor/assets/javascripts/RGraph.modaldialog.js +1 -1
  53. data/vendor/assets/javascripts/RGraph.odo.js +3 -5
  54. data/vendor/assets/javascripts/RGraph.pie.js +23 -15
  55. data/vendor/assets/javascripts/RGraph.radar.js +1 -1
  56. data/vendor/assets/javascripts/RGraph.rose.js +2 -2
  57. data/vendor/assets/javascripts/RGraph.rscatter.js +116 -27
  58. data/vendor/assets/javascripts/RGraph.scatter.js +14 -15
  59. data/vendor/assets/javascripts/RGraph.thermometer.js +8 -10
  60. data/vendor/assets/javascripts/RGraph.vprogress.js +8 -10
  61. data/vendor/assets/javascripts/RGraph.waterfall.js +1 -1
  62. data/vendor/assets/stylesheets/website.css +32 -2
  63. metadata +6 -5
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -134,7 +135,7 @@
134
135
  tooltipObj.id = '__rgraph_tooltip_' + obj.canvas.id + '_' + obj.uid + '_'+ idx;
135
136
  tooltipObj.__event__ = obj.Get('chart.tooltips.event') || 'click';
136
137
  tooltipObj.__object__ = obj;
137
-
138
+
138
139
  if (typeof(idx) == 'number') {
139
140
  tooltipObj.__index__ = idx;
140
141
  origIdx = idx;
@@ -171,6 +172,7 @@
171
172
  /**
172
173
  * If the function exists call the object specific tooltip positioning function
173
174
  */
175
+
174
176
  if (typeof(obj.positionTooltip) == 'function') {
175
177
  if (tooltipObj.innerHTML.length > 0) {
176
178
 
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -652,15 +652,16 @@
652
652
  gap /= 2;
653
653
  }
654
654
 
655
- RG.Text2(this, {'font':font,
656
- 'size':size,
657
- 'x':x - (align == 'right' ? -5 : 5),
658
- 'y':(i * gap) + this.gutterTop,
659
- 'text':labels_specific[i],
660
- 'valign':'center',
661
- 'halign':align == 'right' ? 'left' : 'right',
662
- 'tag': 'scale'
663
- });
655
+ RG.text2(this, {
656
+ 'font':font,
657
+ 'size':size,
658
+ 'x':x - (align == 'right' ? -5 : 5),
659
+ 'y':(i * gap) + this.gutterTop,
660
+ 'text':labels_specific[i],
661
+ 'valign':'center',
662
+ 'halign':align == 'right' ? 'left' : 'right',
663
+ 'tag': 'scale'
664
+ });
664
665
 
665
666
  /**
666
667
  * Store the max length so that it can be used if necessary to determine
@@ -674,15 +675,16 @@
674
675
  // It's "-2" so that the center label isn't added twice
675
676
  for (var i=(labels_specific.length-2); i>=0; --i) {
676
677
 
677
- RG.Text2(this, {'font':font,
678
- 'size':size,
679
- 'x':x - (align == 'right' ? -5 : 5),
680
- 'y':ca.height - this.gutterBottom - (i * gap),
681
- 'text':labels_specific[i],
682
- 'valign':'center',
683
- 'halign':align == 'right' ? 'left' : 'right',
684
- 'tag': 'scale'
685
- });
678
+ RG.text2(this, {
679
+ 'font':font,
680
+ 'size':size,
681
+ 'x':x - (align == 'right' ? -5 : 5),
682
+ 'y':ca.height - this.gutterBottom - (i * gap),
683
+ 'text':labels_specific[i],
684
+ 'valign':'center',
685
+ 'halign':align == 'right' ? 'left' : 'right',
686
+ 'tag': 'scale'
687
+ });
686
688
  }
687
689
  }
688
690
 
@@ -696,8 +698,8 @@
696
698
  continue;
697
699
  }
698
700
 
699
- var text = RG.number_format(this, original.toFixed(decimals), units_pre, units_post);
700
- var text = String(typeof(formatter) == 'function' ? formatter(this, original) : text);
701
+ var text = RG.number_format(this, original.toFixed(decimals), units_pre, units_post);
702
+ var text = String(typeof(formatter) == 'function' ? formatter(this, original) : text);
701
703
 
702
704
  // text_len is used below for positioning the title
703
705
  var text_len = Math.max(text_len, co.measureText(text).width);
@@ -720,15 +722,16 @@
720
722
  /**
721
723
  * Now - draw the labels
722
724
  */
723
- RG.Text2(this, {'font':font,
724
- 'size':size,
725
- 'x':x - (align == 'right' ? -5 : 5),
726
- 'y':y + this.gutterTop,
727
- 'text':text,
728
- 'valign':'center',
729
- 'halign':align == 'right' ? 'left' : 'right',
730
- 'tag': 'scale'
731
- });
725
+ RG.text2(this, {
726
+ 'font':font,
727
+ 'size':size,
728
+ 'x':x - (align == 'right' ? -5 : 5),
729
+ 'y':y + this.gutterTop,
730
+ 'text':text,
731
+ 'valign':'center',
732
+ 'halign':align == 'right' ? 'left' : 'right',
733
+ 'tag': 'scale'
734
+ });
732
735
 
733
736
 
734
737
 
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -29,24 +29,22 @@
29
29
  * Allow for object config style
30
30
  */
31
31
  if ( typeof conf === 'object'
32
- && typeof conf.min === 'number'
33
- && typeof conf.max === 'number'
34
32
  && typeof conf.id === 'string') {
35
33
 
36
- var id = conf.id
37
- var canvas = document.getElementById(id);
38
- var min = conf.min;
39
- var max = conf.max;
40
- var value = conf.value;
41
- var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
34
+ var id = conf.id,
35
+ canvas = document.getElementById(id),
36
+ min = conf.min,
37
+ max = conf.max,
38
+ value = conf.value,
39
+ parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
42
40
 
43
41
  } else {
44
42
 
45
- var id = conf;
46
- var canvas = document.getElementById(id);
47
- var min = arguments[1];
48
- var max = arguments[2];
49
- var value = arguments[3];
43
+ var id = conf,
44
+ canvas = document.getElementById(id),
45
+ min = arguments[1],
46
+ max = arguments[2],
47
+ value = arguments[3];
50
48
  }
51
49
 
52
50
  // Get the canvas and context objects
@@ -56,8 +54,8 @@
56
54
  this.canvas.__object__ = this;
57
55
  this.type = 'fuel';
58
56
  this.isRGraph = true;
59
- this.min = min;
60
- this.max = max;
57
+ this.min = RGraph.stringsToNumbers(min);
58
+ this.max = RGraph.stringsToNumbers(max);
61
59
  this.value = RGraph.stringsToNumbers(value);
62
60
  this.angles = {};
63
61
  this.currentValue = null;
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -28,8 +28,6 @@
28
28
  * Allow for object config style
29
29
  */
30
30
  if ( typeof conf === 'object'
31
- && typeof conf.min === 'number'
32
- && typeof conf.max === 'number'
33
31
  && typeof conf.id === 'string') {
34
32
 
35
33
  var id = conf.id
@@ -54,8 +52,8 @@
54
52
  this.context = this.canvas.getContext ? this.canvas.getContext("2d", {alpha: (typeof id === 'object' && id.alpha === false) ? false : true}) : null;
55
53
  this.canvas.__object__ = this;
56
54
  this.type = 'gauge';
57
- this.min = min;
58
- this.max = max;
55
+ this.min = RGraph.stringsToNumbers(min);
56
+ this.max = RGraph.stringsToNumbers(max);
59
57
  this.value = RGraph.stringsToNumbers(value);
60
58
  this.isRGraph = true;
61
59
  this.currentValue = null;
@@ -1,4 +1,4 @@
1
- // version: 2015-11-02
1
+ // version: 2016-02-06
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,8 +7,9 @@
7
7
  * | |
8
8
  * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
9
  * | v2.0 license and a commercial license which means that you're not bound by |
10
- * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
- * | read about it here: |
10
+ * | the terms of the GPL. The commercial license starts at just �99 (GBP) and |
11
+ * | you can read about it here: |
12
+ * | |
12
13
  * | http://www.rgraph.net/license |
13
14
  * o--------------------------------------------------------------------------------o
14
15
  */
@@ -62,6 +63,7 @@
62
63
  this.firstDraw = true; // After the first draw this will be false
63
64
 
64
65
 
66
+
65
67
  /**
66
68
  * Compatibility with older browsers
67
69
  */
@@ -198,6 +200,7 @@
198
200
  'chart.scale.point': '.',
199
201
  'chart.scale.thousand': ',',
200
202
  'chart.scale.decimals': null,
203
+ 'chart.scale.zerostart': false,
201
204
  'chart.noredraw': false,
202
205
  'chart.events.click': null,
203
206
  'chart.events.mousemove': null,
@@ -207,7 +210,15 @@
207
210
  'chart.noxtickmarks': false,
208
211
  'chart.noytickmarks': false,
209
212
  'chart.numyticks': data.length,
210
- 'chart.numxticks': 10
213
+ 'chart.numxticks': 10,
214
+ 'chart.variant': 'hbar',
215
+ 'chart.variant.threed.angle': 0.1,
216
+ 'chart.variant.threed.offsetx': 10,
217
+ 'chart.variant.threed.offsety': 5,
218
+ 'chart.variant.threed.xaxis': true,
219
+ 'chart.variant.threed.yaxis': true,
220
+ 'chart.yaxispos': 'left',
221
+ 'chart.variant': 'hbar'
211
222
  }
212
223
 
213
224
  // Check for support
@@ -236,7 +247,7 @@
236
247
  /**
237
248
  * Create the linear data array
238
249
  */
239
- this.data_arr = RGraph.array_linearize(this.data);
250
+ this.data_arr = RGraph.arrayLinearize(this.data);
240
251
 
241
252
 
242
253
  /**
@@ -316,7 +327,7 @@
316
327
  if (name == 'chart.labels.abovebar') {
317
328
  name = 'chart.labels.above';
318
329
  }
319
-
330
+
320
331
  prop[name] = value;
321
332
 
322
333
  return this;
@@ -367,7 +378,24 @@
367
378
  * Fire the onbeforedraw event
368
379
  */
369
380
  RG.FireCustomEvent(this, 'onbeforedraw');
370
-
381
+
382
+
383
+
384
+
385
+ //
386
+ // If the chart is 3d then angle it it
387
+ //
388
+ if (prop['chart.variant'] === '3d') {
389
+ co.setTransform(1,prop['chart.variant.threed.angle'],0,1,0.5,0.5);
390
+
391
+ // Enlarge the gutter if its 25
392
+ if (prop['chart.gutter.bottom'] === 25) {
393
+ this.set('gutterBottom', 80);
394
+ }
395
+ }
396
+
397
+
398
+
371
399
 
372
400
  /**
373
401
  * Parse the colors. This allows for simple gradient syntax
@@ -421,7 +449,10 @@
421
449
  this.gutterRight = prop['chart.gutter.right'];
422
450
  this.gutterTop = prop['chart.gutter.top'];
423
451
  this.gutterBottom = prop['chart.gutter.bottom'];
424
-
452
+
453
+
454
+
455
+
425
456
  /**
426
457
  * Stop the coords array from growing uncontrollably
427
458
  */
@@ -446,6 +477,7 @@
446
477
  this.graphheight = ca.height - this.gutterTop - this.gutterBottom;
447
478
  this.halfgrapharea = this.grapharea / 2;
448
479
  this.halfTextHeight = prop['chart.text.size'] / 2;
480
+ this.halfway = ma.round((this.graphwidth / 2) + this.gutterLeft)
449
481
 
450
482
 
451
483
 
@@ -539,13 +571,21 @@
539
571
  this.drawAxes =
540
572
  this.DrawAxes = function ()
541
573
  {
542
- var halfway = ma.round((this.graphwidth / 2) + this.gutterLeft);
543
-
574
+ var halfway = this.halfway
575
+
576
+
577
+
578
+
579
+
580
+
544
581
  co.beginPath();
545
582
 
546
583
  co.lineWidth = prop['chart.axis.linewidth'] ? prop['chart.axis.linewidth'] + 0.001 : 1.001;
547
584
  co.strokeStyle = prop['chart.axis.color'];
548
-
585
+
586
+
587
+
588
+
549
589
  // Draw the Y axis
550
590
  if (prop['chart.noyaxis'] == false && prop['chart.noaxes'] == false) {
551
591
  if (prop['chart.yaxispos'] == 'center') {
@@ -677,10 +717,10 @@
677
717
  this.drawLabels =
678
718
  this.DrawLabels = function ()
679
719
  {
680
- var units_pre = prop['chart.units.pre'];
681
- var units_post = prop['chart.units.post'];
682
- var text_size = prop['chart.text.size'];
683
- var font = prop['chart.text.font'];
720
+ var units_pre = prop['chart.units.pre'],
721
+ units_post = prop['chart.units.post'],
722
+ text_size = prop['chart.text.size'],
723
+ font = prop['chart.text.font'];
684
724
 
685
725
 
686
726
 
@@ -784,61 +824,68 @@
784
824
  if (prop['chart.yaxispos'] == 'center') {
785
825
 
786
826
  for (var i=0; i<this.scale2.labels.length; ++i) {
787
- RG.Text2(this, {'font':font,
788
- 'size':text_size,
789
- 'x':this.gutterLeft + (this.graphwidth / 2) - ((this.graphwidth / 2) * ((i+1)/this.scale2.labels.length)),
790
- 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap,
791
- 'text':'-' + this.scale2.labels[i],
792
- 'valign':'center',
793
- 'halign':'center',
794
- 'tag': 'scale'});
827
+ RG.text2(this, {
828
+ 'font':font,
829
+ 'size':text_size,
830
+ 'x':this.gutterLeft + (this.graphwidth / 2) - ((this.graphwidth / 2) * ((i+1)/this.scale2.labels.length)),
831
+ 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap,
832
+ 'text':'-' + this.scale2.labels[i],
833
+ 'valign':'center',
834
+ 'halign':'center',
835
+ 'tag': 'scale'
836
+ });
795
837
  }
796
838
 
797
839
  for (var i=0; i<this.scale2.labels.length; ++i) {
798
- RG.Text2(this, {'font':font,
799
- 'size':text_size,
800
- 'x':this.gutterLeft + ((this.graphwidth / 2) * ((i+1)/this.scale2.labels.length)) + (this.graphwidth / 2),
801
- 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap,
802
- 'text':this.scale2.labels[i],
803
- 'valign':'center',
804
- 'halign':'center',
805
- 'tag': 'scale'});
840
+ RG.text2(this, {
841
+ 'font':font,
842
+ 'size':text_size,
843
+ 'x':this.gutterLeft + ((this.graphwidth / 2) * ((i+1)/this.scale2.labels.length)) + (this.graphwidth / 2),
844
+ 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap,
845
+ 'text':this.scale2.labels[i],
846
+ 'valign':'center',
847
+ 'halign':'center',
848
+ 'tag': 'scale'
849
+ });
806
850
  }
807
851
 
808
852
  }else if (prop['chart.yaxispos'] == 'right') {
809
853
 
810
854
 
811
855
  for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
812
- RG.Text2(this, {'font':font,
813
- 'size':text_size,
814
- 'x':this.gutterLeft + (i * (this.graphwidth / len)),
815
- 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap,
816
- 'text':'-' + this.scale2.labels[len - 1 - i],
817
- 'valign':'center',
818
- 'halign':'center',
819
- 'tag': 'scale'
820
- });
856
+ RG.Text2(this, {
857
+ 'font':font,
858
+ 'size':text_size,
859
+ 'x':this.gutterLeft + (i * (this.graphwidth / len)),
860
+ 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap,
861
+ 'text':'-' + this.scale2.labels[len - 1 - i],
862
+ 'valign':'center',
863
+ 'halign':'center',
864
+ 'tag': 'scale'
865
+ });
821
866
  }
822
867
 
868
+
823
869
  } else {
824
870
  for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
825
- RG.Text2(this, {'font':font,
826
- 'size':text_size,
827
- 'x':this.gutterLeft + (this.graphwidth * ((i+1)/len)),
828
- 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap,
829
- 'text':this.scale2.labels[i],
830
- 'valign':'center',
831
- 'halign':'center',
832
- 'tag': 'scale'
833
- });
871
+ RG.Text2(this, {
872
+ 'font':font,
873
+ 'size':text_size,
874
+ 'x':this.gutterLeft + (this.graphwidth * ((i+1)/len)),
875
+ 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap,
876
+ 'text':this.scale2.labels[i],
877
+ 'valign':'center',
878
+ 'halign':'center',
879
+ 'tag': 'scale'
880
+ });
834
881
  }
835
882
  }
836
883
 
837
884
  /**
838
885
  * If xmin is not zero - draw that
839
886
  */
840
- if (prop['chart.xmin'] > 0 || prop['chart.noyaxis'] == true) {
841
-
887
+ if (prop['chart.xmin'] > 0 || prop['chart.noyaxis'] == true || prop['chart.scale.zerostart'] || prop['chart.noaxes']) {
888
+
842
889
  var x = prop['chart.yaxispos'] == 'center' ? this.gutterLeft + (this.graphwidth / 2): this.gutterLeft;
843
890
 
844
891
  /**
@@ -848,28 +895,35 @@
848
895
  var x = ca.width - this.gutterRight;
849
896
  }
850
897
 
851
- RG.Text2(this, {'font':font,
852
- 'size':text_size,
853
- 'x':x,
854
- 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap,
855
- 'text':RG.number_format(this, prop['chart.xmin'].toFixed(prop['chart.scale.decimals']), units_pre, units_post),
856
- 'valign':'center',
857
- 'halign':'center',
858
- 'tag': 'scale'
859
- });
898
+ RG.text2(this, {
899
+ 'font':font,
900
+ 'size':text_size,
901
+ 'x':x,
902
+ 'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap,
903
+ 'text':RG.numberFormat(this, prop['chart.xmin'].toFixed(prop['chart.scale.decimals']), units_pre, units_post),
904
+ 'valign':'center',
905
+ 'halign':'center',
906
+ 'tag': 'scale'
907
+ });
860
908
  }
861
909
 
862
910
  co.fill();
863
911
  co.stroke();
864
912
  }
865
913
  }
866
-
914
+
915
+
916
+
917
+
918
+
919
+
920
+
867
921
  /**
868
922
  * The Y axis labels
869
923
  */
870
- if (typeof(prop['chart.labels']) == 'object') {
924
+ if (typeof prop['chart.labels'] == 'object') {
871
925
 
872
- var xOffset = 5,
926
+ var xOffset = prop['chart.variant'] === '3d' && prop['chart.yaxispos'] === 'right' ? 15 : 5,
873
927
  font = prop['chart.text.font'],
874
928
  color = prop['chart.labels.color'] || prop['chart.text.color'],
875
929
  bold = prop['chart.labels.bold']
@@ -918,7 +972,8 @@
918
972
 
919
973
 
920
974
  /**
921
- * This function draws the bars
975
+ * This function draws the bars. It also draw 3D axes as the axes drawing bit
976
+ * is don AFTER the bars are drawn
922
977
  */
923
978
  this.drawbars =
924
979
  this.Drawbars = function ()
@@ -926,25 +981,29 @@
926
981
  co.lineWidth = prop['chart.linewidth'];
927
982
  co.strokeStyle = prop['chart.strokestyle'];
928
983
  co.fillStyle = prop['chart.colors'][0];
929
- var prevX = 0;
930
- var prevY = 0;
984
+
985
+ var prevX = 0,
986
+ prevY = 0;
987
+
931
988
 
932
989
  /**
933
990
  * Work out the max value
934
991
  */
935
992
  if (prop['chart.xmax']) {
936
993
 
937
- this.scale2 = RG.getScale2(this, {'max':prop['chart.xmax'],
938
- 'min':prop['chart.xmin'],
939
- 'scale.decimals':Number(prop['chart.scale.decimals']),
940
- 'scale.point':prop['chart.scale.point'],
941
- 'scale.thousand':prop['chart.scale.thousand'],
942
- 'scale.round':prop['chart.scale.round'],
943
- 'units.pre':prop['chart.units.pre'],
944
- 'units.post':prop['chart.units.post'],
945
- 'ylabels.count':prop['chart.xlabels.count'],
946
- 'strict':true
947
- });
994
+ this.scale2 = RG.getScale2(this, {
995
+ 'max':prop['chart.xmax'],
996
+ 'min':prop['chart.xmin'],
997
+ 'scale.decimals':Number(prop['chart.scale.decimals']),
998
+ 'scale.point':prop['chart.scale.point'],
999
+ 'scale.thousand':prop['chart.scale.thousand'],
1000
+ 'scale.round':prop['chart.scale.round'],
1001
+ 'units.pre':prop['chart.units.pre'],
1002
+ 'units.post':prop['chart.units.post'],
1003
+ 'ylabels.count':prop['chart.xlabels.count'],
1004
+ 'strict':true
1005
+ });
1006
+
948
1007
  this.max = this.scale2.max;
949
1008
 
950
1009
  } else {
@@ -955,23 +1014,24 @@
955
1014
  if (typeof(this.data[i]) == 'object') {
956
1015
  var value = grouping == 'grouped' ? Number(RG.array_max(this.data[i], true)) : Number(RG.array_sum(this.data[i])) ;
957
1016
  } else {
958
- var value = Number(Math.abs(this.data[i]));
1017
+ var value = Number(ma.abs(this.data[i]));
959
1018
  }
960
1019
 
961
1020
  this.max = ma.max(Math.abs(this.max), Math.abs(value));
962
1021
  }
963
1022
 
964
- this.scale2 = RG.getScale2(this, {'max':this.max,
965
- 'min':prop['chart.xmin'],
966
- 'scale.decimals':Number(prop['chart.scale.decimals']),
967
- 'scale.point':prop['chart.scale.point'],
968
- 'scale.thousand':prop['chart.scale.thousand'],
969
- 'scale.round':prop['chart.scale.round'],
970
- 'units.pre':prop['chart.units.pre'],
971
- 'units.post':prop['chart.units.post'],
972
- 'ylabels.count':prop['chart.xlabels.count']
973
- });
974
-
1023
+ this.scale2 = RG.getScale2(this, {
1024
+ 'max':this.max,
1025
+ 'min':prop['chart.xmin'],
1026
+ 'scale.decimals':Number(prop['chart.scale.decimals']),
1027
+ 'scale.point':prop['chart.scale.point'],
1028
+ 'scale.thousand':prop['chart.scale.thousand'],
1029
+ 'scale.round':prop['chart.scale.round'],
1030
+ 'units.pre':prop['chart.units.pre'],
1031
+ 'units.post':prop['chart.units.post'],
1032
+ 'ylabels.count':prop['chart.xlabels.count']
1033
+ });
1034
+
975
1035
 
976
1036
  this.max = this.scale2.max;
977
1037
  this.min = this.scale2.min;
@@ -988,6 +1048,15 @@
988
1048
 
989
1049
 
990
1050
 
1051
+ // Draw the 3d axes if necessary
1052
+ if (prop['chart.variant'] === '3d') {
1053
+ RG.draw3DAxes(this);
1054
+ }
1055
+
1056
+
1057
+
1058
+
1059
+
991
1060
 
992
1061
  /**
993
1062
  * The bars are drawn HERE
@@ -995,8 +1064,8 @@
995
1064
  var graphwidth = (ca.width - this.gutterLeft - this.gutterRight);
996
1065
  var halfwidth = graphwidth / 2;
997
1066
 
998
- for (i=0,len=this.data.length; i<len; ++i) {
999
-
1067
+ for (i=(len=this.data.length-1); i>=0; --i) {
1068
+
1000
1069
  // Work out the width and height
1001
1070
  var width = ma.abs((this.data[i] / this.max) * graphwidth);
1002
1071
  var height = this.graphheight / this.data.length;
@@ -1027,16 +1096,18 @@
1027
1096
  co.shadowOffsetX = prop['chart.shadow.offsetx'];
1028
1097
  co.shadowOffsetY = prop['chart.shadow.offsety'];
1029
1098
  }
1030
-
1099
+
1031
1100
  /**
1032
1101
  * Draw the bar
1033
1102
  */
1034
1103
  co.beginPath();
1035
- if (typeof(this.data[i]) == 'number') {
1036
-
1037
- var barHeight = height - (2 * vmargin);
1038
- var barWidth = ((this.data[i] - prop['chart.xmin']) / (this.max - prop['chart.xmin'])) * this.graphwidth;
1039
- var barX = this.gutterLeft;
1104
+
1105
+ // Standard (non-grouped and non-stacked) bars here
1106
+ if (typeof this.data[i] == 'number' || RG.isNull(this.data[i])) {
1107
+
1108
+ var barHeight = height - (2 * vmargin),
1109
+ barWidth = ((this.data[i] - prop['chart.xmin']) / (this.max - prop['chart.xmin'])) * this.graphwidth,
1110
+ barX = this.gutterLeft;
1040
1111
 
1041
1112
  // Account for Y axis pos
1042
1113
  if (prop['chart.yaxispos'] == 'center') {
@@ -1044,42 +1115,155 @@
1044
1115
  barX += halfwidth;
1045
1116
 
1046
1117
  if (this.data[i] < 0) {
1047
- barWidth = (Math.abs(this.data[i]) - prop['chart.xmin']) / (this.max - prop['chart.xmin']);
1118
+ barWidth = (ma.abs(this.data[i]) - prop['chart.xmin']) / (this.max - prop['chart.xmin']);
1048
1119
  barWidth = barWidth * (this.graphwidth / 2);
1049
1120
  barX = ((this.graphwidth / 2) + this.gutterLeft) - barWidth;
1050
1121
  }
1051
1122
 
1052
1123
  } else if (prop['chart.yaxispos'] == 'right') {
1053
1124
 
1054
- barWidth = Math.abs(barWidth);
1125
+ barWidth = ma.abs(barWidth);
1055
1126
  barX = ca.width - this.gutterRight - barWidth;
1127
+
1056
1128
  }
1057
1129
 
1058
1130
  // Set the fill color
1059
1131
  co.strokeStyle = prop['chart.strokestyle'];
1060
- co.fillStyle = prop['chart.colors'][0];
1061
-
1132
+ co.fillStyle = prop['chart.colors'][0];
1133
+
1062
1134
  // Sequential colors
1063
1135
  if (prop['chart.colors.sequential']) {
1064
1136
  co.fillStyle = prop['chart.colors'][colorIdx++];
1065
1137
  }
1066
1138
 
1139
+
1140
+
1141
+
1142
+
1143
+
1144
+
1145
+
1146
+
1147
+
1148
+
1149
+
1150
+
1151
+
1152
+
1153
+
1067
1154
  co.strokeRect(barX, this.gutterTop + (i * height) + prop['chart.vmargin'], barWidth, barHeight);
1068
1155
  co.fillRect(barX, this.gutterTop + (i * height) + prop['chart.vmargin'], barWidth, barHeight);
1069
1156
 
1070
- this.coords.push([barX,
1071
- y + vmargin,
1072
- barWidth,
1073
- height - (2 * vmargin),
1074
- co.fillStyle,
1075
- this.data[i],
1076
- true]);
1077
-
1157
+
1158
+
1159
+
1160
+
1161
+
1162
+
1163
+
1164
+
1165
+
1166
+
1167
+
1168
+
1169
+
1170
+
1171
+
1172
+
1173
+
1174
+
1175
+
1176
+
1177
+
1178
+
1179
+
1180
+ this.coords.push([
1181
+ barX,
1182
+ y + vmargin,
1183
+ barWidth,
1184
+ height - (2 * vmargin),
1185
+ co.fillStyle,
1186
+ this.data[i],
1187
+ true
1188
+ ]);
1189
+
1190
+
1191
+
1192
+
1193
+
1194
+
1195
+ // Draw the 3D effect using the coords that have just been stored
1196
+ if (prop['chart.variant'] === '3d' && typeof this.data[i] == 'number') {
1197
+
1198
+
1199
+ var prevStrokeStyle = co.strokeStyle,
1200
+ prevFillStyle = co.fillStyle;
1201
+
1202
+ /**
1203
+ * Turn off the shadow for the 3D bits
1204
+ */
1205
+ RG.noShadow(this);
1206
+
1207
+ // DRAW THE 3D BITS HERE
1208
+ var barX = barX,
1209
+ barY = y + vmargin,
1210
+ barW = barWidth,
1211
+ barH = height - (2 * vmargin),
1212
+ offsetX = prop['chart.variant.threed.offsetx'],
1213
+ offsetY = prop['chart.variant.threed.offsety'],
1214
+ value = this.data[i];
1215
+
1216
+
1217
+ pa2(
1218
+ co,
1219
+ [
1220
+ 'b',
1221
+ 'm', barX, barY,
1222
+ 'l', barX + offsetX - (prop['chart.yaxispos'] == 'left' && value < 0 ? offsetX : 0), barY - offsetY,
1223
+ 'l', barX + barW + offsetX - (prop['chart.yaxispos'] == 'center' && value < 0 ? offsetX : 0), barY - offsetY,
1224
+ 'l', barX + barW, barY,
1225
+ 'c',
1226
+ 's', co.strokeStyle,
1227
+ 'f', co.fillStyle,
1228
+ 'f','rgba(255,255,255,0.6)'//Fill again to lighten it
1229
+ ]
1230
+ );
1231
+
1232
+ if ( prop['chart.yaxispos'] !== 'right'
1233
+ && !(prop['chart.yaxispos'] === 'center' && value < 0)
1234
+ && value >= 0
1235
+ && !RG.isNull(value)
1236
+ ) {
1237
+
1238
+ pa2(
1239
+ co,
1240
+ [
1241
+ 'b',
1242
+ 'fs', prevFillStyle,
1243
+ 'm', barX + barW, barY,
1244
+ 'l', barX + barW + offsetX, barY - offsetY,
1245
+ 'l', barX + barW + offsetX, barY - offsetY + barH,
1246
+ 'l', barX + barW, barY + barH,
1247
+ 'c',
1248
+ 's', co.strokeStyle,
1249
+ 'f', prevFillStyle,
1250
+ 'f', 'rgba(0,0,0,0.25)'
1251
+ ]
1252
+ );
1253
+ }
1254
+
1255
+ }
1256
+
1257
+
1258
+
1259
+
1260
+
1261
+
1078
1262
  /**
1079
1263
  * Stacked bar chart
1080
1264
  */
1081
1265
  } else if (typeof(this.data[i]) == 'object' && prop['chart.grouping'] == 'stacked') {
1082
-
1266
+
1083
1267
  if (prop['chart.yaxispos'] == 'center') {
1084
1268
  alert('[HBAR] You can\'t have a stacked chart with the Y axis in the center, change it to grouped');
1085
1269
  } else if (prop['chart.yaxispos'] == 'right') {
@@ -1091,10 +1275,27 @@
1091
1275
  if (typeof this.coords2[i] == 'undefined') {
1092
1276
  this.coords2[i] = [];
1093
1277
  }
1094
-
1278
+
1095
1279
  for (j=0; j<this.data[i].length; ++j) {
1096
1280
 
1281
+ // The previous 3D segments would have turned the shadow off - so turn it back on
1282
+ if (prop['chart.shadow'] && prop['chart.variant'] === '3d') {
1283
+ co.shadowColor = prop['chart.shadow.color'];
1284
+ co.shadowBlur = prop['chart.shadow.blur'];
1285
+ co.shadowOffsetX = prop['chart.shadow.offsetx'];
1286
+ co.shadowOffsetY = prop['chart.shadow.offsety'];
1287
+ }
1288
+
1289
+ //
1290
+ // Ensure the number is positive
1291
+ //(even though having the X axis on the right implies a
1292
+ //negative value)
1293
+ //
1294
+ if (!RG.isNull(this.data[i][j])) this.data[i][j] = ma.abs(this.data[i][j]);
1295
+
1097
1296
 
1297
+ var last = (j === (this.data[i].length - 1) );
1298
+
1098
1299
  // Set the fill/stroke colors
1099
1300
  co.strokeStyle = prop['chart.strokestyle'];
1100
1301
  co.fillStyle = prop['chart.colors'][j];
@@ -1117,39 +1318,124 @@
1117
1318
 
1118
1319
  co.strokeRect(x, this.gutterTop + prop['chart.vmargin'] + (this.graphheight / this.data.length) * i, width, height - (2 * vmargin) );
1119
1320
  co.fillRect(x, this.gutterTop + prop['chart.vmargin'] + (this.graphheight / this.data.length) * i, width, height - (2 * vmargin) );
1120
-
1321
+
1322
+
1121
1323
  /**
1122
1324
  * Store the coords for tooltips
1123
1325
  */
1124
1326
 
1125
1327
  // The last property of this array is a boolean which tells you whether the value is the last or not
1126
- this.coords.push([x,
1127
- y + vmargin,
1128
- width,
1129
- height - (2 * vmargin),
1130
- co.fillStyle,
1131
- RG.array_sum(this.data[i]),
1132
- j == (this.data[i].length - 1)
1133
- ]);
1134
- this.coords2[i].push([x,
1135
- y + vmargin,
1136
- width,
1137
- height - (2 * vmargin),
1138
- co.fillStyle,
1139
- RG.array_sum(this.data[i]),
1140
- j == (this.data[i].length - 1)
1141
- ]);
1328
+ this.coords.push([
1329
+ x,
1330
+ y + vmargin,
1331
+ width,
1332
+ height - (2 * vmargin),
1333
+ co.fillStyle,
1334
+ RG.array_sum(this.data[i]),
1335
+ j == (this.data[i].length - 1)
1336
+ ]);
1337
+
1338
+ this.coords2[i].push([
1339
+ x,
1340
+ y + vmargin,
1341
+ width,
1342
+ height - (2 * vmargin),
1343
+ co.fillStyle,
1344
+ RG.array_sum(this.data[i]),
1345
+ j == (this.data[i].length - 1)
1346
+ ]);
1347
+
1348
+
1349
+
1350
+
1351
+
1352
+
1353
+ // 3D effect
1354
+ if (prop['chart.variant'] === '3d') {
1355
+
1356
+ /**
1357
+ * Turn off the shadow for the 3D bits
1358
+ */
1359
+ RG.noShadow(this);
1360
+
1361
+ var prevStrokeStyle = co.strokeStyle,
1362
+ prevFillStyle = co.fillStyle;
1363
+
1364
+ // DRAW THE 3D BITS HERE
1365
+ var barX = x,
1366
+ barY = y + vmargin,
1367
+ barW = width,
1368
+ barH = height - (2 * vmargin),
1369
+ offsetX = prop['chart.variant.threed.offsetx'],
1370
+ offsetY = prop['chart.variant.threed.offsety'],
1371
+ value = this.data[i][j];
1372
+
1373
+ if (!RG.isNull(value)) {
1374
+ pa2(
1375
+ co,
1376
+ [
1377
+ 'b',
1378
+ 'm', barX, barY,
1379
+ 'l', barX + offsetX, barY - offsetY,
1380
+ 'l', barX + barW + offsetX, barY - offsetY,
1381
+ 'l', barX + barW, barY,
1382
+ 'c',
1383
+ 's', co.strokeStyle,
1384
+ 'f', co.fillStyle,
1385
+ 'f','rgba(255,255,255,0.6)'//Fill again to lighten it
1386
+ ]
1387
+ );
1388
+ }
1389
+
1390
+ if ( prop['chart.yaxispos'] !== 'right'
1391
+ && !(prop['chart.yaxispos'] === 'center' && value < 0)
1392
+ && !RG.isNull(value)
1393
+ ) {
1394
+
1395
+ pa2(
1396
+ co,
1397
+ [
1398
+ 'fs', prevFillStyle,
1399
+ 'b',
1400
+ 'm', barX + barW, barY,
1401
+ 'l', barX + barW + offsetX, barY - offsetY,
1402
+ 'l', barX + barW + offsetX, barY - offsetY + barH,
1403
+ 'l', barX + barW, barY + barH,
1404
+ 'c',
1405
+ 's', co.strokeStyle,
1406
+ 'f', prevFillStyle,
1407
+ 'f', 'rgba(0,0,0,0.25)'
1408
+ ]
1409
+ );
1410
+ }
1411
+
1412
+ co.beginPath();
1413
+ co.strokeStyle = prevStrokeStyle;
1414
+ co.fillStyle = prevFillStyle;
1415
+ }
1416
+
1417
+
1418
+
1419
+
1420
+
1142
1421
 
1143
1422
  if (prop['chart.yaxispos'] !== 'right') {
1144
1423
  x += width;
1145
1424
  }
1146
1425
  }
1147
-
1426
+
1427
+
1428
+
1429
+
1430
+
1431
+
1432
+
1433
+
1148
1434
  /**
1149
1435
  * A grouped bar chart
1150
1436
  */
1151
1437
  } else if (typeof(this.data[i]) == 'object' && prop['chart.grouping'] == 'grouped') {
1152
-
1438
+
1153
1439
  var vmarginGrouped = prop['chart.vmargin.grouped'];
1154
1440
  var individualBarHeight = ((height - (2 * vmargin) - ((this.data[i].length - 1) * vmarginGrouped)) / this.data[i].length)
1155
1441
 
@@ -1157,8 +1443,8 @@
1157
1443
  this.coords2[i] = [];
1158
1444
  }
1159
1445
 
1160
- for (j=0; j<this.data[i].length; ++j) {
1161
-
1446
+ for (j=(this.data[i].length - 1); j>=0; --j) {
1447
+
1162
1448
 
1163
1449
  /**
1164
1450
  * Turn on the shadow if need be
@@ -1202,22 +1488,115 @@
1202
1488
 
1203
1489
  co.strokeRect(startX, startY, width, individualBarHeight);
1204
1490
  co.fillRect(startX, startY, width, individualBarHeight);
1491
+
1492
+
1493
+
1494
+
1495
+
1496
+
1497
+ this.coords.push([
1498
+ startX,
1499
+ startY,
1500
+ width,
1501
+ individualBarHeight,
1502
+ co.fillStyle,
1503
+ this.data[i][j],
1504
+ true
1505
+ ]);
1205
1506
 
1206
- this.coords.push([startX,
1207
- startY,
1208
- width,
1209
- individualBarHeight,
1210
- co.fillStyle,
1211
- this.data[i][j],
1212
- true]);
1213
-
1214
- this.coords2[i].push([startX,
1215
- startY,
1216
- width,
1217
- individualBarHeight,
1218
- co.fillStyle,
1219
- this.data[i][j],
1220
- true]);
1507
+ this.coords2[i].push([
1508
+ startX,
1509
+ startY,
1510
+ width,
1511
+ individualBarHeight,
1512
+ co.fillStyle,
1513
+ this.data[i][j],
1514
+ true
1515
+ ]);
1516
+
1517
+
1518
+
1519
+
1520
+
1521
+
1522
+
1523
+
1524
+
1525
+
1526
+
1527
+
1528
+ // 3D effect
1529
+ if (prop['chart.variant'] === '3d') {
1530
+
1531
+ /**
1532
+ * Turn off the shadow for the 3D bits
1533
+ */
1534
+ RG.noShadow(this);
1535
+
1536
+ var prevStrokeStyle = co.strokeStyle,
1537
+ prevFillStyle = co.fillStyle;
1538
+
1539
+ // DRAW THE 3D BITS HERE
1540
+ var barX = startX,
1541
+ barY = startY,
1542
+ barW = width,
1543
+ barH = individualBarHeight,
1544
+ offsetX = prop['chart.variant.threed.offsetx'],
1545
+ offsetY = prop['chart.variant.threed.offsety'],
1546
+ value = this.data[i][j];
1547
+
1548
+ pa2(
1549
+ co,
1550
+ [
1551
+ 'b',
1552
+ 'm', barX, barY,
1553
+ 'l', barX + offsetX, barY - offsetY,
1554
+ 'l', barX + barW + offsetX - (value < 0 ? offsetX : 0), barY - offsetY,
1555
+ 'l', barX + barW, barY,
1556
+ 'c',
1557
+ 's', co.strokeStyle,
1558
+ 'f', co.fillStyle,
1559
+ 'f','rgba(255,255,255,0.6)'//Fill again to lighten it
1560
+ ]
1561
+ );
1562
+
1563
+ if ( prop['chart.yaxispos'] !== 'right'
1564
+ && !(prop['chart.yaxispos'] === 'center' && value < 0)
1565
+ && value >= 0
1566
+ && !RG.isNull(value)
1567
+ ) {
1568
+
1569
+ pa2(
1570
+ co,
1571
+ [
1572
+ 'fs', prevFillStyle,
1573
+ 'b',
1574
+ 'm', barX + barW, barY,
1575
+ 'l', barX + barW + offsetX, barY - offsetY,
1576
+ 'l', barX + barW + offsetX, barY - offsetY + barH,
1577
+ 'l', barX + barW, barY + barH,
1578
+ 'c',
1579
+ 's', co.strokeStyle,
1580
+ 'f', prevFillStyle,
1581
+ 'f', 'rgba(0,0,0,0.25)'
1582
+ ]
1583
+ );
1584
+ }
1585
+
1586
+
1587
+
1588
+
1589
+
1590
+ co.beginPath();
1591
+ co.strokeStyle = prevStrokeStyle;
1592
+ co.fillStyle = prevFillStyle;
1593
+ }
1594
+
1595
+
1596
+
1597
+
1598
+
1599
+
1221
1600
  }
1222
1601
 
1223
1602
  startY += vmargin;
@@ -1228,15 +1607,49 @@
1228
1607
 
1229
1608
  co.stroke();
1230
1609
  co.fill();
1231
-
1232
-
1610
+
1611
+ // Under certain circumstances we can cover the shadow
1612
+ // overspill with a white rectangle
1613
+ if (prop['chart,yaxispos'] === 'right') {
1614
+ pa2(co, 'cr % % % %',
1615
+ ca.width - this.gutterRight + prop['chart.variant.threed.offsetx'],
1616
+ '0',
1617
+ this.gutterRight,
1618
+ ca.height
1619
+ );
1620
+ }
1621
+
1622
+
1623
+
1624
+
1625
+
1626
+
1627
+ // Draw the 3d axes AGAIN if the Y axis is on the right
1628
+ if ( prop['chart.yaxispos'] === 'right'
1629
+ && prop['chart.variant'] === '3d'
1630
+ ) {
1631
+ RG.draw3DYAxis(this);
1632
+ }
1233
1633
 
1234
1634
  /**
1235
1635
  * Now the bars are stroke()ed, turn off the shadow
1236
1636
  */
1237
- RG.NoShadow(this);
1637
+ RG.noShadow(this);
1638
+
1639
+
1640
+ //
1641
+ // Reverse the coords arrays as the bars are drawn from the borrom up now
1642
+ //
1643
+ this.coords = RG.arrayReverse(this.coords);
1644
+
1645
+ if (prop['chart.grouping'] === 'grouped') {
1646
+ for (var i=0; i<this.coords2.length; ++i) {
1647
+ this.coords2[i] = RG.arrayReverse(this.coords2[i]);
1648
+ }
1649
+ }
1238
1650
 
1239
- this.RedrawBars();
1651
+
1652
+ this.redrawBars();
1240
1653
  };
1241
1654
 
1242
1655
 
@@ -1254,9 +1667,9 @@
1254
1667
 
1255
1668
  var coords = this.coords;
1256
1669
 
1257
- var font = prop['chart.text.font'];
1258
- var size = prop['chart.text.size'];
1259
- var color = prop['chart.text.color'];
1670
+ var font = prop['chart.text.font'],
1671
+ size = prop['chart.text.size'],
1672
+ color = prop['chart.text.color'];
1260
1673
 
1261
1674
  RG.noShadow(this);
1262
1675
  co.strokeStyle = prop['chart.strokestyle'];
@@ -1304,15 +1717,16 @@
1304
1717
  halign = 'right';
1305
1718
  }
1306
1719
 
1307
- RG.Text2(this, {'font':font,
1308
- 'size':size,
1309
- 'x':x,
1310
- 'y':y,
1311
- 'text': text,
1312
- 'valign':'center',
1313
- 'halign': halign,
1314
- 'tag': 'labels.above'
1315
- });
1720
+ RG.text2(this, {
1721
+ 'font': font,
1722
+ 'size': size,
1723
+ 'x': x,
1724
+ 'y': y,
1725
+ 'text': text,
1726
+ 'valign': 'center',
1727
+ 'halign': halign,
1728
+ 'tag': 'labels.above'
1729
+ });
1316
1730
  }
1317
1731
  }
1318
1732
  };
@@ -1329,34 +1743,40 @@
1329
1743
  this.getShape =
1330
1744
  this.getBar = function (e)
1331
1745
  {
1332
- var mouseCoords = RG.getMouseXY(e);
1746
+ var mouseXY = RG.getMouseXY(e);
1333
1747
 
1334
1748
  /**
1335
1749
  * Loop through the bars determining if the mouse is over a bar
1336
1750
  */
1337
1751
  for (var i=0,len=this.coords.length; i<len; i++) {
1338
1752
 
1339
- var mouseX = mouseCoords[0]; // In relation to the canvas
1340
- var mouseY = mouseCoords[1]; // In relation to the canvas
1341
- var left = this.coords[i][0];
1342
- var top = this.coords[i][1];
1343
- var width = this.coords[i][2];
1344
- var height = this.coords[i][3];
1345
- var idx = i;
1346
-
1347
- if (mouseX >= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) {
1753
+ var mouseX = mouseXY[0], // In relation to the canvas
1754
+ mouseY = mouseXY[1], // In relation to the canvas
1755
+ left = this.coords[i][0],
1756
+ top = this.coords[i][1],
1757
+ width = this.coords[i][2],
1758
+ height = this.coords[i][3],
1759
+ idx = i;
1760
+
1761
+
1762
+
1763
+ // Recreate the path/rectangle so that it can be tested
1764
+ // ** DO NOT STROKE OR FILL IT **
1765
+ pa(co,['b','r',left,top,width,height]);
1766
+
1767
+ if (co.isPointInPath(mouseX, mouseY)) {
1348
1768
 
1349
1769
  var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i);
1350
-
1770
+
1351
1771
  return {
1352
- 0: this, 'object': this,
1353
- 1: left, 'x': left,
1354
- 2: top, 'y': top,
1355
- 3: width, 'width': width,
1356
- 4: height, 'height': height,
1357
- 5: idx, 'index': idx,
1358
- 'tooltip': tooltip
1359
- };
1772
+ 0: this, 'object': this,
1773
+ 1: left, 'x': left,
1774
+ 2: top, 'y': top,
1775
+ 3: width, 'width': width,
1776
+ 4: height, 'height': height,
1777
+ 5: idx, 'index': idx,
1778
+ 'tooltip': tooltip
1779
+ };
1360
1780
  }
1361
1781
  }
1362
1782
  };
@@ -1438,7 +1858,15 @@
1438
1858
  this.getObjectByXY = function (e)
1439
1859
  {
1440
1860
  var mouseXY = RG.getMouseXY(e);
1441
-
1861
+
1862
+ // Adjust the mouse Y coordinate for when the bar chart is
1863
+ // a 3D variant
1864
+ if (prop['chart.variant'] === '3d') {
1865
+ var adjustment = prop['chart.variant.threed.angle'] * mouseXY[0];
1866
+ mouseXY[1] -= adjustment;
1867
+ }
1868
+
1869
+
1442
1870
  if (
1443
1871
  mouseXY[0] > this.gutterLeft
1444
1872
  && mouseXY[0] < (ca.width - this.gutterRight)
@@ -1463,19 +1891,28 @@
1463
1891
  */
1464
1892
  this.positionTooltip = function (obj, x, y, tooltip, idx)
1465
1893
  {
1466
- var coordX = obj.coords[tooltip.__index__][0];
1467
- var coordY = obj.coords[tooltip.__index__][1];
1468
- var coordW = obj.coords[tooltip.__index__][2];
1469
- var coordH = obj.coords[tooltip.__index__][3];
1470
- var canvasXY = RG.getCanvasXY(obj.canvas);
1471
- var gutterLeft = obj.gutterLeft;
1472
- var gutterTop = obj.gutterTop;
1473
- var width = tooltip.offsetWidth;
1474
- var height = tooltip.offsetHeight;
1475
-
1894
+ var coordX = obj.coords[tooltip.__index__][0],
1895
+ coordY = obj.coords[tooltip.__index__][1],
1896
+ coordW = obj.coords[tooltip.__index__][2],
1897
+ coordH = obj.coords[tooltip.__index__][3],
1898
+ canvasXY = RG.getCanvasXY(obj.canvas),
1899
+ gutterLeft = obj.gutterLeft,
1900
+ gutterTop = obj.gutterTop,
1901
+ width = tooltip.offsetWidth,
1902
+ height = tooltip.offsetHeight,
1903
+ mouseXY = RG.getMouseXY(window.event);
1904
+
1905
+ // If the chart is a 3D version the tooltip Y position needs this
1906
+ // adjustment
1907
+ if (prop['chart.variant'] === '3d' && coordW) {
1908
+ var adjustment = (prop['chart.variant.threed.angle'] * ((coordX + coordW) / 2));
1909
+ }
1910
+
1911
+
1912
+
1476
1913
  // Set the top position
1477
1914
  tooltip.style.left = 0;
1478
- tooltip.style.top = canvasXY[1] + coordY + (coordH / 2) - height + 'px';
1915
+ tooltip.style.top = canvasXY[1] + coordY - height + 5 + (adjustment || 0) + 'px';
1479
1916
 
1480
1917
  // By default any overflow is hidden
1481
1918
  tooltip.style.overflow = '';
@@ -1705,36 +2142,36 @@
1705
2142
  */
1706
2143
  this.grow = function ()
1707
2144
  {
1708
- var obj = this;
1709
- var opt = arguments[0] || {};
1710
- var frames = opt.frames || 30;
1711
- var frame = 0;
1712
- var callback = arguments[1] || function () {};
2145
+ var obj = this,
2146
+ opt = arguments[0] || {},
2147
+ frames = opt.frames || 30,
2148
+ frame = 0,
2149
+ callback = arguments[1] || function () {};
1713
2150
 
1714
2151
 
1715
2152
  // Save the data
1716
- obj.original_data = RG.array_clone(obj.data);
2153
+ obj.original_data = RG.arrayClone(obj.data);
1717
2154
 
1718
2155
 
1719
2156
  // Stop the scale from changing by setting chart.ymax (if it's not already set)
1720
- if (obj.Get('chart.xmax') == 0) {
2157
+ if (prop['chart.xmax'] == 0) {
1721
2158
 
1722
2159
  var xmax = 0;
1723
2160
 
1724
2161
  for (var i=0; i<obj.data.length; ++i) {
1725
- if (RG.is_array(obj.data[i]) && obj.Get('chart.grouping') == 'stacked') {
1726
- xmax = Math.max(xmax, RG.array_sum(obj.data[i]));
1727
- } else if (RG.is_array(obj.data[i]) && obj.Get('chart.grouping') == 'grouped') {
1728
- xmax = ma.max(xmax, RG.array_max(obj.data[i]));
2162
+ if (RG.isArray(obj.data[i]) && prop['chart.grouping'] == 'stacked') {
2163
+ xmax = ma.max(xmax, RG.arraySum(obj.data[i]));
2164
+ } else if (RG.isArray(obj.data[i]) && prop['chart.grouping'] == 'grouped') {
2165
+ xmax = ma.max(xmax, RG.arrayMax(obj.data[i]));
1729
2166
  } else {
1730
- xmax = ma.max(xmax, RG.array_max(obj.data[i]));
2167
+ xmax = ma.max(xmax, ma.abs(RG.arrayMax(obj.data[i])));
1731
2168
  }
1732
2169
  }
1733
-
2170
+
1734
2171
  var scale2 = RG.getScale2(obj, {'max':xmax});
1735
2172
  obj.Set('chart.xmax', scale2.max);
1736
2173
  }
1737
-
2174
+
1738
2175
  function iterator ()
1739
2176
  {
1740
2177
  // Alter the Bar chart data depending on the frame
@@ -1743,12 +2180,12 @@
1743
2180
  // This stops the animation from being completely linear
1744
2181
  var easingFactor = RG.Effects.getEasingMultiplier(frames, frame);
1745
2182
 
1746
- if (typeof obj.data[j] === 'object') {
2183
+ if (typeof obj.data[j] === 'object' && obj.data[j]) {
1747
2184
  for (var k=0,len2=obj.data[j].length; k<len2; ++k) {
1748
- obj.data[j][k] = obj.original_data[j][k] * easingFactor;
2185
+ obj.data[j][k] = RG.isNull(obj.data[j][k]) ? null : obj.original_data[j][k] * easingFactor;
1749
2186
  }
1750
2187
  } else {
1751
- obj.data[j] = obj.original_data[j] * easingFactor;
2188
+ obj.data[j] = RG.isNull(obj.data[j]) ? null : obj.original_data[j] * easingFactor;
1752
2189
  }
1753
2190
  }
1754
2191
 
@@ -1771,7 +2208,96 @@
1771
2208
 
1772
2209
 
1773
2210
 
1774
- RG.att(ca);
2211
+
2212
+ /**
2213
+ * (new) Bar chart Wave effect. This is a rewrite that should be smoother
2214
+ * because it just uses a single loop and not setTimeout
2215
+ *
2216
+ * @param object OPTIONAL An object map of options. You specify 'frames' here to give the number of frames in the effect
2217
+ * @param function OPTIONAL A function that will be called when the effect is complete
2218
+ */
2219
+ this.wave = function ()
2220
+ {
2221
+ var obj = this,
2222
+ opt = arguments[0] || {};
2223
+ opt.frames = opt.frames || 60;
2224
+ opt.startFrames = [];
2225
+ opt.counters = [];
2226
+
2227
+ var framesperbar = opt.frames / 3,
2228
+ frame = -1,
2229
+ callback = arguments[1] || function () {},
2230
+ original = RG.arrayClone(obj.data);
2231
+
2232
+ for (var i=0,len=obj.data.length; i<len; i+=1) {
2233
+ opt.startFrames[i] = ((opt.frames / 2) / (obj.data.length - 1)) * i;
2234
+
2235
+ if (typeof obj.data[i] === 'object' && obj.data[i]) {
2236
+ opt.counters[i] = [];
2237
+ for (var j=0; j<obj.data[i].length; j++) {
2238
+ opt.counters[i][j] = 0;
2239
+ }
2240
+ } else {
2241
+ opt.counters[i] = 0;
2242
+ }
2243
+ }
2244
+
2245
+ /**
2246
+ * This stops the chart from jumping
2247
+ */
2248
+ obj.draw();
2249
+ obj.Set('xmax', obj.scale2.max);
2250
+ RG.clear(obj.canvas);
2251
+
2252
+ function iterator ()
2253
+ {
2254
+ ++frame;
2255
+
2256
+ for (var i=0,len=obj.data.length; i<len; i+=1) {
2257
+ if (frame > opt.startFrames[i]) {
2258
+ if (typeof obj.data[i] === 'number') {
2259
+
2260
+ obj.data[i] = ma.min(
2261
+ ma.abs(original[i]),
2262
+ ma.abs(original[i] * ( (opt.counters[i]++) / framesperbar))
2263
+ );
2264
+
2265
+ // Make the number negative if the original was
2266
+ if (original[i] < 0) {
2267
+ obj.data[i] *= -1;
2268
+ }
2269
+ } else if (!RG.isNull(obj.data[i])) {
2270
+ for (var j=0,len2=obj.data[i].length; j<len2; j+=1) {
2271
+
2272
+ obj.data[i][j] = ma.min(
2273
+ ma.abs(original[i][j]),
2274
+ ma.abs(original[i][j] * ( (opt.counters[i][j]++) / framesperbar))
2275
+ );
2276
+
2277
+ // Make the number negative if the original was
2278
+ if (original[i][j] < 0) {
2279
+ obj.data[i][j] *= -1;
2280
+ }
2281
+ }
2282
+ }
2283
+ } else {
2284
+ 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);
2285
+ }
2286
+ }
2287
+
2288
+
2289
+ if (frame >= opt.frames) {
2290
+ callback(obj);
2291
+ } else {
2292
+ RG.redrawCanvas(obj.canvas);
2293
+ RG.Effects.updateCanvas(iterator);
2294
+ }
2295
+ }
2296
+
2297
+ iterator();
2298
+
2299
+ return this;
2300
+ };
1775
2301
 
1776
2302
 
1777
2303