rgraph-rails 1.0.4 → 1.0.5

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 (55) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +1 -0
  3. data/README.md +2 -2
  4. data/lib/rgraph-rails/version.rb +1 -1
  5. data/vendor/assets/images/bullet.png +0 -0
  6. data/vendor/assets/images/facebook-large.png +0 -0
  7. data/vendor/assets/images/google-plus-large.png +0 -0
  8. data/vendor/assets/images/logo.png +0 -0
  9. data/vendor/assets/images/rgraph.jpg +0 -0
  10. data/vendor/assets/javascripts/RGraph.bar.js +533 -242
  11. data/vendor/assets/javascripts/RGraph.bipolar.js +152 -169
  12. data/vendor/assets/javascripts/RGraph.common.annotate.js +2 -2
  13. data/vendor/assets/javascripts/RGraph.common.context.js +2 -2
  14. data/vendor/assets/javascripts/RGraph.common.core.js +688 -373
  15. data/vendor/assets/javascripts/RGraph.common.csv.js +2 -2
  16. data/vendor/assets/javascripts/RGraph.common.deprecated.js +2 -2
  17. data/vendor/assets/javascripts/RGraph.common.dynamic.js +188 -193
  18. data/vendor/assets/javascripts/RGraph.common.effects.js +62 -38
  19. data/vendor/assets/javascripts/RGraph.common.key.js +35 -15
  20. data/vendor/assets/javascripts/RGraph.common.resizing.js +38 -21
  21. data/vendor/assets/javascripts/RGraph.common.sheets.js +2 -2
  22. data/vendor/assets/javascripts/RGraph.common.tooltips.js +48 -40
  23. data/vendor/assets/javascripts/RGraph.common.zoom.js +2 -2
  24. data/vendor/assets/javascripts/RGraph.drawing.background.js +33 -49
  25. data/vendor/assets/javascripts/RGraph.drawing.circle.js +27 -30
  26. data/vendor/assets/javascripts/RGraph.drawing.image.js +23 -26
  27. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +47 -40
  28. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +38 -42
  29. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +24 -28
  30. data/vendor/assets/javascripts/RGraph.drawing.poly.js +25 -39
  31. data/vendor/assets/javascripts/RGraph.drawing.rect.js +27 -32
  32. data/vendor/assets/javascripts/RGraph.drawing.text.js +53 -58
  33. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +24 -29
  34. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +45 -51
  35. data/vendor/assets/javascripts/RGraph.fuel.js +11 -9
  36. data/vendor/assets/javascripts/RGraph.funnel.js +40 -43
  37. data/vendor/assets/javascripts/RGraph.gantt.js +34 -34
  38. data/vendor/assets/javascripts/RGraph.gauge.js +64 -55
  39. data/vendor/assets/javascripts/RGraph.hbar.js +194 -137
  40. data/vendor/assets/javascripts/RGraph.hprogress.js +261 -167
  41. data/vendor/assets/javascripts/RGraph.line.js +520 -512
  42. data/vendor/assets/javascripts/RGraph.meter.js +11 -10
  43. data/vendor/assets/javascripts/RGraph.modaldialog.js +11 -2
  44. data/vendor/assets/javascripts/RGraph.odo.js +11 -9
  45. data/vendor/assets/javascripts/RGraph.pie.js +385 -100
  46. data/vendor/assets/javascripts/RGraph.radar.js +36 -29
  47. data/vendor/assets/javascripts/RGraph.rose.js +58 -41
  48. data/vendor/assets/javascripts/RGraph.rscatter.js +40 -36
  49. data/vendor/assets/javascripts/RGraph.scatter.js +441 -499
  50. data/vendor/assets/javascripts/RGraph.semicircularprogress.js +1015 -0
  51. data/vendor/assets/javascripts/RGraph.thermometer.js +37 -37
  52. data/vendor/assets/javascripts/RGraph.vprogress.js +285 -157
  53. data/vendor/assets/javascripts/RGraph.waterfall.js +62 -62
  54. data/vendor/assets/stylesheets/website.css +30 -16
  55. metadata +3 -2
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZjgxMzVlOTc0MDk3OWJjZjlkOTBkOGQzNTUwYjllODUyZTQ3MmNiNw==
4
+ ZjVkYTI4NTFiZjU0ZTUwZmQ4M2EwMDdlMDU5ZGNjYjA5YzAyMjg5Ng==
5
5
  data.tar.gz: !binary |-
6
- YTcyNDQ3YjczYzE5NTA5ZTNlN2Y2ZjkzODM4Y2RlY2JkNjJhNWU2Mg==
6
+ N2NkZGUyOGFkYjI0YWY2ZWNlMTM3YjI3ZmM5MTE4MjJkN2ZiMjRhZg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NGY5YTU0MjExMDQ3ZmIxYzEwOWZkNTI2YmQxMmRjZTZhYWZhMTdkNTc3NTdk
10
- MTU0MzkzZjIwOGQ5YmFjMjU4NDkyZGI4NTI1YmVkYWUyNzk4NTQwMjQxYjRl
11
- NWQyNTUzMDE1MGFhOWQ0OTljZjRjNGVkMjQ1YTllNzgzYzM4MGE=
9
+ ZDRhMDMwMmUyODg1NTQ4ZDQ5MWNjYWI4MDExOWM1MjFmYWZkNDRkNjdlMzI0
10
+ Nzc4YjI3MDRhNmEwNTFhN2VlN2IyMmQ4ZmViNzQ2MTJiNzJkZTBmZGExYzYy
11
+ NGMyN2NkOTFkYzk5MmM2ZjQ0NWZhMGRiZmFiNjBjMGYyOTBlNzY=
12
12
  data.tar.gz: !binary |-
13
- NmJlOGY0Zjg0YjQ2ZmU3Y2QzYTk5YjBlNjJmNTg5NjdiNTU4NTMxOGJkMzRi
14
- ZjM0MDViNDVlMDBiMmI2MWJlMWY5ZGFiNzFjZGExY2Y1ZTU4ZWRlYTY5NzYw
15
- YTZkNDMyZTJiMGI1MGI2ZGQxZmZkMWFlZDc0NzhiZDk5NmVhNDc=
13
+ ZDY0M2NhZWMzYmU5NGM1NTllYjZmZmVjMjM1MzlmNGMyZDM0YjE0YmRiNWYz
14
+ NjJhN2MyM2MwZjI5MmQ4NTA3ODk1Zjk0MzQ0NjU2YTI1NDdkMjJhZmMzZDEy
15
+ Yjk4OTA3MmY5MTQwMWI1YTMwYTgxMDU1N2EwYTBjNWEzZjI5OGQ=
data/.travis.yml CHANGED
@@ -8,4 +8,5 @@ deploy:
8
8
  api_key:
9
9
  secure: afUjE//0Dbsz5hq99BS5MAq4mS5m+ZQws9nsUTUXr9I1UQud0sng4/0KsCZJkmJeGmmagWPAOJ4uZF5gnl0STmnYVRavLYwjIZ8pesTeh+wofGIXwhuE2T3JzGLlX9NADNk0tm67wWMztTOiZUMtWHjrfApahoH3NO8EblwBd0PrwghNIP3bq8xS5X5FOi02Om+SxD3Px/JFiLHePejiLc4T1Uw2rX2fy3buy0XKz08tLZ0tKVs16vASR8AfsiW2vDLdJ655bv0x4JaDROyIRn+hPr+5xt2OO+HLLK/kEfQDINXrsUve7BOW0zxGEUnjIwDMtBgfkUvPG1yz7yVOQvz585TQ7w/pxRCZ0JfLxv+DVaCVwk9EyAKFFo6oM+i1cWThQiaxy0TPyZV8a/ffhuTcbMzdJbTKeTXmGooY2DuDIEmZ4ldVltVkoy+3mzMTnHyLn4t69M2jEw27Frn/gE/lwMIbgPHaXDkFGqQDT8NYqT3P9KzigRPlq6wrmoCpo8wwwCqENk7iwE0JPtrhgQA4UcmJN1bhwpjIv7S8URj2Ltn/NBxDsxPtLCs6EFUgJ2KRAuK7MGGfGQgJmO0yF6n+OvCji+eFcw+FwKBDspAqo8Y4jBBfrvajSt23KUp6kaw41UGdoTzRqdPXA9RMV16aVBBrk7SLXYm19Zl0+1I=
10
10
  on:
11
+ branch: master
11
12
  tags: true
data/README.md CHANGED
@@ -10,7 +10,7 @@ Use the [rgraph](http://www.rgraph.net/) chart/graph library with the Rails asse
10
10
  Include the gem in your application's Gemfile:
11
11
 
12
12
  ```ruby
13
- gem 'rgraph-rails', '~> 1.0'
13
+ gem 'rgraph-rails', '~> 1.0.5'
14
14
  ```
15
15
 
16
16
  And then execute:
@@ -60,7 +60,7 @@ To install this gem onto your local machine, run `bundle exec rake install`.
60
60
 
61
61
  ## Deployment
62
62
 
63
- Automatically on tagged release. Reading: https://docs.travis-ci.com/user/deployment/rubygems/
63
+ Automatically on tagged release to master. Reading: https://docs.travis-ci.com/user/deployment/rubygems/
64
64
 
65
65
  ## Issues
66
66
 
@@ -1,3 +1,3 @@
1
1
  module RgraphRails
2
- VERSION = "1.0.4"
2
+ VERSION = "1.0.5"
3
3
  end
Binary file
Binary file
Binary file
@@ -1,4 +1,4 @@
1
- // version: 2016-02-06
1
+ // version: 2016-06-04
2
2
  /**
3
3
  * o--------------------------------------------------------------------------------o
4
4
  * | This file is part of the RGraph package - you can learn more at: |
@@ -7,7 +7,7 @@
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 starts at just �99 (GBP) and |
10
+ * | the terms of the GPL. The commercial license starts at just 99GBP and |
11
11
  * | you can read about it here: |
12
12
  * | |
13
13
  * | http://www.rgraph.net/license |
@@ -97,7 +97,7 @@
97
97
  'chart.numyticks': 10,
98
98
  'chart.hmargin': 5,
99
99
  'chart.hmargin.grouped': 1,
100
- 'chart.strokecolor': 'white',
100
+ 'chart.strokecolor': 'rgba(0,0,0,0)',
101
101
  'chart.axis.color': 'black',
102
102
  'chart.axis.linewidth': 1,
103
103
  'chart.gutter.top': 25,
@@ -112,6 +112,7 @@
112
112
  'chart.labels.above.decimals': 0,
113
113
  'chart.labels.above.size': null,
114
114
  'chart.labels.above.color': null,
115
+ 'chart.labels.above.background':'rgba(0,0,0,0)',
115
116
  'chart.labels.above.angle': null,
116
117
  'chart.labels.above.offset': 4,
117
118
  'chart.labels.above.units.pre': '',
@@ -119,13 +120,19 @@
119
120
  'chart.ylabels': true,
120
121
  'chart.ylabels.count': 5,
121
122
  'chart.ylabels.inside': false,
122
- 'chart.xlabels.offset': 0,
123
+ 'chart.ylabels.offsetx': 0,
124
+ 'chart.ylabels.offsety': 0,
125
+ 'chart.labels.offsetx': 0,
126
+ 'chart.labels.offsety': 0,
123
127
  'chart.xaxispos': 'bottom',
124
128
  'chart.yaxispos': 'left',
125
129
  'chart.text.angle': 0,
126
130
  'chart.text.color': 'black', // Gradients aren't supported for this color
127
131
  'chart.text.size': 12,
128
- 'chart.text.font': 'Arial',
132
+ 'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
133
+ 'chart.text.accessible': true,
134
+ 'chart.text.accessible.overflow': 'visible',
135
+ 'chart.text.accessible.pointerevents': false,
129
136
  'chart.ymin': 0,
130
137
  'chart.ymax': null,
131
138
  'chart.title': '',
@@ -213,6 +220,7 @@
213
220
  'chart.scale.point': '.',
214
221
  'chart.scale.thousand': ',',
215
222
  'chart.scale.round': false,
223
+ 'chart.scale.zerostart': true,
216
224
  'chart.crosshairs': false,
217
225
  'chart.crosshairs.color': '#333',
218
226
  'chart.crosshairs.hline': true,
@@ -246,7 +254,8 @@
246
254
  'chart.errorbars.linewidth': 1,
247
255
  'chart.combinedchart.effect': null,
248
256
  'chart.combinedchart.effect.options': null,
249
- 'chart.combinedchart.effect.callback': null
257
+ 'chart.combinedchart.effect.callback': null,
258
+ 'chart.clearto': 'rgba(0,0,0,0)'
250
259
  }
251
260
 
252
261
  // Check for support
@@ -255,6 +264,22 @@
255
264
  return;
256
265
  }
257
266
 
267
+
268
+ //
269
+ // Convert strings into numbers
270
+ //
271
+ for (var i=0; i<data.length; ++i) {
272
+ if (typeof data[i] === 'string') {
273
+ data[i] = parseFloat(data[i]);
274
+ } else if (typeof data[i] === 'object' && data[i]) {
275
+ for (var j=0; j<data[i].length; ++j) {
276
+ if (typeof data[i][j] === 'string') {
277
+ data[i][j] = parseFloat(data[i][j]);
278
+ }
279
+ }
280
+ }
281
+ }
282
+
258
283
  /**
259
284
  * Determine whether the chart will contain stacked or grouped bars
260
285
  */
@@ -311,7 +336,6 @@
311
336
  ca = this.canvas,
312
337
  co = ca.getContext('2d'),
313
338
  prop = this.properties,
314
- pa = RG.Path,
315
339
  pa2 = RG.path2,
316
340
  win = window,
317
341
  doc = document,
@@ -368,10 +392,15 @@
368
392
 
369
393
 
370
394
  // Convert uppercase letters to dot+lower case letter
371
- name = name.replace(/([A-Z])/g, function (str)
372
- {
373
- return '.' + String(RegExp.$1).toLowerCase();
374
- });
395
+ while(name.match(/([A-Z])/)) {
396
+ name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
397
+ }
398
+
399
+
400
+ // BC accommodation
401
+ if (name === 'chart.xlabels.offset') {
402
+ name = 'chart.labels.offsety';
403
+ }
375
404
 
376
405
  if (name == 'chart.labels.abovebar') {
377
406
  name = 'chart.labels.above';
@@ -468,7 +497,11 @@
468
497
  // If the chart is 3d then angle it it
469
498
  //
470
499
  if (prop['chart.variant'] === '3d') {
471
- co.setTransform(1,prop['chart.variant.threed.angle'],0,1,0.5,0.5);
500
+ if (prop['chart.text.accessible']) {
501
+ // Nada
502
+ } else {
503
+ co.setTransform(1,prop['chart.variant.threed.angle'],0,1,0.5,0.5);
504
+ }
472
505
  }
473
506
 
474
507
 
@@ -535,13 +568,13 @@
535
568
 
536
569
 
537
570
  //If it's a sketch chart variant, draw the axes first
538
- if (prop['chart.variant'] == 'sketch') {
539
- this.DrawAxes();
540
- this.Drawbars();
541
- } else {
542
- this.Drawbars();
543
- this.DrawAxes();
544
- }
571
+ //if (prop['chart.variant'] == 'sketch') {
572
+ // this.DrawAxes();
573
+ // this.Drawbars();
574
+ //} else {
575
+ this.drawbars();
576
+ this.drawAxes();
577
+ //}
545
578
 
546
579
  this.DrawLabels();
547
580
 
@@ -682,15 +715,25 @@
682
715
  co.moveTo(this.gutterLeft - (isSketch ? 3 : 0), this.gutterTop - (isSketch ? 3 : 0));
683
716
  co.lineTo(ca.width - this.gutterRight + (isSketch ? 5 : 0), this.gutterTop + (isSketch ? 2 : 0));
684
717
  } else {
685
- co.moveTo(this.gutterLeft - (isSketch ? 5 : 0), ca.height - this.gutterBottom - (isSketch ? 2 : 0));
686
- co.lineTo(ca.width - this.gutterRight + (isSketch ? 8 : 0), ca.height - this.gutterBottom + (isSketch ? 2 : 0));
718
+ co.moveTo(
719
+ this.gutterLeft - (isSketch ? 5 : 0),
720
+ ma.round(this.getYCoord(0) - (isSketch ? 2 : 0))
721
+ );
722
+ co.lineTo(
723
+ ca.width - this.gutterRight + (isSketch ? 8 : 0),
724
+ ma.round(this.getYCoord(0) + (isSketch ? 2 : 0))
725
+ );
726
+
687
727
  }
688
728
  }
689
729
 
690
730
  var numYTicks = prop['chart.numyticks'];
691
731
 
692
- // Draw the Y tickmarks
732
+ //
733
+ // DRAW THE Y TICKMARKS
734
+ //
693
735
  if (prop['chart.noyaxis'] == false && !isSketch) {
736
+
694
737
  var yTickGap = (ca.height - this.gutterTop - this.gutterBottom) / numYTicks;
695
738
  var xpos = yaxispos == 'left' ? this.gutterLeft : ca.width - this.gutterRight;
696
739
 
@@ -698,14 +741,27 @@
698
741
  for (y=this.gutterTop;
699
742
  xaxispos == 'center' ? y <= (ca.height - this.gutterBottom) : y < (ca.height - this.gutterBottom + (xaxispos == 'top' ? 1 : 0));
700
743
  y += yTickGap) {
701
-
702
- if (xaxispos == 'center' && y == (this.gutterTop + (this.grapharea / 2))) continue;
744
+
745
+ if (xaxispos == 'center' && y == (this.gutterTop + (this.grapharea / 2))) {
746
+ continue;
747
+ }
703
748
 
704
749
  // X axis at the top
705
- if (xaxispos == 'top' && y == this.gutterTop) continue;
750
+ if (xaxispos == 'top' && y == this.gutterTop) {
751
+ continue;
752
+ }
706
753
 
707
- co.moveTo(xpos + (yaxispos == 'left' ? 0 : 0), Math.round(y));
708
- co.lineTo(xpos + (yaxispos == 'left' ? -3 : 3), Math.round(y));
754
+ co.moveTo(xpos + (yaxispos == 'left' ? 0 : 0), ma.round(y));
755
+ co.lineTo(xpos + (yaxispos == 'left' ? -3 : 3), ma.round(y));
756
+ }
757
+
758
+ //
759
+ // If the X axis is offset (ie not at the bottom when xaxispos
760
+ // is set to bottom) - draw an extra tick
761
+ //
762
+ if (xaxispos === 'bottom' && prop['chart.ymin'] !== 0) {
763
+ co.moveTo(xpos + (yaxispos == 'left' ? 0 : 0), ma.round(ca.height - prop['chart.gutter.bottom']));
764
+ co.lineTo(xpos + (yaxispos == 'left' ? -3 : 3), ma.round(ca.height - prop['chart.gutter.bottom']));
709
765
  }
710
766
  }
711
767
 
@@ -737,8 +793,8 @@
737
793
  }
738
794
 
739
795
  if (xaxispos == 'bottom') {
740
- yStart = ca.height - this.gutterBottom;
741
- yEnd = (ca.height - this.gutterBottom) + 3;
796
+ yStart = prop['chart.ymin'] < 0 ? this.getYCoord(0) - 3 : this.getYCoord(0);
797
+ yEnd = this.getYCoord(0) + 3;
742
798
  } else if (xaxispos == 'top') {
743
799
  yStart = this.gutterTop - 3;
744
800
  yEnd = this.gutterTop;
@@ -747,8 +803,8 @@
747
803
  yEnd = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop - 3;
748
804
  }
749
805
 
750
- yStart = yStart;
751
- yEnd = yEnd;
806
+ //yStart = yStart;
807
+ //yEnd = yEnd;
752
808
 
753
809
  //////////////// X TICKS ////////////////
754
810
  var noEndXTick = prop['chart.noendxtick'];
@@ -756,23 +812,23 @@
756
812
  for (x=this.gutterLeft + (yaxispos == 'left' ? xTickGap : 0),len=(ca.width - this.gutterRight + (yaxispos == 'left' ? 5 : 0)); x<len; x+=xTickGap) {
757
813
 
758
814
  if (yaxispos == 'left' && !noEndXTick && x > this.gutterLeft) {
759
- co.moveTo(Math.round(x), yStart);
760
- co.lineTo(Math.round(x), yEnd);
815
+ co.moveTo(ma.round(x), yStart);
816
+ co.lineTo(ma.round(x), yEnd);
761
817
 
762
818
  } else if (yaxispos == 'left' && noEndXTick && x > this.gutterLeft && x < (ca.width - this.gutterRight) ) {
763
- co.moveTo(Math.round(x), yStart);
764
- co.lineTo(Math.round(x), yEnd);
819
+ co.moveTo(ma.round(x), yStart);
820
+ co.lineTo(ma.round(x), yEnd);
765
821
 
766
822
  } else if (yaxispos == 'right' && x < (ca.width - this.gutterRight) && !noEndXTick) {
767
- co.moveTo(Math.round(x), yStart);
768
- co.lineTo(Math.round(x), yEnd);
823
+ co.moveTo(ma.round(x), yStart);
824
+ co.lineTo(ma.round(x), yEnd);
769
825
 
770
826
  } else if (yaxispos == 'right' && x < (ca.width - this.gutterRight) && x > (this.gutterLeft) && noEndXTick) {
771
- co.moveTo(Math.round(x), yStart);
772
- co.lineTo(Math.round(x), yEnd);
827
+ co.moveTo(ma.round(x), yStart);
828
+ co.lineTo(ma.round(x), yEnd);
773
829
  }
774
830
  }
775
-
831
+
776
832
  if (prop['chart.noyaxis'] || prop['chart.numxticks'] == null) {
777
833
  if (typeof(prop['chart.numxticks']) == 'number' && prop['chart.numxticks'] > 0) {
778
834
  co.moveTo(Math.round(this.gutterLeft), yStart);
@@ -788,11 +844,11 @@
788
844
  */
789
845
  if (prop['chart.noyaxis'] && prop['chart.noxaxis'] == false && prop['chart.numxticks'] == null) {
790
846
  if (xaxispos == 'center') {
791
- co.moveTo(Math.round(this.gutterLeft), (ca.height / 2) - 3);
792
- co.lineTo(Math.round(this.gutterLeft), (ca.height / 2) + 3);
847
+ co.moveTo(ma.round(this.gutterLeft), (ca.height / 2) - 3);
848
+ co.lineTo(ma.round(this.gutterLeft), (ca.height / 2) + 3);
793
849
  } else {
794
- co.moveTo(Math.round(this.gutterLeft), ca.height - this.gutterBottom);
795
- co.lineTo(Math.round(this.gutterLeft), ca.height - this.gutterBottom + 3);
850
+ co.moveTo(ma.round(this.gutterLeft), ca.height - this.gutterBottom);
851
+ co.lineTo(ma.round(this.gutterLeft), ca.height - this.gutterBottom + 3);
796
852
  }
797
853
  }
798
854
 
@@ -956,34 +1012,51 @@
956
1012
  strokeStyle = prop['chart.strokecolor'],
957
1013
  colors = prop['chart.colors'],
958
1014
  sequentialColorIndex = 0
1015
+
1016
+ var height;
959
1017
 
960
1018
  for (i=0,len=this.data.length; i<len; i+=1) {
961
1019
 
1020
+
1021
+
1022
+
1023
+
962
1024
  // Work out the height
963
1025
  //The width is up outside the loop
964
- var height = ((RGraph.array_sum(this.data[i]) < 0 ? RGraph.array_sum(this.data[i]) + this.scale2.min : RGraph.array_sum(this.data[i]) - this.scale2.min) / (this.scale2.max - this.scale2.min) ) * (ca.height - this.gutterTop - this.gutterBottom);
965
-
966
- // Half the height if the Y axis is at the center
967
- if (xaxispos == 'center') {
968
- height /= 2;
1026
+ if (RG.arraySum(this.data[i]) < 0) {
1027
+ var height = (RG.arraySum(this.data[i]) + this.scale2.min) / (this.scale2.max - this.scale2.min);
1028
+ } else {
1029
+ var height = (RG.arraySum(this.data[i]) - this.scale2.min) / (this.scale2.max - this.scale2.min);
969
1030
  }
1031
+
1032
+ height *= ma.abs(this.getYCoord(this.scale2.max) - this.getYCoord(this.scale2.min));
1033
+
1034
+
1035
+
1036
+
1037
+
970
1038
 
971
1039
  var x = (i * width) + this.gutterLeft;
972
1040
  var y = xaxispos == 'center' ? ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop - height
973
1041
  : ca.height - height - this.gutterBottom;
974
-
1042
+
975
1043
  // xaxispos is top
976
1044
  if (xaxispos == 'top') {
977
- y = this.gutterTop + Math.abs(height);
1045
+ y = this.gutterTop + ma.abs(height);
978
1046
  }
979
1047
 
980
1048
 
981
- // Account for negative lengths - Some browsers (eg Chrome) don't like a negative value
1049
+ // Account for negative lengths - Some browsers don't like a negative value
982
1050
  if (height < 0) {
983
1051
  y += height;
984
- height = Math.abs(height);
1052
+ height = ma.abs(height);
985
1053
  }
986
-
1054
+
1055
+
1056
+
1057
+
1058
+
1059
+
987
1060
  /**
988
1061
  * Turn on the shadow if need be
989
1062
  */
@@ -1000,6 +1073,17 @@
1000
1073
  co.beginPath();
1001
1074
  if (typeof this.data[i] == 'number') {
1002
1075
 
1076
+
1077
+ // If the Y axis is offset change the bar start (the top of the bar)
1078
+ if (xaxispos === 'bottom' && prop['chart.ymin'] < 0) {
1079
+ if (this.data[i] >= 0) {
1080
+ height = ma.abs(this.getYCoord(0) - this.getYCoord(this.data[i]));
1081
+ } else {
1082
+ y = this.getYCoord(0);
1083
+ height = ma.abs(this.getYCoord(0) - this.getYCoord(this.data[i]));
1084
+ }
1085
+ }
1086
+
1003
1087
  var barWidth = width - (2 * hmargin);
1004
1088
 
1005
1089
  /**
@@ -1093,7 +1177,7 @@
1093
1177
 
1094
1178
  // 3D effect
1095
1179
  if (variant == '3d') {
1096
-
1180
+
1097
1181
  var prevStrokeStyle = co.strokeStyle;
1098
1182
  var prevFillStyle = co.fillStyle;
1099
1183
 
@@ -1115,15 +1199,29 @@
1115
1199
  co.moveTo(x + hmargin + barWidth, y);
1116
1200
  co.lineTo(
1117
1201
  x + hmargin + barWidth + prop['chart.variant.threed.offsetx'],
1118
- this.data[i] < 0 && xaxispos === 'bottom' ? (ca.height - this.gutterBottom) : (this.data[i] < 0 && (y - prop['chart.variant.threed.offsety']) < (this.gutterTop + this.halfgrapharea) ? (this.gutterTop + this.halfgrapharea) : (y - prop['chart.variant.threed.offsety']))
1202
+ this.data[i] < 0 && xaxispos === 'bottom' ?
1203
+ this.getYCoord(0) : (
1204
+ this.data[i] < 0 && (y - prop['chart.variant.threed.offsety'])
1205
+ < (this.gutterTop + this.halfgrapharea)
1206
+
1207
+ ?
1208
+
1209
+ (this.gutterTop + this.halfgrapharea)
1210
+
1211
+ : (y - prop['chart.variant.threed.offsety']))
1119
1212
  );
1120
1213
 
1121
- co.lineTo(
1122
- x + hmargin + barWidth + prop['chart.variant.threed.offsetx'],
1123
- this.data[i] < 0 && (y - prop['chart.variant.threed.offsety'] + height) < (this.gutterTop + this.halfgrapharea)
1124
- ? (this.gutterTop + this.halfgrapharea)
1125
- : this.data[i] > 0 ? y - prop['chart.variant.threed.offsety'] + height : ma.min(y - prop['chart.variant.threed.offsety'] + height, ca.height - this.gutterBottom)
1126
- );
1214
+ co.lineTo(
1215
+ x + hmargin + barWidth + prop['chart.variant.threed.offsetx'],
1216
+
1217
+
1218
+ this.data[i] < 0 && (y - prop['chart.variant.threed.offsety'] + height) < (this.gutterTop + this.getYCoord(0))
1219
+ ? this.getYCoord(this.data[i]) - prop['chart.variant.threed.offsety']
1220
+ : (this.data[i] > 0 ?
1221
+ y - prop['chart.variant.threed.offsety'] + height :
1222
+ ma.min(y - prop['chart.variant.threed.offsety'] + height, ca.height - this.gutterBottom)
1223
+ )
1224
+ );
1127
1225
  co.lineTo(x + hmargin + barWidth, y + height);
1128
1226
  co.closePath();
1129
1227
  co.stroke();
@@ -1133,38 +1231,40 @@
1133
1231
 
1134
1232
 
1135
1233
  // Draw the lighter top section
1136
- co.beginPath();
1137
- co.fillStyle = 'rgba(255,255,255,0.5)';
1138
- co.moveTo(x + hmargin, y);
1139
- co.lineTo(x + hmargin + prop['chart.variant.threed.offsetx'], y - prop['chart.variant.threed.offsety']);
1140
- co.lineTo(x + hmargin + prop['chart.variant.threed.offsetx'] + barWidth, y - prop['chart.variant.threed.offsety']);
1141
- co.lineTo(x + hmargin + barWidth, y);
1142
- co.lineTo(x + hmargin, y);
1143
- co.closePath();
1144
- co.stroke();
1145
- co.fill();
1146
-
1234
+ if (this.data[i] > 0) {
1235
+ co.beginPath();
1236
+ co.fillStyle = 'rgba(255,255,255,0.5)';
1237
+ co.moveTo(x + hmargin, y);
1238
+ co.lineTo(x + hmargin + prop['chart.variant.threed.offsetx'], y - prop['chart.variant.threed.offsety']);
1239
+ co.lineTo(x + hmargin + prop['chart.variant.threed.offsetx'] + barWidth, y - prop['chart.variant.threed.offsety']);
1240
+ co.lineTo(x + hmargin + barWidth, y);
1241
+ co.lineTo(x + hmargin, y);
1242
+ co.closePath();
1243
+ co.stroke();
1244
+ co.fill();
1245
+ }
1147
1246
 
1148
1247
 
1149
1248
 
1249
+
1150
1250
  // Draw the darker right side section
1151
1251
  co.beginPath();
1152
1252
  co.fillStyle = 'rgba(0,0,0,0.4)';
1153
1253
  // TL
1154
1254
  co.moveTo(x + hmargin + barWidth, y);
1155
-
1255
+
1156
1256
  // TR
1157
1257
  co.lineTo(
1158
1258
  x + hmargin + barWidth + prop['chart.variant.threed.offsetx'],
1159
- this.data[i] < 0 && xaxispos === 'bottom' ? (ca.height - this.gutterBottom) : (this.data[i] < 0 && (y - prop['chart.variant.threed.offsety']) < (this.gutterTop + this.halfgrapharea) ? (this.gutterTop + this.halfgrapharea) : y - prop['chart.variant.threed.offsety'])
1259
+ this.data[i] < 0 && xaxispos === 'bottom' ? this.getYCoord(0) : (this.data[i] < 0 && (y - prop['chart.variant.threed.offsety']) < (this.gutterTop + this.halfgrapharea) ? (this.gutterTop + this.halfgrapharea) : y - prop['chart.variant.threed.offsety'])
1160
1260
  );
1161
1261
 
1162
1262
  // BR
1163
1263
  co.lineTo(
1164
1264
  x + hmargin + barWidth + prop['chart.variant.threed.offsetx'],
1165
1265
 
1166
- this.data[i] < 0 && (y - prop['chart.variant.threed.offsety'] + height) < (this.gutterTop + this.halfgrapharea)
1167
- ? (this.gutterTop + this.halfgrapharea)
1266
+ this.data[i] < 0 && (y - prop['chart.variant.threed.offsety'] + height) < this.getYCoord(0)
1267
+ ? this.getYCoord(0)
1168
1268
  : this.data[i] > 0 ? y - prop['chart.variant.threed.offsety'] + height : ma.min(y - prop['chart.variant.threed.offsety'] + height, ca.height - this.gutterBottom)
1169
1269
  );
1170
1270
  // BL
@@ -1465,15 +1565,13 @@
1465
1565
  var startY = this.gutterTop + (this.grapharea / 2) - height;
1466
1566
 
1467
1567
  } else {
1468
- var startY = ca.height - this.gutterBottom - height;
1469
- var height = Math.abs(height);
1470
- }
1471
-
1472
- /**
1473
- * Draw MSIE shadow
1474
- */
1475
- if (RGraph.ISOLD && shadow) {
1476
- this.DrawIEShadow([startX, startY, individualBarWidth, height]);
1568
+ var startY = this.getYCoord(0);//ca.height - this.gutterBottom - height;
1569
+ var height = ma.abs(ma.abs(this.getYCoord(this.data[i][j])) - this.getYCoord(0));
1570
+
1571
+ if (this.data[i][j] >= 0) {
1572
+ startY -= height;
1573
+ }
1574
+
1477
1575
  }
1478
1576
 
1479
1577
  co.strokeRect(startX + groupedMargin, startY, individualBarWidth - (2 * groupedMargin), height);
@@ -1486,6 +1584,7 @@
1486
1584
  * Grouped 3D effect
1487
1585
  */
1488
1586
  if (variant == '3d') {
1587
+
1489
1588
  var prevFillStyle = co.fillStyle;
1490
1589
  var prevStrokeStyle = co.strokeStyle;
1491
1590
  var hmarginGrouped = prop['chart.hmargin.grouped'];
@@ -1508,8 +1607,9 @@
1508
1607
  co.moveTo(startX + individualBarWidth - hmarginGrouped - 1, startY);
1509
1608
  co.lineTo(
1510
1609
  startX + individualBarWidth - hmarginGrouped + prop['chart.variant.threed.offsetx'],
1511
- this.data[i][j] < 0 && (startY - prop['chart.variant.threed.offsety']) < (this.gutterTop + this.halfgrapharea) ? (this.gutterTop + this.halfgrapharea) : (startY - prop['chart.variant.threed.offsety'])
1610
+ this.data[i][j] < 0 ? (this.getYCoord(0) + ma.abs(height) - prop['chart.variant.threed.offsety']) : this.getYCoord(0) - height - prop['chart.variant.threed.offsety']
1512
1611
  );
1612
+
1513
1613
  co.lineTo(
1514
1614
  startX + individualBarWidth - hmarginGrouped + prop['chart.variant.threed.offsetx'],
1515
1615
  this.data[i][j] < 0 && (startY + height - prop['chart.variant.threed.offsety']) < (this.gutterTop + this.halfgrapharea) ? (this.gutterTop + this.halfgrapharea) : (startY + height - prop['chart.variant.threed.offsety'])
@@ -1544,14 +1644,23 @@
1544
1644
  // Draw the darker side section
1545
1645
  co.fillStyle = 'rgba(0,0,0,0.4)';
1546
1646
  co.beginPath();
1547
- // BL corner
1548
- co.moveTo(startX + individualBarWidth - hmarginGrouped, startY);
1647
+ // TL corner
1648
+ co.moveTo(
1649
+ startX + individualBarWidth - hmarginGrouped,
1650
+ startY
1651
+ );
1549
1652
 
1550
- // BR corner
1551
- co.lineTo(startX + individualBarWidth + prop['chart.variant.threed.offsetx'] - hmarginGrouped, this.data[i][j] < 0 && (startY - 5) < (this.gutterTop + this.halfgrapharea) ? (this.gutterTop + this.halfgrapharea) : (startY - prop['chart.variant.threed.offsety']));
1653
+
1654
+ co.lineTo(
1655
+ startX + individualBarWidth + prop['chart.variant.threed.offsetx'] - hmarginGrouped,
1656
+ this.data[i][j] < 0 ? (this.getYCoord(0) + ma.abs(height) - prop['chart.variant.threed.offsety']) : this.getYCoord(0) - height - prop['chart.variant.threed.offsety']
1657
+ );
1552
1658
 
1553
1659
  // TR corner
1554
- co.lineTo(startX + individualBarWidth + prop['chart.variant.threed.offsetx'] - hmarginGrouped, this.data[i][j] < 0 && (startY + height - 5) < (this.gutterTop + this.halfgrapharea) ? (this.gutterTop + this.halfgrapharea) : (startY + height - prop['chart.variant.threed.offsety']));
1660
+ co.lineTo(
1661
+ startX + individualBarWidth + prop['chart.variant.threed.offsetx'] - hmarginGrouped,
1662
+ this.data[i][j] < 0 && (startY + height - 5) < (this.gutterTop + this.halfgrapharea) ? (this.gutterTop + this.halfgrapharea) : (startY + height - prop['chart.variant.threed.offsety'])
1663
+ );
1555
1664
 
1556
1665
  // TL corner
1557
1666
  co.lineTo(startX + individualBarWidth - hmarginGrouped, startY + height);
@@ -1617,11 +1726,20 @@
1617
1726
 
1618
1727
  co.closePath();
1619
1728
  }
1620
-
1729
+
1730
+ // If 3D, redraw the right hand Y axis
1731
+ if (prop['chart.variant'] === '3d' && prop['chart.yaxispos'] === 'right') {
1732
+ RG.draw3DYAxis(this);
1733
+ }
1734
+
1735
+
1736
+
1737
+
1738
+
1621
1739
  /**
1622
1740
  * Turn off any shadow
1623
1741
  */
1624
- RGraph.NoShadow(this);
1742
+ RGraph.noShadow(this);
1625
1743
  };
1626
1744
 
1627
1745
 
@@ -1652,7 +1770,8 @@
1652
1770
  */
1653
1771
  if (typeof(labels) == 'object' && labels) {
1654
1772
 
1655
- var yOffset = Number(prop['chart.xlabels.offset']),
1773
+ var yOffset = Number(prop['chart.labels.offsety']),
1774
+ xOffset = Number(prop['chart.labels.offsetx']),
1656
1775
  bold = prop['chart.labels.bold']
1657
1776
 
1658
1777
  /**
@@ -1683,11 +1802,11 @@
1683
1802
 
1684
1803
  for (x=this.gutterLeft + (xTickGap / 2); x<=ca.width - this.gutterRight; x+=xTickGap) {
1685
1804
 
1686
- RGraph.text2(this, {
1805
+ RG.text2(this, {
1687
1806
  'font': font,
1688
1807
  'size': text_size,
1689
- 'x': x,
1690
- 'y': prop['chart.xaxispos'] == 'top' ? this.gutterTop - yOffset - 5: (ca.height - this.gutterBottom) + yOffset + 3,
1808
+ 'x': x + xOffset,
1809
+ 'y': prop['chart.xaxispos'] == 'top' ? this.gutterTop + yOffset - 5: (ca.height - this.gutterBottom) + yOffset + 3,
1691
1810
  'bold': bold,
1692
1811
  'text': String(labels[i++]),
1693
1812
  'valign': prop['chart.xaxispos'] == 'top' ? 'bottom' : valign,
@@ -1732,6 +1851,8 @@
1732
1851
  var font = prop['chart.text.font'];
1733
1852
  var numYLabels = prop['chart.ylabels.count'];
1734
1853
  var ymin = prop['chart.ymin'];
1854
+ var offsetx = prop['chart.ylabels.offsetx'];
1855
+ var offsety = prop['chart.ylabels.offsety'];
1735
1856
 
1736
1857
  if (prop['chart.ylabels.inside'] == true) {
1737
1858
  var xpos = prop['chart.yaxispos'] == 'left' ? this.gutterLeft + 5 : ca.width - this.gutterRight - 5;
@@ -1753,17 +1874,18 @@
1753
1874
  for (var i=0; i<labels.length; ++i) {
1754
1875
 
1755
1876
  var y = this.gutterTop + (grapharea * (i / labels.length)) + (grapharea / labels.length);
1756
-
1757
- RGraph.Text2(this, {'font': font,
1758
- 'size': text_size,
1759
- 'x': xpos,
1760
- 'y': y,
1761
- 'text': String(labels[i]),
1762
- 'valign': 'center',
1763
- 'halign': align,
1764
- 'bordered':boxed,
1765
- 'tag': 'scale'
1766
- });
1877
+
1878
+ RG.text2(this, {
1879
+ 'font': font,
1880
+ 'size': text_size,
1881
+ 'x': xpos + offsetx,
1882
+ 'y': y + offsety,
1883
+ 'text': String(labels[i]),
1884
+ 'valign': 'center',
1885
+ 'halign': align,
1886
+ 'bordered':boxed,
1887
+ 'tag': 'scale'
1888
+ });
1767
1889
  }
1768
1890
 
1769
1891
  return;
@@ -1780,15 +1902,17 @@
1780
1902
  */
1781
1903
  var labels = this.scale2.labels;
1782
1904
  for (var i=0; i<labels.length; ++i) {
1783
- RGraph.Text2(this, {'font': font,
1784
- 'size':text_size,
1785
- 'x':xpos,
1786
- 'y':this.gutterTop + ((this.grapharea / labels.length) * (i + 1)),
1787
- 'text': '-' + labels[i],
1788
- 'valign': 'center',
1789
- 'halign': align,
1790
- 'bordered': boxed,
1791
- 'tag':'scale'});
1905
+ RGraph.Text2(this, {
1906
+ 'font': font,
1907
+ 'size':text_size,
1908
+ 'x':xpos + offsetx,
1909
+ 'y':this.gutterTop + ((this.grapharea / labels.length) * (i + 1)) + offsety,
1910
+ 'text': '-' + labels[i],
1911
+ 'valign': 'center',
1912
+ 'halign': align,
1913
+ 'bordered': boxed,
1914
+ 'tag':'scale'
1915
+ });
1792
1916
  }
1793
1917
 
1794
1918
 
@@ -1803,15 +1927,17 @@
1803
1927
  */
1804
1928
  if (prop['chart.ymin'] != 0 || prop['chart.noxaxis'] || prop['chart.scale.zerostart']) {
1805
1929
 
1806
- RGraph.Text2(this, {'font': font,
1807
- 'size': text_size,
1808
- 'x': xpos,
1809
- 'y': this.gutterTop,
1810
- 'text': (this.scale2.min != 0 ? '-' : '') + RGraph.number_format(this,(this.scale2.min.toFixed((prop['chart.scale.decimals']))), units_pre, units_post),
1811
- 'valign': 'center',
1812
- 'halign': align,
1813
- 'bordered': boxed,
1814
- 'tag': 'scale'});
1930
+ RGraph.Text2(this, {
1931
+ 'font': font,
1932
+ 'size': text_size,
1933
+ 'x': xpos + offsetx,
1934
+ 'y': this.gutterTop + offsety,
1935
+ 'text': (this.scale2.min != 0 ? '-' : '') + RGraph.number_format(this,(this.scale2.min.toFixed((prop['chart.scale.decimals']))), units_pre, units_post),
1936
+ 'valign': 'center',
1937
+ 'halign': align,
1938
+ 'bordered': boxed,
1939
+ 'tag': 'scale'
1940
+ });
1815
1941
  }
1816
1942
 
1817
1943
  }
@@ -1849,6 +1975,8 @@
1849
1975
  var xpos = 0;
1850
1976
  var boxed = false;
1851
1977
  var ymin = prop['chart.ymin'];
1978
+ var offsetx = prop['chart.ylabels.offsetx'];
1979
+ var offsety = prop['chart.ylabels.offsety'];
1852
1980
 
1853
1981
  co.fillStyle = prop['chart.text.color'];
1854
1982
  co.strokeStyle = 'black';
@@ -1887,16 +2015,17 @@
1887
2015
 
1888
2016
  var y = this.gutterTop + ((grapharea / 2) / (labels.length - 1)) * i;
1889
2017
 
1890
- RGraph.Text2(this, {'font':font,
1891
- 'size':text_size,
1892
- 'x':xpos,
1893
- 'y':y,
1894
- 'text':String(labels[i]),
1895
- 'valign':'center',
1896
- 'halign':align,
1897
- 'bordered':boxed,
1898
- 'tag': 'scale'
1899
- });
2018
+ RGraph.Text2(this, {
2019
+ 'font':font,
2020
+ 'size':text_size,
2021
+ 'x':xpos + offsetx,
2022
+ 'y':y + offsety,
2023
+ 'text':String(labels[i]),
2024
+ 'valign':'center',
2025
+ 'halign':align,
2026
+ 'bordered':boxed,
2027
+ 'tag': 'scale'
2028
+ });
1900
2029
  }
1901
2030
 
1902
2031
  // Draw the bottom halves labels
@@ -1904,16 +2033,17 @@
1904
2033
 
1905
2034
  var y = this.gutterTop + (grapharea * (i / ((labels.length - 1) * 2) )) + (grapharea / 2);
1906
2035
 
1907
- RG.Text2(this, {'font':font,
1908
- 'size':text_size,
1909
- 'x':xpos,
1910
- 'y':y,
1911
- 'text':String(labels[labels.length - i - 1]),
1912
- 'valign':'center',
1913
- 'halign':align,
1914
- 'bordered':boxed,
1915
- 'tag': 'scale'
1916
- });
2036
+ RG.Text2(this, {
2037
+ 'font':font,
2038
+ 'size':text_size,
2039
+ 'x':xpos + offsetx,
2040
+ 'y':y + offsety,
2041
+ 'text':String(labels[labels.length - i - 1]),
2042
+ 'valign':'center',
2043
+ 'halign':align,
2044
+ 'bordered':boxed,
2045
+ 'tag': 'scale'
2046
+ });
1917
2047
  }
1918
2048
 
1919
2049
  return;
@@ -1934,7 +2064,19 @@
1934
2064
  for (var i=0; i<this.scale2.labels.length; ++i) {
1935
2065
  var y = this.gutterTop + this.halfgrapharea - ((this.halfgrapharea / numYLabels) * (i + 1));
1936
2066
  var text = this.scale2.labels[i];
1937
- RG.Text2(this, {'font':font, 'size':text_size, 'x':xpos, 'y':y, 'text': text, 'valign':'center', 'halign': align, 'bordered': boxed, 'tag':'scale'});
2067
+ RG.Text2(this, {
2068
+ 'font':font,
2069
+ 'size':text_size,
2070
+ 'x':xpos + offsetx,
2071
+ 'y':y + offsety,
2072
+ 'text':
2073
+ text,
2074
+ 'valign':
2075
+ 'center',
2076
+ 'halign': align,
2077
+ 'bordered': boxed,
2078
+ 'tag':'scale'
2079
+ });
1938
2080
  }
1939
2081
 
1940
2082
  /**
@@ -1943,7 +2085,17 @@
1943
2085
  for (var i=(this.scale2.labels.length - 1); i>=0; --i) {
1944
2086
  var y = this.gutterTop + ((this.halfgrapharea / numYLabels) * (i + 1)) + this.halfgrapharea;
1945
2087
  var text = this.scale2.labels[i];
1946
- RG.Text2(this, {'font':font, 'size':text_size,'x':xpos,'y':y,'text': '-' + text,'valign':'center','halign': align,'bordered': boxed,'tag':'scale'});
2088
+ RG.Text2(this, {
2089
+ 'font':font,
2090
+ 'size':text_size,
2091
+ 'x':xpos + offsetx,
2092
+ 'y':y + offsety,
2093
+ 'text': '-' + text,
2094
+ 'valign':'center',
2095
+ 'halign': align,
2096
+ 'bordered': boxed,
2097
+ 'tag':'scale'
2098
+ });
1947
2099
  }
1948
2100
 
1949
2101
 
@@ -1954,7 +2106,18 @@
1954
2106
  * Show the minimum value if its not zero
1955
2107
  */
1956
2108
  if (this.scale2.min != 0 || prop['chart.scale.zerostart']) {
1957
- RG.Text2(this, {'font':font,'size':text_size, 'x':xpos, 'y':this.gutterTop + this.halfgrapharea,'text': RGraph.number_format(this,(this.scale2.min.toFixed((prop['chart.scale.decimals']))), units_pre, units_post),'valign':'center', 'valign':'center','halign': align, 'bordered': boxed, 'tag':'scale'});
2109
+ RG.Text2(this, {
2110
+ 'font':font,
2111
+ 'size':text_size,
2112
+ 'x':xpos + offsetx,
2113
+ 'y':this.gutterTop + this.halfgrapharea + offsety,
2114
+ 'text': RG.number_format(this,(this.scale2.min.toFixed((prop['chart.scale.decimals']))), units_pre, units_post),
2115
+ 'valign':'center',
2116
+ 'valign':'center',
2117
+ 'halign': align,
2118
+ 'bordered': boxed,
2119
+ 'tag':'scale'
2120
+ });
1958
2121
  }
1959
2122
  }
1960
2123
  };
@@ -1975,7 +2138,9 @@
1975
2138
  align = prop['chart.yaxispos'] == 'left' ? 'right' : 'left',
1976
2139
  font = prop['chart.text.font'],
1977
2140
  numYLabels = prop['chart.ylabels.count'],
1978
- ymin = prop['chart.ymin']
2141
+ ymin = prop['chart.ymin'],
2142
+ offsetx = prop['chart.ylabels.offsetx'],
2143
+ offsety = prop['chart.ylabels.offsety']
1979
2144
 
1980
2145
  co.beginPath();
1981
2146
 
@@ -2002,16 +2167,17 @@
2002
2167
  for (var i=0; i<labels.length; ++i) {
2003
2168
  var y = this.gutterTop + (grapharea * (i / (labels.length - 1)));
2004
2169
 
2005
- RGraph.Text2(this, {'font':font,
2006
- 'size':text_size,
2007
- 'x':xpos,
2008
- 'y':y,
2009
- 'text': labels[i],
2010
- 'valign':'center',
2011
- 'halign': align,
2012
- 'bordered': boxed,
2013
- 'tag':'scale'
2014
- });
2170
+ RGraph.Text2(this, {
2171
+ 'font':font,
2172
+ 'size':text_size,
2173
+ 'x':xpos + offsetx,
2174
+ 'y':y + offsety,
2175
+ 'text': labels[i],
2176
+ 'valign':'center',
2177
+ 'halign': align,
2178
+ 'bordered': boxed,
2179
+ 'tag':'scale'
2180
+ });
2015
2181
  }
2016
2182
 
2017
2183
  return;
@@ -2024,15 +2190,17 @@
2024
2190
 
2025
2191
  for (var i=0; i<numYLabels; ++i) {
2026
2192
  var text = this.scale2.labels[i];
2027
- RGraph.Text2(this, {'font':font,
2028
- 'size':text_size,
2029
- 'x':xpos,
2030
- 'y':this.gutterTop + this.grapharea - ((this.grapharea / numYLabels) * (i+1)),
2031
- 'text': text,
2032
- 'valign':'center',
2033
- 'halign': align,
2034
- 'bordered': boxed,
2035
- 'tag':'scale'});
2193
+ RGraph.Text2(this, {
2194
+ 'font':font,
2195
+ 'size':text_size,
2196
+ 'x':xpos + offsetx,
2197
+ 'y':this.gutterTop + this.grapharea - ((this.grapharea / numYLabels) * (i+1)) + offsety,
2198
+ 'text': text,
2199
+ 'valign':'center',
2200
+ 'halign': align,
2201
+ 'bordered': boxed,
2202
+ 'tag':'scale'
2203
+ });
2036
2204
  }
2037
2205
 
2038
2206
 
@@ -2040,15 +2208,17 @@
2040
2208
  * Show the minimum value if its not zero
2041
2209
  */
2042
2210
  if (prop['chart.ymin'] != 0 || prop['chart.noxaxis'] || prop['chart.scale.zerostart']) {
2043
- RG.Text2(this, {'font':font,
2044
- 'size':text_size,
2045
- 'x':xpos,
2046
- 'y':ca.height - this.gutterBottom,
2047
- 'text': RG.number_format(this,(this.scale2.min.toFixed((prop['chart.scale.decimals']))), units_pre, units_post),
2048
- 'valign':'center',
2049
- 'halign': align,
2050
- 'bordered': boxed,
2051
- 'tag':'scale'});
2211
+ RG.Text2(this, {
2212
+ 'font':font,
2213
+ 'size':text_size,
2214
+ 'x':xpos + offsetx,
2215
+ 'y':ca.height - this.gutterBottom + offsety,
2216
+ 'text': RG.number_format(this,(this.scale2.min.toFixed((prop['chart.scale.decimals']))), units_pre, units_post),
2217
+ 'valign':'center',
2218
+ 'halign': align,
2219
+ 'bordered': boxed,
2220
+ 'tag':'scale'
2221
+ });
2052
2222
  }
2053
2223
 
2054
2224
  co.fill();
@@ -2127,9 +2297,21 @@
2127
2297
  // Recreate the path/rectangle so that it can be tested
2128
2298
  // ** DO NOT STROKE OR FILL IT **
2129
2299
  if (prop['chart.tooltips.hotspot.xonly']) {
2130
- pa(co,['b','r',left,this.gutterTop,width,ca.height - this.gutterBottom]);
2300
+ pa2(co,
2301
+ 'b r % % % %',
2302
+ left,
2303
+ this.gutterTop,
2304
+ width,
2305
+ ca.height - this.gutterBottom
2306
+ );
2131
2307
  } else {
2132
- pa(co,['b','r',left,top,width,height]);
2308
+ pa2(co,
2309
+ 'b r % % % %',
2310
+ left,
2311
+ top,
2312
+ width,
2313
+ height
2314
+ );
2133
2315
  }
2134
2316
 
2135
2317
  if (co.isPointInPath(mouseX, mouseY)) {
@@ -2294,6 +2476,7 @@
2294
2476
  */
2295
2477
  this.getYCoord = function (value)
2296
2478
  {
2479
+
2297
2480
  if (value > this.scale2.max) {
2298
2481
  return null;
2299
2482
  }
@@ -2302,14 +2485,13 @@
2302
2485
  ca = this.canvas,
2303
2486
  prop = this.properties;
2304
2487
 
2305
- var y;
2306
- var xaxispos = prop['chart.xaxispos'];
2488
+ var y, xaxispos = prop['chart.xaxispos'];
2307
2489
 
2308
2490
  if (xaxispos == 'top') {
2309
2491
 
2310
2492
  // Account for negative numbers
2311
2493
  if (value < 0) {
2312
- value = Math.abs(value);
2494
+ value = ma.abs(value);
2313
2495
  }
2314
2496
 
2315
2497
  y = ((value - this.scale2.min) / (this.scale2.max - this.scale2.min)) * this.grapharea;
@@ -2322,16 +2504,17 @@
2322
2504
  y += this.gutterTop;
2323
2505
 
2324
2506
  } else {
2325
-
2507
+
2326
2508
  if (value < this.scale2.min) {
2327
2509
  value = this.scale2.min;
2328
2510
  }
2329
-
2330
- y = ((value - this.scale2.min) / (this.scale2.max - this.scale2.min)) * this.grapharea;
2511
+
2512
+ y = ((value - this.scale2.min) / (this.scale2.max - this.scale2.min));
2513
+ y *= (ca.height - this.gutterTop - this.gutterBottom);
2331
2514
 
2332
2515
  y = ca.height - this.gutterBottom - y;
2333
2516
  }
2334
-
2517
+
2335
2518
  return y;
2336
2519
  };
2337
2520
 
@@ -2345,8 +2528,12 @@
2345
2528
  this.highlight =
2346
2529
  this.Highlight = function (shape)
2347
2530
  {
2348
- // Add the new highlight
2349
- RGraph.Highlight.Rect(this, shape);
2531
+ if (typeof prop['chart.highlight.style'] === 'function') {
2532
+ (prop['chart.highlight.style'])(shape);
2533
+ } else {
2534
+ // Add the new highlight
2535
+ RG.Highlight.Rect(this, shape);
2536
+ }
2350
2537
  };
2351
2538
 
2352
2539
 
@@ -2447,25 +2634,19 @@
2447
2634
  width = tooltip.offsetWidth,
2448
2635
  height = tooltip.offsetHeight,
2449
2636
  value = obj.data_arr[tooltip.__index__]
2450
-
2451
2637
 
2452
- // If the chart is a 3D version the tooltip Y position needs this
2453
- // adjustment
2454
- if (prop['chart.variant'] === '3d' && mouseXY) {
2455
- var adjustment = (prop['chart.variant.threed.angle'] * mouseXY[0]);
2456
- }
2457
2638
 
2458
2639
 
2459
2640
  // Set the top position
2460
2641
  tooltip.style.left = 0;
2461
- tooltip.style.top = canvasXY[1] + coordY - height - 7 + (adjustment || 0) + 'px';
2462
-
2642
+ tooltip.style.top = window.event.pageY - height - 5 + 'px';
2643
+
2463
2644
  /**
2464
2645
  * If the tooltip is for a negative value - position it underneath the bar
2465
2646
  */
2466
- if (value < 0) {
2467
- tooltip.style.top = canvasXY[1] + coordY + coordH + 7 + (adjustment || 0)+ 'px';
2468
- }
2647
+ //if (value < 0) {
2648
+ //tooltip.style.top = canvasXY[1] + coordY + coordH + 'px';
2649
+ //}
2469
2650
 
2470
2651
 
2471
2652
  // By default any overflow is hidden
@@ -2475,35 +2656,37 @@
2475
2656
  // data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAFCAMAAACkeOZkAAAAK3RFWHRDcmVhdGlvbiBUaW1lAFNhdCA2IE9jdCAyMDEyIDEyOjQ5OjMyIC0wMDAw2S1RlgAAAAd0SU1FB9wKBgszM4Ed2k4AAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAEZ0FNQQAAsY8L/GEFAAAACVBMVEX/AAC9vb3//+92Pom0AAAAAXRSTlMAQObYZgAAAB1JREFUeNpjYAABRgY4YGRiRDCZYBwQE8qBMEEcAANCACqByy1sAAAAAElFTkSuQmCC
2476
2657
 
2477
2658
  // The arrow
2478
- var img = new Image();
2479
- img.style.position = 'absolute';
2480
- img.id = '__rgraph_tooltip_pointer__';
2481
- if (value >= 0) {
2482
- img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAFCAYAAACjKgd3AAAARUlEQVQYV2NkQAN79+797+RkhC4M5+/bd47B2dmZEVkBCgcmgcsgbAaA9GA1BCSBbhAuA/AagmwQPgMIGgIzCD0M0AMMAEFVIAa6UQgcAAAAAElFTkSuQmCC';
2483
- img.style.top = (tooltip.offsetHeight - 2) + 'px';
2484
- } else {
2485
- img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAFCAMAAACkeOZkAAAAK3RFWHRDcmVhdGlvbiBUaW1lAFNhdCA2IE9jdCAyMDEyIDEyOjQ5OjMyIC0wMDAw2S1RlgAAAAd0SU1FB9wKBgszM4Ed2k4AAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAEZ0FNQQAAsY8L/GEFAAAACVBMVEX/AAC9vb3//+92Pom0AAAAAXRSTlMAQObYZgAAAB1JREFUeNpjYAABRgY4YGRiRDCZYBwQE8qBMEEcAANCACqByy1sAAAAAElFTkSuQmCC';
2486
- img.style.top = '-5px';
2487
- }
2488
-
2489
- tooltip.appendChild(img);
2659
+ //var img = new Image();
2660
+ // img.style.position = 'absolute';
2661
+ // img.id = '__rgraph_tooltip_pointer__';
2662
+ // if (value >= 0) {
2663
+ // //img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAICAYAAAAm06XyAAAARUlEQVQYV2P8///TfwYyASNIHzkGMDLyMYI1k2oASCNID1wzsQbANGJoJmQAskasmnEZgK4Rp2Z0A7BpxKsZZgAujSB5AB8hH/j9emSYAAAAAElFTkSuQmCC';
2664
+ // img.src = '/images/tooltips-pointer-large.png?jkl';
2665
+ // img.style.top = tooltip.offsetHeight + 'px';
2666
+ // } else {
2667
+ // img.src = '/images/tooltips-pointer-large.png?jkl';
2668
+ // //img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAICAYAAAAm06XyAAAARUlEQVQYV2P8///TfwYyASNIHzkGMDLyMYI1k2oASCNID1wzsQbANGJoJmQAskasmnEZgK4Rp2Z0A7BpxKsZZgAujSB5AB8hH/j9emSYAAAAAElFTkSuQmCC';
2669
+ // img.style.top = '-5px';
2670
+ // }
2671
+ //
2672
+ //tooltip.appendChild(img);
2490
2673
 
2491
2674
  // Reposition the tooltip if at the edges:
2492
2675
 
2493
2676
  // LEFT edge
2494
2677
  if ((canvasXY[0] + coordX + (coordW / 2) - (width / 2)) < 10) {
2495
- tooltip.style.left = (canvasXY[0] + coordX - (width * 0.1)) + (coordW / 2) + 'px';
2496
- img.style.left = ((width * 0.1) - 8.5) + 'px';
2678
+ tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
2679
+ //img.style.left = ((width * 0.1) - 8.5) + 'px';
2497
2680
 
2498
2681
  // RIGHT edge
2499
2682
  } else if ((canvasXY[0] + coordX + (width / 2)) > doc.body.offsetWidth) {
2500
- tooltip.style.left = canvasXY[0] + coordX - (width * 0.9) + (coordW / 2) + 'px';
2501
- img.style.left = ((width * 0.9) - 8.5) + 'px';
2683
+ tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
2684
+ //img.style.left = ((width * 0.9) - 8.5) + 'px';
2502
2685
 
2503
2686
  // Default positioning - CENTERED
2504
2687
  } else {
2505
- tooltip.style.left = (canvasXY[0] + coordX + (coordW / 2) - (width * 0.5)) + 'px';
2506
- img.style.left = ((width * 0.5) - 8.5) + 'px';
2688
+ tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
2689
+ //img.style.left = ((width * 0.5) - 8.5) + 'px';
2507
2690
  }
2508
2691
  };
2509
2692
 
@@ -2758,6 +2941,7 @@
2758
2941
  var labels = prop['chart.labels.above'],
2759
2942
  specific = prop['chart.labels.above.specific'],
2760
2943
  color = prop['chart.labels.above.color'],
2944
+ background= prop['chart.labels.above.background'],
2761
2945
  decimals = prop['chart.labels.above.decimals'],
2762
2946
  size = prop['chart.labels.above.size'],
2763
2947
  angle = -1 * prop['chart.labels.above.angle'],
@@ -2801,7 +2985,9 @@
2801
2985
  'valign': valign,
2802
2986
  'angle': angle,
2803
2987
  'marker': false,
2804
- 'bounding': false,
2988
+ 'bounding': true,
2989
+ 'bounding.fill': background,
2990
+ 'bounding.stroke': 'rgba(0,0,0,0)',
2805
2991
  'tag': 'labels.above'
2806
2992
  });
2807
2993
 
@@ -2829,7 +3015,9 @@
2829
3015
  'halign': halign,
2830
3016
  'valign': valign,
2831
3017
  'angle': angle,
2832
- 'bounding': false,
3018
+ 'bounding': true,
3019
+ 'bounding.fill': background,
3020
+ 'bounding.stroke': 'rgba(0,0,0,0)',
2833
3021
  'marker': false,
2834
3022
  'tag': 'labels.above'
2835
3023
  });
@@ -2861,7 +3049,9 @@
2861
3049
  'halign': halign,
2862
3050
  'valign': valign,
2863
3051
  'angle': angle,
2864
- 'bounding': false,
3052
+ 'bounding': true,
3053
+ 'bounding.fill': background,
3054
+ 'bounding.stroke': 'rgba(0,0,0,0)',
2865
3055
  'marker': false,
2866
3056
  'tag': 'labels.above'
2867
3057
  });
@@ -2894,7 +3084,9 @@
2894
3084
  'halign': halign,
2895
3085
  'valign': valign,
2896
3086
  'angle': angle,
2897
- 'bounding': false,
3087
+ 'bounding': true,
3088
+ 'bounding.fill': background,
3089
+ 'bounding.stroke': 'rgba(0,0,0,0)',
2898
3090
  'marker': false,
2899
3091
  'tag': 'labels.above'
2900
3092
  });
@@ -2919,7 +3111,9 @@
2919
3111
  'halign': halign,
2920
3112
  'valign': valign,
2921
3113
  'angle': angle,
2922
- 'bounding': false,
3114
+ 'bounding': true,
3115
+ 'bounding.fill': background,
3116
+ 'bounding.stroke': 'rgba(0,0,0,0)',
2923
3117
  'marker': false,
2924
3118
  'tag': 'labels.above'
2925
3119
  });
@@ -3018,16 +3212,23 @@
3018
3212
  this.wave = function ()
3019
3213
  {
3020
3214
  var obj = this,
3021
- opt = arguments[0] || {};
3022
- opt.frames = opt.frames || 60;
3023
- opt.startFrames = [];
3024
- opt.counters = [];
3215
+ opt = arguments[0] || {},
3216
+ labelsAbove = this.get('labelsAbove');
3217
+
3218
+ opt.frames = opt.frames || 60;
3219
+ opt.startFrames = [];
3220
+ opt.counters = [];
3025
3221
 
3026
3222
  var framesperbar = opt.frames / 3,
3027
3223
  frame = -1,
3028
3224
  callback = arguments[1] || function () {},
3029
3225
  original = RG.arrayClone(obj.data);
3030
3226
 
3227
+ //
3228
+ // turn off the labelsAbove option whilst animating
3229
+ //
3230
+ this.set('labelsAbove', false);
3231
+
3031
3232
  for (var i=0,len=obj.data.length; i<len; i+=1) {
3032
3233
  opt.startFrames[i] = ((opt.frames / 2) / (obj.data.length - 1)) * i;
3033
3234
 
@@ -3085,6 +3286,86 @@
3085
3286
  }
3086
3287
 
3087
3288
 
3289
+ if (frame >= opt.frames) {
3290
+
3291
+ if (labelsAbove) {
3292
+ obj.set('labelsAbove', true);
3293
+ RG.redraw();
3294
+ }
3295
+
3296
+ callback(obj);
3297
+ } else {
3298
+ RG.redrawCanvas(obj.canvas);
3299
+ RG.Effects.updateCanvas(iterator);
3300
+ }
3301
+ }
3302
+
3303
+ iterator();
3304
+
3305
+ return this;
3306
+ };
3307
+
3308
+
3309
+
3310
+
3311
+ /**
3312
+ * Color Wave effect. This fades in color sequentially like the wave effect
3313
+ * makes the bars grow.
3314
+ *
3315
+ * @param object OPTIONAL An object map of options. You specify 'frames'
3316
+ * here to give the number of frames in the effect
3317
+ * @param function OPTIONAL A function that will be called when the effect
3318
+ * is complete
3319
+ */
3320
+ this.colorWave = function ()
3321
+ {
3322
+ var obj = this,
3323
+ opt = arguments[0] || {};
3324
+ opt.frames = opt.frames || 60;
3325
+ opt.startFrames = [];
3326
+ opt.counters = [],
3327
+ colors = obj.properties['chart.colors'];
3328
+
3329
+ // If just one color is specified and colorsSequential is not, then
3330
+ // pad the colors array out
3331
+ if (colors.length <= obj.data.length) {
3332
+ obj.set('chart.colors.sequential', true);
3333
+ colors = RG.arrayPad(colors, obj.data.length, colors[colors.length - 1]);
3334
+ }
3335
+
3336
+ var framesperbar = opt.frames / 2,
3337
+ frame = -1,
3338
+ callback = arguments[1] || function () {},
3339
+ originalColors = RG.arrayClone(obj.properties['chart.colors']);
3340
+
3341
+
3342
+
3343
+ for (var i=0,len=originalColors.length; i<len; i+=1) {
3344
+ opt.startFrames[i] = ((opt.frames / 2) / (originalColors.length - 1)) * i;
3345
+ opt.counters[i] = 0;
3346
+ }
3347
+
3348
+
3349
+ function iterator ()
3350
+ {
3351
+ ++frame;
3352
+
3353
+ for (var i=0,len=colors.length; i<len; i+=1) {
3354
+ if (frame > opt.startFrames[i] && colors[i].match(/^rgba?\(([0-9 ]+),([0-9 ]+),([0-9 ]+)(,([ 0-9.]+)?)\)/)) {
3355
+
3356
+ // DO NOT USE SPACES!
3357
+ colors[i] = 'rgba({1},{2},{3},{4})'.format(
3358
+ RegExp.$1,
3359
+ RegExp.$2,
3360
+ RegExp.$3,
3361
+ (frame - opt.startFrames[i]) / framesperbar
3362
+ );
3363
+ } else {
3364
+ colors[i] = colors[i].replace(/,[0-9. ]+\)/, ',0)');
3365
+ }
3366
+ }
3367
+
3368
+
3088
3369
  if (frame >= opt.frames) {
3089
3370
  callback(obj);
3090
3371
  } else {
@@ -3112,14 +3393,20 @@
3112
3393
  this.grow = function ()
3113
3394
  {
3114
3395
  // Callback
3115
- var opt = arguments[0] || {};
3116
- var frames = opt.frames || 30;
3117
- var frame = 0;
3118
- var callback = arguments[1] || function () {};
3119
- var obj = this;
3396
+ var opt = arguments[0] || {},
3397
+ frames = opt.frames || 30,
3398
+ frame = 0,
3399
+ callback = arguments[1] || function () {},
3400
+ obj = this,
3401
+ labelsAbove = this.get('labelsAbove')
3402
+
3403
+ //
3404
+ // turn off the labelsAbove option whilst animating
3405
+ //
3406
+ this.set('labelsAbove', false);
3120
3407
 
3121
3408
  // Save the data
3122
- obj.original_data = RG.arrayClone(obj.data);
3409
+ this.original_data = RG.arrayClone(this.data);
3123
3410
 
3124
3411
 
3125
3412
  // Stop the scale from changing by setting chart.ymax (if it's not already set)
@@ -3128,24 +3415,24 @@
3128
3415
  var ymax = 0;
3129
3416
 
3130
3417
  for (var i=0; i<obj.data.length; ++i) {
3131
- if (RG.isArray(obj.data[i]) && prop['chart.grouping'] === 'stacked') {
3132
- ymax = ma.max(ymax, ma.abs(RG.arraySum(obj.data[i])));
3418
+ if (RG.isArray(this.data[i]) && prop['chart.grouping'] === 'stacked') {
3419
+ ymax = ma.max(ymax, ma.abs(RG.arraySum(this.data[i])));
3133
3420
 
3134
- } else if (RG.isArray(obj.data[i]) && prop['chart.grouping'] === 'grouped') {
3421
+ } else if (RG.isArray(this.data[i]) && prop['chart.grouping'] === 'grouped') {
3135
3422
 
3136
- for (var j=0,group=[]; j<obj.data[i].length; j++) {
3137
- group.push(ma.abs(obj.data[i][j]));
3423
+ for (var j=0,group=[]; j<this.data[i].length; j++) {
3424
+ group.push(ma.abs(this.data[i][j]));
3138
3425
  }
3139
3426
 
3140
3427
  ymax = ma.max(ymax, ma.abs(RG.arrayMax(group)));
3141
3428
 
3142
3429
  } else {
3143
- ymax = ma.max(ymax, ma.abs(obj.data[i]));
3430
+ ymax = ma.max(ymax, ma.abs(this.data[i]));
3144
3431
  }
3145
3432
  }
3146
3433
 
3147
- var scale = RG.getScale2(obj, {'max':ymax});
3148
- obj.Set('chart.ymax', scale.max);
3434
+ var scale = RG.getScale2(this, {'max':ymax});
3435
+ this.Set('chart.ymax', scale.max);
3149
3436
  }
3150
3437
 
3151
3438
 
@@ -3181,6 +3468,10 @@
3181
3468
 
3182
3469
  // Call the callback function
3183
3470
  } else {
3471
+ if (labelsAbove) {
3472
+ obj.set('labelsAbove', true);
3473
+ RG.redraw();
3474
+ }
3184
3475
  callback(obj);
3185
3476
  }
3186
3477
  };