rgraph-rails 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
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
  };