rgraph-rails 1.0.3 → 1.0.4

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 (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