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
@@ -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 is just 99 (GBP) and you can |
10
+ * | the terms of the GPL. The commercial license is just 99 GBP and you can |
11
11
  * | read about it here: |
12
12
  * | http://www.rgraph.net/license |
13
13
  * o--------------------------------------------------------------------------------o
@@ -56,6 +56,7 @@
56
56
  this.coords.key = [];
57
57
  this.coordsText = [];
58
58
  this.coordsSpline = [];
59
+ this.coordsAxes = {xaxis: [], yaxis: []};
59
60
  this.hasnegativevalues = false;
60
61
  this.isRGraph = true;
61
62
  this.uid = RGraph.CreateUID();
@@ -114,6 +115,8 @@
114
115
  'chart.labels.above.units.pre': '',
115
116
  'chart.labels.above.units.post': '',
116
117
  'chart.labels.above.specific': null,
118
+ 'chart.labels.offsetx': 0,
119
+ 'chart.labels.offsety': 0,
117
120
  'chart.xtickgap': 20,
118
121
  'chart.smallxticks': 3,
119
122
  'chart.largexticks': 5,
@@ -143,12 +146,16 @@
143
146
  'chart.yaxispoints': 5,
144
147
  'chart.fillstyle': null,
145
148
  'chart.xaxispos': 'bottom',
149
+ 'chart.xaxispos.value': 0,
146
150
  'chart.yaxispos': 'left',
147
151
  'chart.xticks': null,
148
152
  'chart.text.size': 12,
149
153
  'chart.text.angle': 0,
150
154
  'chart.text.color': 'black',
151
- 'chart.text.font': 'Arial',
155
+ 'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
156
+ 'chart.text.accessible': true,
157
+ 'chart.text.accessible.overflow': 'visible',
158
+ 'chart.text.accessible.pointerevents': false,
152
159
  'chart.ymin': 0,
153
160
  'chart.ymax': null,
154
161
  'chart.title': '',
@@ -189,6 +196,7 @@
189
196
  'chart.tooltips.event': 'onmousemove',
190
197
  'chart.tooltips.highlight': true,
191
198
  'chart.tooltips.coords.page': false,
199
+ 'chart.highlight.style': null,
192
200
  'chart.highlight.stroke': 'gray',
193
201
  'chart.highlight.fill': 'white',
194
202
  'chart.stepped': false,
@@ -216,7 +224,9 @@
216
224
  'chart.ylabels': true,
217
225
  'chart.ylabels.count': 5,
218
226
  'chart.ylabels.inside': false,
219
- 'chart.scale.invert': false,
227
+ 'chart.ylabels.offsetx': 0,
228
+ 'chart.ylabels.offsety': 0,
229
+ 'chart.scale.invert': false,
220
230
  'chart.xlabels.inside': false,
221
231
  'chart.xlabels.inside.color': 'rgba(255,255,255,0.5)',
222
232
  'chart.noaxes': false,
@@ -226,7 +236,7 @@
226
236
  'chart.noendytick': false,
227
237
  'chart.units.post': '',
228
238
  'chart.units.pre': '',
229
- 'chart.scale.zerostart': false,
239
+ 'chart.scale.zerostart': true,
230
240
  'chart.scale.decimals': null,
231
241
  'chart.scale.point': '.',
232
242
  'chart.scale.thousand': ',',
@@ -274,7 +284,7 @@
274
284
  'chart.animation.unfold.initial': 2,
275
285
  'chart.animation.trace.clip': 1,
276
286
  'chart.curvy': false,
277
- 'chart.line.visible': true,
287
+ 'chart.line.visible': [],
278
288
  'chart.events.click': null,
279
289
  'chart.events.mousemove': null,
280
290
  'chart.errorbars': false,
@@ -284,7 +294,8 @@
284
294
  'chart.errorbars.linewidth': 1,
285
295
  'chart.combinedchart.effect': null,
286
296
  'chart.combinedchart.effect.options': null,
287
- 'chart.combinedchart.effect.callback': null
297
+ 'chart.combinedchart.effect.callback': null,
298
+ 'chart.clearto': 'rgba(0,0,0,0)'
288
299
  }
289
300
 
290
301
  /**
@@ -349,10 +360,20 @@
349
360
  return;
350
361
  }
351
362
 
363
+ // Convert strings to numbers
364
+ for (var i=0; i<this.original_data.length; ++i) {
365
+ for (var j=0; j<this.original_data[i].length; ++j) {
366
+ if (typeof this.original_data[i][j] === 'string') {
367
+ this.original_data[i][j] = parseFloat(this.original_data[i][j]);
368
+ }
369
+ }
370
+ }
371
+
372
+
352
373
  /**
353
374
  * Store the data here as one big array
354
375
  */
355
- this.data_arr = RGraph.array_linearize(this.original_data);
376
+ this.data_arr = RGraph.arrayLinearize(this.original_data);
356
377
 
357
378
  for (var i=0; i<this.data_arr.length; ++i) {
358
379
  this['$' + i] = {};
@@ -377,7 +398,6 @@
377
398
  ca = this.canvas,
378
399
  co = ca.getContext('2d'),
379
400
  prop = this.properties,
380
- pa = RG.Path,
381
401
  pa2 = RG.path2,
382
402
  win = window,
383
403
  doc = document,
@@ -391,12 +411,8 @@
391
411
  if (RG.Effects && typeof RG.Effects.decorate === 'function') {
392
412
  RG.Effects.decorate(this);
393
413
  }
414
+
394
415
 
395
- //
396
- // Wrap the canvas with a DIV so that DOM text can be positioned
397
- // accurately
398
- //
399
- //RG.wrap(ca);
400
416
 
401
417
 
402
418
 
@@ -435,10 +451,9 @@
435
451
 
436
452
 
437
453
  // Convert uppercase letters to dot+lower case letter
438
- name = name.replace(/([A-Z])/g, function (str)
439
- {
440
- return '.' + String(RegExp.$1).toLowerCase();
441
- });
454
+ while(name.match(/([A-Z])/)) {
455
+ name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
456
+ }
442
457
 
443
458
 
444
459
 
@@ -676,18 +691,18 @@
676
691
  this.min = prop['chart.ymin'] ? prop['chart.ymin'] : 0;
677
692
 
678
693
  this.scale2 = RG.getScale2(this, {
679
- 'max':this.max,
680
- 'min':prop['chart.ymin'],
681
- 'strict':true,
682
- 'scale.thousand':prop['chart.scale.thousand'],
683
- 'scale.point':prop['chart.scale.point'],
684
- 'scale.decimals':prop['chart.scale.decimals'],
685
- 'ylabels.count':prop['chart.ylabels.count'],
686
- 'scale.round':prop['chart.scale.round'],
687
- 'units.pre': prop['chart.units.pre'],
688
- 'units.post': prop['chart.units.post']
689
- });
690
-
694
+ 'max':this.max,
695
+ 'min':prop['chart.ymin'],
696
+ 'strict':true,
697
+ 'scale.thousand':prop['chart.scale.thousand'],
698
+ 'scale.point':prop['chart.scale.point'],
699
+ 'scale.decimals':prop['chart.scale.decimals'],
700
+ 'ylabels.count':prop['chart.ylabels.count'],
701
+ 'scale.round':prop['chart.scale.round'],
702
+ 'units.pre': prop['chart.units.pre'],
703
+ 'units.post': prop['chart.units.post']
704
+ });
705
+
691
706
  this.max = this.scale2.max ? this.scale2.max : 0;
692
707
 
693
708
  // Check for negative values
@@ -757,11 +772,11 @@
757
772
 
758
773
  // Check the combination of the X axis position and if there any negative values
759
774
  //
760
- // 19th Dec 2010 - removed for Opera since it can be reported incorrectly whn there
761
- // are multiple graphs on the page
762
- if (prop['chart.xaxispos'] == 'bottom' && this.hasnegativevalues && !RG.ISOPERA) {
763
- alert('[LINE] You have negative values and the X axis is at the bottom. This is not good...');
764
- }
775
+ // 25th Feb 2016 - Removed entirely as this is another way to do
776
+ // offset axes
777
+ //if (prop['chart.xaxispos'] == 'bottom' && this.hasnegativevalues && !RG.ISOPERA) {
778
+ // alert('[LINE] You have negative values and the X axis is at the bottom. This is not good...');
779
+ //}
765
780
 
766
781
  if (prop['chart.variant'] == '3d') {
767
782
  RG.Draw3DAxes(this);
@@ -884,7 +899,7 @@
884
899
 
885
900
  co.beginPath();
886
901
  co.lineWidth = this.GetLineWidth(i);
887
- co.strokeStyle = prop['chart.colors'][i];
902
+ co.strokeStyle = !this.hidden(i) ? prop['chart.colors'][i] : 'rgba(0,0,0,0)';
888
903
 
889
904
  for (var j=0,len=this.coords2[i].length; j<len; ++j) {
890
905
 
@@ -919,15 +934,18 @@
919
934
 
920
935
  var tickmarks = typeof(prop['chart.tickmarks']) == 'object' ? prop['chart.tickmarks'][i] : prop['chart.tickmarks'];
921
936
 
922
- this.DrawTick( this.coords2[i],
923
- this.coords2[i][j][0],
924
- this.coords2[i][j][1],
925
- co.strokeStyle,
926
- false,
927
- j == 0 ? 0 : this.coords2[i][j - 1][0],
928
- j == 0 ? 0 : this.coords2[i][j - 1][1],
929
- tickmarks,
930
- j);
937
+ this.DrawTick(
938
+ this.coords2[i],
939
+ this.coords2[i][j][0],
940
+ this.coords2[i][j][1],
941
+ co.strokeStyle,
942
+ false,
943
+ j == 0 ? 0 : this.coords2[i][j - 1][0],
944
+ j == 0 ? 0 : this.coords2[i][j - 1][1],
945
+ tickmarks,
946
+ j,
947
+ i
948
+ );
931
949
  }
932
950
  }
933
951
  }
@@ -967,15 +985,18 @@
967
985
 
968
986
  var tickmarks = typeof prop['chart.tickmarks'] == 'object' && !RGraph.is_null(prop['chart.tickmarks']) ? prop['chart.tickmarks'][i] : prop['chart.tickmarks'];
969
987
  co.strokeStyle = prop['chart.colors'][i];
970
- this.DrawTick( this.coords2[i],
971
- this.coords2[i][j][0],
972
- this.coords2[i][j][1],
973
- prop['chart.colors'][i],
974
- false,
975
- j == 0 ? 0 : this.coords2[i][j - 1][0],
976
- j == 0 ? 0 : this.coords2[i][j - 1][1],
977
- tickmarks,
978
- j);
988
+ this.DrawTick(
989
+ this.coords2[i],
990
+ this.coords2[i][j][0],
991
+ this.coords2[i][j][1],
992
+ prop['chart.colors'][i],
993
+ false,
994
+ j == 0 ? 0 : this.coords2[i][j - 1][0],
995
+ j == 0 ? 0 : this.coords2[i][j - 1][1],
996
+ tickmarks,
997
+ j,
998
+ i
999
+ );
979
1000
  }
980
1001
  }
981
1002
  }
@@ -1007,7 +1028,7 @@
1007
1028
  * Draw the range if necessary
1008
1029
  */
1009
1030
  this.DrawRange();
1010
-
1031
+
1011
1032
  // Draw a key if necessary
1012
1033
  if (prop['chart.key'] && prop['chart.key'].length && RG.DrawKey) {
1013
1034
  RG.DrawKey(this, prop['chart.key'], prop['chart.colors']);
@@ -1024,7 +1045,7 @@
1024
1045
  * Draw the "in graph" labels
1025
1046
  */
1026
1047
  RG.DrawInGraphLabels(this);
1027
-
1048
+
1028
1049
  /**
1029
1050
  * Redraw the lines if a filled range is on the cards
1030
1051
  */
@@ -1033,11 +1054,11 @@
1033
1054
  co.beginPath();
1034
1055
  var len = this.coords.length / 2;
1035
1056
  co.lineWidth = prop['chart.linewidth'];
1036
- co.strokeStyle = prop['chart.colors'][0];
1057
+ co.strokeStyle = this.hidden(0) ? 'rgba(0,0,0,0)' : prop['chart.colors'][0];
1037
1058
 
1038
1059
  for (var i=0; i<len; ++i) {
1039
1060
 
1040
- if (!RG.is_null(this.coords[i][1])) {
1061
+ if (!RG.isNull(this.coords[i][1])) {
1041
1062
  if (i == 0) {
1042
1063
  co.moveTo(this.coords[i][0], this.coords[i][1]);
1043
1064
  } else {
@@ -1052,7 +1073,7 @@
1052
1073
  co.beginPath();
1053
1074
 
1054
1075
  if (prop['chart.colors'][1]) {
1055
- co.strokeStyle = prop['chart.colors'][1];
1076
+ co.strokeStyle = this.hidden(1) ? 'rgba(0,0,0,0)' : prop['chart.colors'][1];
1056
1077
  }
1057
1078
 
1058
1079
  for (var i=this.coords.length - 1; i>=len; --i) {
@@ -1071,7 +1092,7 @@
1071
1092
  } else if (prop['chart.filled'] && prop['chart.filled.range']) {
1072
1093
  alert('[LINE] You must have only two sets of data for a filled range chart');
1073
1094
  }
1074
-
1095
+
1075
1096
  /**
1076
1097
  * This function enables resizing
1077
1098
  */
@@ -1144,22 +1165,49 @@
1144
1165
 
1145
1166
  co.lineWidth = prop['chart.axis.linewidth'] + 0.001;
1146
1167
  co.lineCap = 'square';
1147
- co.lineJoin = 'miter';
1168
+ co.lineJoin = 'miter';
1148
1169
  co.strokeStyle = prop['chart.axis.color'];
1170
+ coords = {
1171
+ xaxis: {},
1172
+ yaxis: {}
1173
+ };
1174
+
1149
1175
  co.beginPath();
1150
1176
 
1151
1177
  // Draw the X axis
1152
1178
  if (prop['chart.noxaxis'] == false) {
1153
1179
  if (prop['chart.xaxispos'] == 'center') {
1154
- co.moveTo(this.gutterLeft, Math.round((this.grapharea / 2) + this.gutterTop));
1155
- co.lineTo(ca.width - this.gutterRight, Math.round((this.grapharea / 2) + this.gutterTop));
1180
+ coords.xaxis = [
1181
+ this.gutterLeft,
1182
+ ma.round((this.grapharea / 2) + this.gutterTop),
1183
+ ca.width - this.gutterRight,
1184
+ ma.round((this.grapharea / 2) + this.gutterTop)
1185
+ ];
1156
1186
  } else if (prop['chart.xaxispos'] === 'top') {
1157
- co.moveTo(this.gutterLeft, this.gutterTop);
1158
- co.lineTo(ca.width - this.gutterRight, this.gutterTop);
1187
+ coords.xaxis = [
1188
+ this.gutterLeft,
1189
+ this.gutterTop,
1190
+ ca.width - this.gutterRight,
1191
+ this.gutterTop
1192
+ ];
1159
1193
  } else {
1160
- co.moveTo(this.gutterLeft, ca.height - this.gutterBottom);
1161
- co.lineTo(ca.width - this.gutterRight, ca.height - this.gutterBottom);
1194
+
1195
+ var y = ma.round(this.getYCoord(prop['chart.ymin'] > 0 ? prop['chart.ymin'] : 0));
1196
+
1197
+ coords.xaxis = [
1198
+ this.gutterLeft,
1199
+ y,
1200
+ ca.width - this.gutterRight,
1201
+ y
1202
+ ];
1162
1203
  }
1204
+
1205
+ co.moveTo(coords.xaxis[0], coords.xaxis[1]);
1206
+ co.lineTo(coords.xaxis[2], coords.xaxis[3]);
1207
+
1208
+ // Save the coords so that they can
1209
+ // be referenced at a later time
1210
+ this.coordsAxes = coords;
1163
1211
  }
1164
1212
 
1165
1213
  // Draw the Y axis
@@ -1172,12 +1220,12 @@
1172
1220
  co.lineTo(ca.width - this.gutterRight, ca.height - this.gutterBottom);
1173
1221
  }
1174
1222
  }
1175
-
1223
+
1176
1224
  /**
1177
1225
  * Draw the X tickmarks
1178
1226
  */
1179
1227
  if (prop['chart.noxaxis'] == false && prop['chart.numxticks'] > 0) {
1180
-
1228
+
1181
1229
  var xTickInterval = (ca.width - this.gutterLeft - this.gutterRight) / prop['chart.numxticks'];
1182
1230
 
1183
1231
 
@@ -1200,30 +1248,41 @@
1200
1248
  }
1201
1249
  }
1202
1250
 
1203
- var yStart = prop['chart.xaxispos'] == 'center' ? (this.gutterTop + (this.grapharea / 2)) - 3 : ca.height - this.gutterBottom;
1204
- var yEnd = prop['chart.xaxispos'] == 'center' ? yStart + 6 : ca.height - this.gutterBottom - (x % 60 == 0 ? prop['chart.largexticks'] * prop['chart.tickdirection'] : prop['chart.smallxticks'] * prop['chart.tickdirection']);
1205
-
1206
- if (prop['chart.xaxispos'] == 'center') {
1207
- var yStart = Math.round((this.gutterTop + (this.grapharea / 2))) - 3;
1208
- var yEnd = yStart + 6;
1251
+ var yStart = prop['chart.xaxispos'] === 'center' ? (this.gutterTop + (this.grapharea / 2)) - 3 : ca.height - this.gutterBottom;
1252
+ var yEnd = prop['chart.xaxispos'] === 'center' ? yStart + 6 : ca.height - this.gutterBottom - (x % 60 == 0 ? prop['chart.largexticks'] * prop['chart.tickdirection'] : prop['chart.smallxticks'] * prop['chart.tickdirection']);
1253
+
1254
+
1255
+ // Draw the tick
1256
+ if (prop['chart.ymin'] >= 0 && prop['chart.xaxispos'] === 'bottom') {
1257
+ var yStart = this.getYCoord(prop['chart.ymin']) - (prop['chart.ymin'] >= 0 ? 0 : 3),
1258
+ yEnd = this.getYCoord(prop['chart.ymin']) + 3;
1259
+
1260
+ } else if (prop['chart.xaxispos'] == 'center') {
1261
+ var yStart = Math.round((this.gutterTop + (this.grapharea / 2))) - 3,
1262
+ yEnd = yStart + 6;
1209
1263
 
1210
1264
  } else if (prop['chart.xaxispos'] == 'bottom') {
1211
- var yStart = ca.height - this.gutterBottom;
1212
- var yEnd = ca.height - this.gutterBottom - (x % 60 == 0 ? prop['chart.largexticks'] * prop['chart.tickdirection'] : prop['chart.smallxticks'] * prop['chart.tickdirection']);
1213
- yEnd += 0;
1214
-
1265
+
1266
+ var yStart = this.getYCoord(0) - (prop['chart.ymin'] !== 0 ? 3 : 0),
1267
+ yEnd = this.getYCoord(0) - (x % 60 == 0 ? prop['chart.largexticks'] * prop['chart.tickdirection'] : prop['chart.smallxticks'] * prop['chart.tickdirection']);
1268
+ yEnd += 0;
1269
+
1215
1270
 
1216
1271
  } else if (prop['chart.xaxispos'] == 'top') {
1272
+
1217
1273
  yStart = this.gutterTop - 3;
1218
1274
  yEnd = this.gutterTop;
1219
1275
  }
1220
-
1221
- co.moveTo(Math.round(x), yStart);
1222
- co.lineTo(Math.round(x), yEnd);
1276
+
1277
+
1278
+ co.moveTo(ma.round(x), yStart);
1279
+ co.lineTo(ma.round(x), yEnd);
1223
1280
  }
1224
1281
 
1225
1282
  // Draw an extra tickmark if there is no X axis, but there IS a Y axis
1283
+ // OR if there is an offset X axis
1226
1284
  } else if (prop['chart.noyaxis'] == false && prop['chart.numyticks'] > 0) {
1285
+
1227
1286
  if (!prop['chart.noendytick']) {
1228
1287
  if (prop['chart.yaxispos'] == 'left') {
1229
1288
  co.moveTo(this.gutterLeft, Math.round(ca.height - this.gutterBottom));
@@ -1239,10 +1298,11 @@
1239
1298
  * Draw the Y tickmarks
1240
1299
  */
1241
1300
  var numyticks = prop['chart.numyticks'];
1242
-
1301
+
1243
1302
  if (prop['chart.noyaxis'] == false && numyticks > 0) {
1244
- var counter = 0;
1245
- var adjustment = 0;
1303
+
1304
+ var counter = 0,
1305
+ adjustment = 0;
1246
1306
 
1247
1307
  if (prop['chart.yaxispos'] == 'right') {
1248
1308
  adjustment = (ca.width - this.gutterLeft - this.gutterRight);
@@ -1273,10 +1333,11 @@
1273
1333
  var lineto = (prop['chart.yaxispos'] == 'left' ? this.gutterLeft : ca.width - this.gutterRight + prop['chart.smallyticks']);
1274
1334
 
1275
1335
  // Draw the Y tick marks
1276
- for (y=this.gutterTop + interval; y <=this.grapharea + this.gutterTop; y+=interval) {
1336
+ for (y=this.gutterTop + interval; y <= this.grapharea + this.gutterBottom; y+=interval) {
1277
1337
  co.moveTo((prop['chart.yaxispos'] == 'left' ? this.gutterLeft - prop['chart.smallyticks'] : ca.width - this.gutterRight), Math.round(y));
1278
1338
  co.lineTo(lineto, Math.round(y));
1279
1339
  }
1340
+
1280
1341
 
1281
1342
  // If there's no X axis draw an extra tick
1282
1343
  if (prop['chart.noxaxis'] && prop['chart.noendytick'] == false) {
@@ -1286,16 +1347,37 @@
1286
1347
 
1287
1348
  // X axis at the bottom
1288
1349
  } else {
1289
-
1350
+
1290
1351
  var lineto = (prop['chart.yaxispos'] == 'left' ? this.gutterLeft - prop['chart.smallyticks'] : ca.width - this.gutterRight + prop['chart.smallyticks']);
1291
-
1292
- for (y=this.gutterTop; y<(ca.height - this.gutterBottom) && counter < numyticks; y+=( (ca.height - this.gutterTop - this.gutterBottom) / numyticks) ) {
1293
-
1294
- co.moveTo(this.gutterLeft + adjustment, Math.round(y));
1295
- co.lineTo(lineto, Math.round(y));
1352
+
1353
+ for (y=this.gutterTop;
1354
+ y<(ca.height - this.gutterBottom) && counter < numyticks;
1355
+ y+=( (ca.height - this.gutterTop - this.gutterBottom) / numyticks)
1356
+ ) {
1357
+
1358
+ // This check is so that there's no tickmark at
1359
+ // the same position as the X axis
1360
+ if (ma.round(y) !== ma.round(this.coordsAxes.xaxis[1])) {
1361
+ co.moveTo(this.gutterLeft + adjustment, ma.round(y));
1362
+ co.lineTo(lineto, ma.round(y));
1363
+ }
1296
1364
 
1297
1365
  var counter = counter + 1;
1298
1366
  }
1367
+
1368
+ // Draw an extra Y tick if there's an offsetX axis
1369
+ if (prop['chart.ymin'] < 0) {
1370
+
1371
+ co.moveTo(
1372
+ (prop['chart.yaxispos'] == 'left' ? this.gutterLeft : ca.width - this.gutterRight),
1373
+ ma.round(y)
1374
+ );
1375
+
1376
+ co.lineTo(
1377
+ lineto,
1378
+ ma.round(y)
1379
+ );
1380
+ }
1299
1381
  }
1300
1382
 
1301
1383
  // Draw an extra X tickmark
@@ -1311,7 +1393,7 @@
1311
1393
  }
1312
1394
 
1313
1395
  co.stroke();
1314
-
1396
+
1315
1397
  /**
1316
1398
  * This is here so that setting the color after this function doesn't
1317
1399
  * change the color of the axes
@@ -1353,6 +1435,8 @@
1353
1435
  var numYLabels = this.scale2.labels.length;
1354
1436
  var bounding = false;
1355
1437
  var bgcolor = prop['chart.ylabels.inside'] ? prop['chart.ylabels.inside.color'] : null;
1438
+ var offsetx = prop['chart.ylabels.offsetx'];
1439
+ var offsety = prop['chart.ylabels.offsety'];
1356
1440
 
1357
1441
 
1358
1442
  /**
@@ -1384,49 +1468,52 @@
1384
1468
  * Draw the top half
1385
1469
  */
1386
1470
  for (var i=0; i<this.scale2.labels.length; ++i) {
1387
- RG.Text2(this, {'font': font,
1388
- 'size': text_size,
1389
- 'x': xpos,
1390
- 'y': this.gutterTop + half - (((i+1)/numYLabels) * half),
1391
- 'valign': 'center',
1392
- 'halign':align,
1393
- 'bounding': bounding,
1394
- 'boundingFill': bgcolor,
1395
- 'text': this.scale2.labels[i],
1396
- 'tag': 'scale'
1397
- });
1471
+ RG.text2(this, {
1472
+ 'font': font,
1473
+ 'size': text_size,
1474
+ 'x': xpos + offsetx,
1475
+ 'y': this.gutterTop + half - (((i+1)/numYLabels) * half) + offsety,
1476
+ 'valign': 'center',
1477
+ 'halign':align,
1478
+ 'bounding': bounding,
1479
+ 'boundingFill': bgcolor,
1480
+ 'text': this.scale2.labels[i],
1481
+ 'tag': 'scale'
1482
+ });
1398
1483
  }
1399
1484
 
1400
1485
  /**
1401
1486
  * Draw the bottom half
1402
1487
  */
1403
1488
  for (var i=0; i<this.scale2.labels.length; ++i) {
1404
- RG.Text2(this, {'font': font,
1405
- 'size': text_size,
1406
- 'x': xpos,
1407
- 'y': this.gutterTop + half + (((i+1)/numYLabels) * half),
1408
- 'valign': 'center',
1409
- 'halign':align,
1410
- 'bounding': bounding,
1411
- 'boundingFill': bgcolor,
1412
- 'text': '-' + this.scale2.labels[i],
1413
- 'tag': 'scale'
1414
- });
1489
+ RG.text2(this, {
1490
+ 'font': font,
1491
+ 'size': text_size,
1492
+ 'x': xpos + offsetx,
1493
+ 'y': this.gutterTop + half + (((i+1)/numYLabels) * half) + offsety,
1494
+ 'valign': 'center',
1495
+ 'halign':align,
1496
+ 'bounding': bounding,
1497
+ 'boundingFill': bgcolor,
1498
+ 'text': '-' + this.scale2.labels[i],
1499
+ 'tag': 'scale'
1500
+ });
1415
1501
  }
1416
1502
 
1417
1503
  // No X axis - so draw 0
1418
1504
  if (prop['chart.noxaxis'] == true || ymin != 0 || prop['chart.scale.zerostart']) {
1419
- RG.Text2(this,{'font':font,
1420
- 'size':text_size,
1421
- 'x':xpos,
1422
- 'y':this.gutterTop + half,
1423
- 'text':prop['chart.units.pre'] + ymin.toFixed(decimals) + prop['chart.units.post'],
1424
- 'bounding':bounding,
1425
- 'boundingFill':bgcolor,
1426
- 'valign':'center',
1427
- 'halign':align,
1428
- 'tag': 'scale'
1429
- });
1505
+ RG.text2(this,{
1506
+ 'font':font,
1507
+ 'size':text_size,
1508
+ 'x':xpos + offsetx,
1509
+ 'y':this.gutterTop + half + offsety,
1510
+ 'text':prop['chart.units.pre'] + ymin.toFixed(decimals) + prop['chart.units.post'],
1511
+ 'bounding':bounding,
1512
+ 'boundingFill':bgcolor,
1513
+ 'valign':'center',
1514
+ 'halign':align,
1515
+ 'tag': 'scale'
1516
+ });
1430
1517
  }
1431
1518
 
1432
1519
 
@@ -1442,46 +1529,50 @@
1442
1529
 
1443
1530
  for (var i=0; i<this.scale2.labels.length; ++i) {
1444
1531
 
1445
- RG.Text2(this, {'font': font,
1446
- 'size': text_size,
1447
- 'x': xpos,
1448
- 'y': this.gutterTop + ((i/this.scale2.labels.length) * this.grapharea),
1449
- 'valign': 'center',
1450
- 'halign':align,
1451
- 'bounding': bounding,
1452
- 'boundingFill': bgcolor,
1453
- 'text': '-' + this.scale2.labels[this.scale2.labels.length - (i+1)],
1454
- 'tag': 'scale'
1455
- });
1532
+ RG.text2(this, {
1533
+ 'font': font,
1534
+ 'size': text_size,
1535
+ 'x': xpos + offsetx,
1536
+ 'y': this.gutterTop + ((i/this.scale2.labels.length) * this.grapharea) + offsety,
1537
+ 'valign': 'center',
1538
+ 'halign':align,
1539
+ 'bounding': bounding,
1540
+ 'boundingFill': bgcolor,
1541
+ 'text': '-' + this.scale2.labels[this.scale2.labels.length - (i+1)],
1542
+ 'tag': 'scale'
1543
+ });
1456
1544
  }
1457
1545
  } else {
1458
1546
  for (var i=0; i<this.scale2.labels.length; ++i) {
1459
- RG.Text2(this, {'font': font,
1460
- 'size': text_size,
1461
- 'x': xpos,
1462
- 'y': this.gutterTop + (((i+1)/numYLabels) * this.grapharea),
1463
- 'valign': 'center',
1464
- 'halign':align,
1465
- 'bounding': bounding,
1466
- 'boundingFill': bgcolor,
1467
- 'text': '-' + this.scale2.labels[i],
1468
- 'tag': 'scale'
1469
- });
1547
+ RG.text2(this, {
1548
+ 'font': font,
1549
+ 'size': text_size,
1550
+ 'x': xpos + offsetx,
1551
+ 'y': this.gutterTop + (((i+1)/numYLabels) * this.grapharea) + offsety,
1552
+ 'valign': 'center',
1553
+ 'halign':align,
1554
+ 'bounding': bounding,
1555
+ 'boundingFill': bgcolor,
1556
+ 'text': '-' + this.scale2.labels[i],
1557
+ 'tag': 'scale'
1558
+ });
1470
1559
  }
1471
1560
  }
1472
-
1561
+
1473
1562
  // Draw the lower limit if chart.ymin is specified
1474
1563
  if ((prop['chart.ymin'] != 0 || prop['chart.noxaxis']) || prop['chart.scale.invert'] || prop['chart.scale.zerostart']) {
1475
- RG.Text2(this, {'font':font,
1476
- 'size':text_size,
1477
- 'x':xpos,
1478
- 'y': prop['chart.scale.invert'] ? ca.height - this.gutterBottom : this.gutterTop,
1479
- 'text': (prop['chart.ymin'] != 0 ? '-' : '') + RG.number_format(this, prop['chart.ymin'].toFixed(decimals), units_pre, units_post),
1480
- 'valign':'center',
1481
- 'halign': align,
1482
- 'bounding':bounding,
1483
- 'boundingFill':bgcolor,
1484
- 'tag': 'scale'});
1564
+ RG.text2(this, {
1565
+ 'font':font,
1566
+ 'size':text_size,
1567
+ 'x':xpos + offsetx,
1568
+ 'y': prop['chart.scale.invert'] ? ca.height - this.gutterBottom + offsety : this.gutterTop + offsety,
1569
+ 'text': (prop['chart.ymin'] != 0 ? '-' : '') + RG.number_format(this, prop['chart.ymin'].toFixed(decimals), units_pre, units_post),
1570
+ 'valign':'center',
1571
+ 'halign': align,
1572
+ 'bounding':bounding,
1573
+ 'boundingFill':bgcolor,
1574
+ 'tag': 'scale'
1575
+ });
1485
1576
  }
1486
1577
 
1487
1578
 
@@ -1495,72 +1586,79 @@
1495
1586
  } else {
1496
1587
 
1497
1588
  if (prop['chart.scale.invert']) {
1498
-
1589
+
1499
1590
  // Draw the minimum value
1500
- RG.Text2(this, {'font': font,
1501
- 'size': text_size,
1502
- 'x': xpos,
1503
- 'y': this.gutterTop,
1504
- 'valign': 'center',
1505
- 'halign':align,
1506
- 'bounding': bounding,
1507
- 'boundingFill': bgcolor,
1508
- 'text': RG.number_format(this, this.min.toFixed(prop['chart.scale.decimals']), units_pre, units_post),
1509
- 'tag': 'scale'
1510
- });
1511
-
1591
+ RG.text2(this, {
1592
+ 'font': font,
1593
+ 'size': text_size,
1594
+ 'x': xpos + offsetx,
1595
+ 'y': this.gutterTop + offsety,
1596
+ 'valign': 'center',
1597
+ 'halign':align,
1598
+ 'bounding': bounding,
1599
+ 'boundingFill': bgcolor,
1600
+ 'text': RG.numberFormat(this, this.min.toFixed(prop['chart.scale.decimals']), units_pre, units_post),
1601
+ 'tag': 'scale'
1602
+ });
1603
+
1512
1604
  for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
1513
- RG.Text2(this, {'font': font,
1514
- 'size': text_size,
1515
- 'x': xpos,
1516
- 'y': this.gutterTop + (((i+1)/this.scale2.labels.length) * this.grapharea),
1517
- 'valign': 'center',
1518
- 'halign':align,
1519
- 'bounding': bounding,
1520
- 'boundingFill': bgcolor,
1521
- 'text': this.scale2.labels[i],
1522
- 'tag': 'scale'
1523
- });
1605
+ RG.Text2(this, {
1606
+ 'font': font,
1607
+ 'size': text_size,
1608
+ 'x': xpos + offsetx,
1609
+ 'y': this.gutterTop + (((i+1)/this.scale2.labels.length) * this.grapharea) + offsety,
1610
+ 'valign': 'center',
1611
+ 'halign':align,
1612
+ 'bounding': bounding,
1613
+ 'boundingFill': bgcolor,
1614
+ 'text': this.scale2.labels[i],
1615
+ 'tag': 'scale'
1616
+ });
1524
1617
  }
1618
+
1525
1619
  } else {
1526
1620
  for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
1527
- RG.Text2(this, {'font': font,
1528
- 'size': text_size,
1529
- 'x': xpos,
1530
- 'y': this.gutterTop + ((i/this.scale2.labels.length) * this.grapharea),
1531
- 'valign': 'center',
1532
- 'halign':align,
1533
- 'bounding': bounding,
1534
- 'boundingFill': bgcolor,
1535
- 'text': this.scale2.labels[this.scale2.labels.length - (i + 1)],
1536
- 'tag': 'scale'
1537
- });
1621
+ RG.text2(this, {
1622
+ 'font': font,
1623
+ 'size': text_size,
1624
+ 'x': xpos + offsetx,
1625
+ 'y': this.gutterTop + ((i/this.scale2.labels.length) * this.grapharea) + offsety,
1626
+ 'valign': 'center',
1627
+ 'halign':align,
1628
+ 'bounding': bounding,
1629
+ 'boundingFill': bgcolor,
1630
+ 'text': this.scale2.labels[this.scale2.labels.length - (i + 1)],
1631
+ 'tag': 'scale'
1632
+ });
1538
1633
  }
1539
1634
  }
1540
-
1635
+
1541
1636
  // Draw the lower limit if chart.ymin is specified
1542
1637
  if ( (prop['chart.ymin']!= 0 && !prop['chart.scale.invert'] || prop['chart.scale.zerostart'])
1543
1638
  || prop['chart.noxaxis']
1544
1639
  ) {
1545
- RG.Text2(this, {'font':font,
1546
- 'size':text_size,
1547
- 'x':xpos,
1548
- 'y':prop['chart.scale.invert'] ? this.gutterTop : ca.height - this.gutterBottom,
1549
- 'text':RG.number_format(this, prop['chart.ymin'].toFixed(prop['chart.scale.decimals']), units_pre, units_post),
1550
- 'valign':'center',
1551
- 'halign':align,
1552
- 'bounding':bounding,
1553
- 'boundingFill':bgcolor,
1554
- 'tag': 'scale'
1555
- });
1640
+
1641
+ RG.text2(this, {
1642
+ 'font':font,
1643
+ 'size':text_size,
1644
+ 'x':xpos + offsetx,
1645
+ 'y':prop['chart.scale.invert'] ? this.gutterTop + offsety : ca.height - this.gutterBottom + offsety,
1646
+ 'text':RG.number_format(this, prop['chart.ymin'].toFixed(prop['chart.scale.decimals']), units_pre, units_post),
1647
+ 'valign':'center',
1648
+ 'halign':align,
1649
+ 'bounding':bounding,
1650
+ 'boundingFill':bgcolor,
1651
+ 'tag': 'scale'
1652
+ });
1653
+
1556
1654
  }
1557
1655
  }
1656
+
1558
1657
 
1559
1658
 
1560
1659
 
1561
1660
 
1562
-
1563
-
1661
+
1564
1662
 
1565
1663
  // No X axis - so draw 0 - but not if the X axis is in the center
1566
1664
  if ( prop['chart.noxaxis'] == true
@@ -1568,19 +1666,20 @@
1568
1666
  && prop['chart.xaxispos'] != 'center'
1569
1667
  && prop['chart.noendytick'] == false
1570
1668
  ) {
1571
-
1572
- RG.Text2(this, {'font':font,
1573
- 'size':text_size,
1574
- 'x':xpos,
1575
- 'y':prop['chart.xaxispos'] == 'top' ? this.gutterTop : (ca.height - this.gutterBottom),'text': prop['chart.units.pre'] + Number(0).toFixed(prop['chart.scale.decimals']) + prop['chart.units.post'],
1576
- 'valign':'center',
1577
- 'halign':align,
1578
- 'bounding':bounding,
1579
- 'boundingFill':bgcolor,
1580
- 'tag':'scale'
1581
- });
1669
+
1670
+ RG.text2(this, {
1671
+ 'font':font,
1672
+ 'size':text_size,
1673
+ 'x':xpos + offsetx,
1674
+ 'y':prop['chart.xaxispos'] == 'top' ? this.gutterTop + offsety : (ca.height - this.gutterBottom),'text': prop['chart.units.pre'] + Number(0).toFixed(prop['chart.scale.decimals']) + prop['chart.units.post'] + offsety,
1675
+ 'valign':'center',
1676
+ 'halign':align,
1677
+ 'bounding':bounding,
1678
+ 'boundingFill':bgcolor,
1679
+ 'tag':'scale'
1680
+ });
1582
1681
  }
1583
-
1682
+
1584
1683
  } else if (prop['chart.ylabels'] && typeof(prop['chart.ylabels.specific']) == 'object') {
1585
1684
 
1586
1685
  // A few things
@@ -1612,10 +1711,14 @@
1612
1711
  }
1613
1712
  }
1614
1713
 
1615
-
1714
+ var offsetx = prop['chart.ylabels.offsetx'];
1715
+ var offsety = prop['chart.ylabels.offsety'];
1716
+
1616
1717
  // Draw the labels
1617
1718
  if (prop['chart.xaxispos'] == 'center') {
1618
1719
 
1720
+
1721
+
1619
1722
  // Draw the top halfs labels
1620
1723
  for (var i=0; i<prop['chart.ylabels.specific'].length; ++i) {
1621
1724
 
@@ -1625,18 +1728,19 @@
1625
1728
  var y = ((this.grapharea / 2) / (prop['chart.ylabels.specific'].length - (ymin ? 1 : 0)) ) * i;
1626
1729
  y += this.gutterTop;
1627
1730
  }
1628
-
1629
- RG.Text2(this, {'font':font,
1630
- 'size':text_size,
1631
- 'x':x,
1632
- 'y':y,
1633
- 'text':String(prop['chart.ylabels.specific'][i]),
1634
- 'valign': 'center',
1635
- 'halign':halign,
1636
- 'bounding':bounding,
1637
- 'boundingFill':bgcolor,
1638
- 'tag': 'ylabels.specific'
1639
- });
1731
+
1732
+ RG.text2(this, {
1733
+ 'font':font,
1734
+ 'size':text_size,
1735
+ 'x':x + offsetx,
1736
+ 'y':y + offsety,
1737
+ 'text':String(prop['chart.ylabels.specific'][i]),
1738
+ 'valign': 'center',
1739
+ 'halign':halign,
1740
+ 'bounding':bounding,
1741
+ 'boundingFill':bgcolor,
1742
+ 'tag': 'ylabels.specific'
1743
+ });
1640
1744
  }
1641
1745
 
1642
1746
  // Now reverse the labels and draw the bottom half
@@ -1647,17 +1751,18 @@
1647
1751
 
1648
1752
  var y = (this.grapharea / 2) + this.gutterTop + ((this.grapharea / ((reversed_labels.length - 1) * 2) ) * i);
1649
1753
 
1650
- RG.Text2(this, {'font':font,
1651
- 'size':text_size,
1652
- 'x':x,
1653
- 'y':y,
1654
- 'text':i == 0 ? '' : String(reversed_labels[i]),
1655
- 'valign': 'center',
1656
- 'halign':halign,
1657
- 'bounding':bounding,
1658
- 'boundingFill':bgcolor,
1659
- 'tag': 'ylabels.specific'
1660
- });
1754
+ RG.text2(this, {
1755
+ 'font':font,
1756
+ 'size':text_size,
1757
+ 'x':x + offsetx,
1758
+ 'y':y + offsety,
1759
+ 'text':i == 0 ? '' : String(reversed_labels[i]),
1760
+ 'valign': 'center',
1761
+ 'halign':halign,
1762
+ 'bounding':bounding,
1763
+ 'boundingFill':bgcolor,
1764
+ 'tag': 'ylabels.specific'
1765
+ });
1661
1766
  }
1662
1767
 
1663
1768
  } else if (prop['chart.xaxispos'] == 'top') {
@@ -1671,33 +1776,35 @@
1671
1776
  var y = (this.grapharea / (reversed_labels.length - 1)) * i;
1672
1777
  y = y + this.gutterTop;
1673
1778
 
1674
- RG.Text2(this, {'font':font,
1675
- 'size':text_size,
1676
- 'x':x,
1677
- 'y':y,
1678
- 'text':String(reversed_labels[i]),
1679
- 'valign': 'center',
1680
- 'halign':halign,
1681
- 'bounding':bounding,
1682
- 'boundingFill':bgcolor,
1683
- 'tag': 'ylabels.specific'
1684
- });
1779
+ RG.Text2(this, {
1780
+ 'font':font,
1781
+ 'size':text_size,
1782
+ 'x':x + offsetx,
1783
+ 'y':y + offsety,
1784
+ 'text':String(reversed_labels[i]),
1785
+ 'valign': 'center',
1786
+ 'halign':halign,
1787
+ 'bounding':bounding,
1788
+ 'boundingFill':bgcolor,
1789
+ 'tag': 'ylabels.specific'
1790
+ });
1685
1791
  }
1686
1792
 
1687
1793
  } else {
1688
1794
  for (var i=0; i<prop['chart.ylabels.specific'].length; ++i) {
1689
1795
  var y = this.gutterTop + ((this.grapharea / (prop['chart.ylabels.specific'].length - 1)) * i);
1690
- RG.Text2(this, {'font':font,
1691
- 'size':text_size,
1692
- 'x':x,
1693
- 'y':y,
1694
- 'text':String(prop['chart.ylabels.specific'][i]),
1695
- 'valign':'center',
1696
- 'halign':halign,
1697
- 'bounding':bounding,
1698
- 'boundingFill':bgcolor,
1699
- 'tag': 'ylabels.specific'
1700
- });
1796
+ RG.text2(this, {
1797
+ 'font':font,
1798
+ 'size':text_size,
1799
+ 'x':x + offsetx,
1800
+ 'y':y + offsety,
1801
+ 'text':String(prop['chart.ylabels.specific'][i]),
1802
+ 'valign':'center',
1803
+ 'halign':halign,
1804
+ 'bounding':bounding,
1805
+ 'boundingFill':bgcolor,
1806
+ 'tag': 'ylabels.specific'
1807
+ });
1701
1808
  }
1702
1809
  }
1703
1810
  }
@@ -1742,7 +1849,9 @@
1742
1849
  }
1743
1850
  }
1744
1851
 
1745
- var numLabels = prop['chart.labels'].length;
1852
+ var numLabels = prop['chart.labels'].length,
1853
+ offsetx = prop['chart.labels.offsetx'],
1854
+ offsety = prop['chart.labels.offsety'];
1746
1855
 
1747
1856
  for (i=0; i<numLabels; ++i) {
1748
1857
 
@@ -1778,8 +1887,8 @@
1778
1887
  'font':font,
1779
1888
  'size':text_size,
1780
1889
  'bold': bold,
1781
- 'x':labelX,
1782
- 'y':(prop['chart.xaxispos'] == 'top') ? this.gutterTop - yOffset - (prop['chart.xlabels.inside'] ? -22 : 0) : (ca.height - this.gutterBottom) + yOffset,
1890
+ 'x':labelX + offsetx,
1891
+ 'y':(prop['chart.xaxispos'] == 'top') ? this.gutterTop - yOffset - (prop['chart.xlabels.inside'] ? -22 : 0) + offsety : (ca.height - this.gutterBottom) + yOffset + offsety,
1783
1892
  'text':String(prop['chart.labels'][i]),
1784
1893
  'valign':valign,
1785
1894
  'halign':halign,
@@ -2031,15 +2140,15 @@
2031
2140
  co.lineTo(lineCoords[0][0],prop['chart.gutter.top'] + 1);
2032
2141
  } else if (typeof(lineCoords[i - 1][1]) == 'number') {
2033
2142
 
2034
- var yPosition = prop['chart.xaxispos'] == 'center' ? ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop : ca.height - this.gutterBottom;
2143
+ var yPosition = prop['chart.xaxispos'] == 'center' ? ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop : this.getYCoord(0);//ca.height - this.gutterBottom;
2035
2144
 
2036
2145
  co.lineTo(xPos,yPosition);
2037
2146
  co.lineTo(lineCoords[0][0],yPosition);
2038
2147
  }
2039
2148
  }
2040
2149
 
2041
- co.fillStyle = fill;
2042
-
2150
+ co.fillStyle = !this.hidden(index) ? fill : 'rgba(0,0,0,0)';
2151
+
2043
2152
  co.fill();
2044
2153
  co.beginPath();
2045
2154
 
@@ -2141,8 +2250,19 @@
2141
2250
 
2142
2251
  var prevX = (i <= 0 ? null : lineCoords[i - 1][0]);
2143
2252
  var prevY = (i <= 0 ? null : lineCoords[i - 1][1]);
2144
-
2145
- this.DrawTick(lineData, lineCoords[i][0], lineCoords[i][1], color, false, prevX, prevY, tickmarks, i);
2253
+
2254
+ this.DrawTick(
2255
+ lineData,
2256
+ lineCoords[i][0],
2257
+ lineCoords[i][1],
2258
+ color,
2259
+ false,
2260
+ prevX,
2261
+ prevY,
2262
+ tickmarks,
2263
+ i,
2264
+ index
2265
+ );
2146
2266
 
2147
2267
  // Draws tickmarks on the stepped bits of stepped charts. Takend out 14th July 2010
2148
2268
  //
@@ -2164,17 +2284,12 @@
2164
2284
 
2165
2285
  /**
2166
2286
  * This functions draws a tick mark on the line
2167
- *
2168
- * @param xPos int The x position of the tickmark
2169
- * @param yPos int The y position of the tickmark
2170
- * @param color str The color of the tickmark
2171
- * @param bool Whether the tick is a shadow. If it is, it gets offset by the shadow offset
2172
2287
  */
2173
2288
  this.drawTick =
2174
- this.DrawTick = function (lineData, xPos, yPos, color, isShadow, prevX, prevY, tickmarks, index)
2289
+ this.DrawTick = function (lineData, xPos, yPos, color, isShadow, prevX, prevY, tickmarks, index, dataset)
2175
2290
  {
2176
2291
  // Various conditions mean no tick
2177
- if (!prop['chart.line.visible']) {
2292
+ if (this.hidden(dataset)) {
2178
2293
  return;
2179
2294
  } else if (RG.is_null(yPos)) {
2180
2295
  return false;
@@ -2276,7 +2391,7 @@
2276
2391
 
2277
2392
  co.lineWidth = prop['chart.tickmarks.dot.linewidth'] || 0.00000001;
2278
2393
 
2279
- pa(this, [
2394
+ pa2(co, [
2280
2395
  'b',
2281
2396
  'a',xPos, yPos, prop['chart.ticksize'], 0, 360 / (180 / RG.PI), false,
2282
2397
  'c',
@@ -2441,17 +2556,12 @@
2441
2556
  this.drawRange =
2442
2557
  this.DrawRange = function ()
2443
2558
  {
2444
- //var RG = RGraph;
2445
- //var ca = this.canvas;
2446
- //var co = this.context;
2447
- //var prop = this.properties;
2448
-
2449
2559
  /**
2450
2560
  * Fill the range if necessary
2451
2561
  */
2452
- if (prop['chart.filled.range'] && prop['chart.filled'] && prop['chart.line.visible']) {
2562
+ if (prop['chart.filled.range'] && prop['chart.filled']) {
2453
2563
 
2454
- if (RG.is_null(prop['chart.filled.range.threshold'])) {
2564
+ if (RG.isNull(prop['chart.filled.range.threshold'])) {
2455
2565
  prop['chart.filled.range.threshold'] = this.ymin
2456
2566
  prop['chart.filled.range.threshold.colors'] = [prop['chart.fillstyle'], prop['chart.fillstyle']]
2457
2567
  }
@@ -2479,7 +2589,7 @@
2479
2589
 
2480
2590
  //co.strokeStyle = prop['chart.fillstyle']; // Strokestyle not used now (10th October 2012)
2481
2591
 
2482
- co.lineWidth = 1;
2592
+ co.lineWidth = !this.hidden(idx) ? 1 : 0;
2483
2593
  var len = (this.coords.length / 2);
2484
2594
 
2485
2595
 
@@ -2526,6 +2636,7 @@
2526
2636
  this.redrawLine =
2527
2637
  this.RedrawLine = function (coords, color, linewidth, index)
2528
2638
  {
2639
+
2529
2640
  if (prop['chart.noredraw'] || prop['chart.filled.range']) {
2530
2641
  return;
2531
2642
  }
@@ -2533,7 +2644,7 @@
2533
2644
  co.strokeStyle = (typeof(color) == 'object' && color && color.toString().indexOf('CanvasGradient') == -1 ? color[0] : color);
2534
2645
  co.lineWidth = linewidth;
2535
2646
 
2536
- if (!prop['chart.line.visible']) {
2647
+ if (this.hidden(index)) {
2537
2648
  co.strokeStyle = 'rgba(0,0,0,0)';
2538
2649
  }
2539
2650
 
@@ -2545,7 +2656,7 @@
2545
2656
 
2546
2657
 
2547
2658
  if (!RG.ISOLD && (prop['chart.curvy'] || prop['chart.spline'])) {
2548
- this.DrawCurvyLine(coords, !prop['chart.line.visible'] ? 'rgba(0,0,0,0)' : color, linewidth, index);
2659
+ this.DrawCurvyLine(coords, this.hidden(index) ? 'rgba(0,0,0,0)' : color, linewidth, index);
2549
2660
  return;
2550
2661
  }
2551
2662
 
@@ -2853,10 +2964,6 @@
2853
2964
  this.drawCurvyLine =
2854
2965
  this.DrawCurvyLine = function (coords, color, linewidth, index)
2855
2966
  {
2856
- if (RG.ISOLD) {
2857
- return;
2858
- }
2859
-
2860
2967
  var yCoords = [];
2861
2968
 
2862
2969
  for (var i=0; i<coords.length; ++i) {
@@ -2870,7 +2977,7 @@
2870
2977
  if (prop['chart.xaxispos'] === 'center') {
2871
2978
  var xaxisY = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
2872
2979
  } else {
2873
- var xaxisY = ca.height - this.gutterBottom;
2980
+ var xaxisY = this.getYCoord(0);
2874
2981
  }
2875
2982
 
2876
2983
 
@@ -2949,8 +3056,41 @@
2949
3056
  this.Highlight = function (shape)
2950
3057
  {
2951
3058
  if (prop['chart.tooltips.highlight']) {
2952
- // Add the new highlight
2953
- RG.Highlight.Point(this, shape);
3059
+
3060
+ if (typeof prop['chart.highlight.style'] === 'function') {
3061
+ (prop['chart.highlight.style'])(shape);
3062
+
3063
+ } else if (prop['chart.highlight.style'] === 'halo') {
3064
+
3065
+ var obj = shape.object,
3066
+ color = prop['chart.colors'][shape.dataset];
3067
+
3068
+ // Clear a space in white first for the tickmark
3069
+ RG.path2(obj.context, 'b a % % 13 0 6.2830 false f rgba(255,255,255,0.75)',
3070
+ shape.x,
3071
+ shape.y
3072
+ );
3073
+
3074
+ RG.path2(obj.context, 'ga 0.15 b a % % 13 0 6.2830 false f % ga 1',
3075
+ shape.x,
3076
+ shape.y,
3077
+ color
3078
+ );
3079
+
3080
+ RG.path2(obj.context, 'b a % % 7 0 6.2830 false f white',
3081
+ shape.x,
3082
+ shape.y
3083
+ );
3084
+
3085
+ RG.path2(obj.context, 'b a % % 5 0 6.2830 false f %',
3086
+ shape.x,
3087
+ shape.y,
3088
+ color
3089
+ );
3090
+
3091
+ } else {
3092
+ RG.Highlight.Point(this, shape);
3093
+ }
2954
3094
  }
2955
3095
  };
2956
3096
 
@@ -3093,48 +3233,36 @@
3093
3233
  */
3094
3234
  this.positionTooltip = function (obj, x, y, tooltip, idx)
3095
3235
  {
3096
- //var ca = obj.canvas;
3097
- //var co = obj.context;
3098
- //var prop = obj.properties;
3099
-
3236
+
3100
3237
  var coordX = obj.coords[tooltip.__index__][0];
3101
3238
  var coordY = obj.coords[tooltip.__index__][1];
3102
3239
  var canvasXY = RG.getCanvasXY(obj.canvas);
3103
3240
  var gutterLeft = prop['chart.gutter.left'];
3104
3241
  var gutterTop = prop['chart.gutter.top'];
3105
3242
  var width = tooltip.offsetWidth;
3243
+ var height = tooltip.offsetHeight;
3244
+ var mouseXY = RG.getMouseXY(window.event);
3106
3245
 
3107
3246
  // Set the top position
3108
3247
  tooltip.style.left = 0;
3109
- tooltip.style.top = parseInt(tooltip.style.top) - 9 + 'px';
3248
+ tooltip.style.top = window.event.pageY - height - 20 + 'px';
3110
3249
 
3111
3250
  // By default any overflow is hidden
3112
3251
  tooltip.style.overflow = '';
3113
-
3114
- // The arrow
3115
- var img = new Image();
3116
- img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAFCAYAAACjKgd3AAAARUlEQVQYV2NkQAN79+797+RkhC4M5+/bd47B2dmZEVkBCgcmgcsgbAaA9GA1BCSBbhAuA/AagmwQPgMIGgIzCD0M0AMMAEFVIAa6UQgcAAAAAElFTkSuQmCC';
3117
- img.style.position = 'absolute';
3118
- img.id = '__rgraph_tooltip_pointer__';
3119
- img.style.top = (tooltip.offsetHeight - 2) + 'px';
3120
- tooltip.appendChild(img);
3121
3252
 
3122
3253
  // Reposition the tooltip if at the edges:
3123
3254
 
3124
3255
  // LEFT edge
3125
- if ((canvasXY[0] + coordX - (width / 2)) < 10) {
3126
- tooltip.style.left = (canvasXY[0] + coordX - (width * 0.2)) + 'px';
3127
- img.style.left = ((width * 0.2) - 8.5) + 'px';
3256
+ if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
3257
+ tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
3128
3258
 
3129
3259
  // RIGHT edge
3130
- } else if ((canvasXY[0] + coordX + (width / 2)) > doc.body.offsetWidth) {
3131
- tooltip.style.left = canvasXY[0] + coordX - (width * 0.8) + 'px';
3132
- img.style.left = ((width * 0.8) - 8.5) + 'px';
3260
+ } else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
3261
+ tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
3133
3262
 
3134
3263
  // Default positioning - CENTERED
3135
3264
  } else {
3136
- tooltip.style.left = (canvasXY[0] + coordX - (width * 0.5)) + 'px';
3137
- img.style.left = ((width * 0.5) - 8.5) + 'px';
3265
+ tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
3138
3266
  }
3139
3267
  };
3140
3268
 
@@ -3637,213 +3765,85 @@
3637
3765
 
3638
3766
 
3639
3767
  /**
3640
- * Trace
3641
- *
3642
- * This effect is for the Line chart, uses the jQuery library and slowly
3643
- * uncovers the Line , but you can see the background of the chart. This effect
3644
- * is quite new (1/10/2011) and as such should be used with caution.
3768
+ * Hides a line by setting the appropriate flag so that the .visible(index)
3769
+ * function returns the relevant result.
3645
3770
  *
3646
- * @param object An object of configuration. You can give 'duration' or 'frames' here.
3647
- * @param function An optional callback function
3771
+ * @param int index The index of the line to hide
3648
3772
  */
3649
- this.trace = function ()
3773
+ this.hide = function ()
3650
3774
  {
3651
- var obj = this;
3652
- var callback = typeof arguments[1] === 'function' ? arguments[1] : function () {};
3653
- var opt = arguments[0] || {};
3654
-
3655
- if (opt.frames) {
3656
- opt.duration = (opt.frames / 60) * 1000;
3657
- }
3658
-
3659
- if (!opt.duration) {
3660
- opt.duration = 1500;
3661
- }
3662
-
3663
- RG.clear(obj.canvas);
3664
- RG.redrawCanvas(obj.canvas);
3665
-
3666
- /**
3667
- * Create the DIV that the second canvas will sit in
3668
- */
3669
- var div = doc.createElement('DIV');
3670
- var xy = RG.getCanvasXY(obj.canvas);
3671
- div.id = '__rgraph_trace_animation_' + RG.random(0, 4351623) + '__';
3672
- div.style.left = xy[0] + 'px';
3673
- div.style.top = xy[1] + 'px';
3674
- div.style.width = obj.Get('chart.gutter.left');
3675
- div.style.height = obj.canvas.height + 'px';
3676
- div.style.position = 'absolute';
3677
- div.style.overflow = 'hidden';
3678
- doc.body.appendChild(div);
3679
-
3680
- obj.canvas.__rgraph_trace_div__ = div;
3681
-
3682
- /**
3683
- * Make the second canvas
3684
- */
3685
- var id = '__rgraph_line_trace_animation_' + RG.random(0, 99999999) + '__';
3686
- var canvas2 = doc.createElement('CANVAS');
3687
-
3688
-
3689
-
3690
-
3691
- // Copy the 3D CSS transformation properties across from the original canvas
3692
- var properties = ['WebkitTransform','MozTransform','OTransform','MSTransform','transform'];
3775
+ // Hide a single line
3776
+ if (typeof arguments[0] === 'number') {
3777
+ prop['chart.line.visible'][arguments[0]] = false;
3693
3778
 
3694
- for (i in properties) {
3695
- var name = properties[i];
3696
- if (typeof obj.canvas.style[name] === 'string' && obj.canvas.style[name]) {
3697
- canvas2.style[name] = obj.canvas.style[name];
3779
+ // Hide multiple lines
3780
+ } else if (typeof arguments[0] === 'object') {
3781
+ for (var i=0; i<arguments[0].length; ++i) {
3782
+ prop['chart.line.visible'][arguments[0][i]] = false;
3698
3783
  }
3699
- }
3700
-
3701
-
3702
-
3703
- obj.canvas.__rgraph_line_canvas2__ = canvas2;
3704
- canvas2.width = obj.canvas.width;
3705
- canvas2.height = obj.canvas.height;
3706
- canvas2.style.position = 'absolute';
3707
- canvas2.style.left = 0;
3708
- canvas2.style.top = 0;
3709
-
3710
-
3711
- // This stops the clear effect clearing the canvas - which can happen if you have multiple canvas tags on the page all with
3712
- // dynamic effects that do redrawing
3713
- canvas2.noclear = true;
3714
-
3715
- canvas2.id = id;
3716
- div.appendChild(canvas2);
3717
-
3718
- var reposition_canvas2 = function (e)
3719
- {
3720
- var xy = RG.getCanvasXY(obj.canvas);
3721
3784
 
3722
- div.style.left = xy[0] + 'px';
3723
- div.style.top = xy[1] + 'px';
3724
- }
3725
- window.addEventListener('resize', reposition_canvas2, false)
3726
-
3727
- /**
3728
- * Make a copy of the original Line object
3729
- */
3730
- var obj2 = new RG.Line(id, RG.array_clone(obj.original_data));
3731
-
3732
- // Remove the new line from the ObjectRegistry so that it isn't redawn
3733
- RG.ObjectRegistry.Remove(obj2);
3734
-
3735
- for (i in obj.properties) {
3736
- if (typeof i === 'string') {
3737
- obj2.Set(i, obj.properties[i]);
3785
+ // Hide all lines
3786
+ } else {
3787
+ for (var i=0; i<this.original_data.length; ++i) {
3788
+ prop['chart.line.visible'][i] = false;
3738
3789
  }
3739
3790
  }
3740
-
3741
- //obj2.Set('chart.tooltips', null);
3742
- obj2.Set('labels', []);
3743
- obj2.Set('background.grid', false);
3744
- obj2.Set('background.barcolor1', 'rgba(0,0,0,0)');
3745
- obj2.Set('background.barcolor2', 'rgba(0,0,0,0)');
3746
- obj2.Set('ylabels', false);
3747
- obj2.Set('noaxes', true);
3748
- obj2.Set('title', '');
3749
- obj2.Set('title.xaxis', '');
3750
- obj2.Set('title.yaxis', '');
3751
- obj2.Set('filled.accumulative', obj.Get('chart.filled.accumulative'));
3752
- obj.Set('key', []);
3753
- obj2.Draw();
3754
3791
 
3755
- obj.canvas.__rgraph_trace_obj2__ = obj2;
3756
-
3757
-
3758
- /**
3759
- * This effectively hides the line
3760
- */
3761
- obj.Set('line.visible', false);
3762
- obj.Set('colors', ['rgba(0,0,0,0)']);
3763
- if (obj.Get('filled')) {
3764
- var original_fillstyle = obj.Get('chart.fillstyle');
3765
- obj.Set('fillstyle', 'rgba(0,0,0,0)');
3766
- obj.Set('animation.trace.original.fillstyle', original_fillstyle);
3767
- }
3768
-
3769
- RG.clear(obj.canvas);
3770
- //obj.Draw();
3771
- RG.redrawCanvas(obj.canvas);
3792
+ RG.redraw();
3772
3793
 
3773
- /**
3774
- * Place a DIV over the canvas to stop interaction with it
3775
- */
3776
- if (!obj.canvas.__rgraph_trace_cover__) {
3777
- var div2 = doc.createElement('DIV');
3778
- div2.id = '__rgraph_trace_animation_' + RG.random(0, 4351623) + '__';
3779
- div2.style.left = xy[0] + 'px';
3780
- div2.style.top = xy[1] + 'px';
3781
- div2.style.width = obj.canvas.width + 'px';
3782
- div2.style.height = obj.canvas.height + 'px';
3783
- div2.style.position = 'absolute';
3784
- div2.style.overflow = 'hidden';
3785
- div2.style.backgroundColor = 'rgba(0,0,0,0)';
3786
- div.div2 = div2;
3787
- obj.canvas.__rgraph_trace_cover__ = div2;
3788
- doc.body.appendChild(div2);
3789
- } else {
3790
- div2 = obj.canvas.__rgraph_trace_cover__;
3791
- }
3794
+ // Facilitate chaining
3795
+ return this;
3796
+ };
3792
3797
 
3793
3798
 
3794
3799
 
3795
- /**
3796
- * Get rid of the second canvas and turn the line back on
3797
- * on the original.
3798
- */
3799
- trace_complete = function (obj)
3800
- {
3801
- var obj2 = obj.canvas.__rgraph_trace_obj2__;
3802
-
3803
- // Remove the window resize listener
3804
- win.removeEventListener('resize', reposition_canvas2, false);
3805
-
3806
- div.style.display = 'none';
3807
- div2.style.display = 'none';
3808
-
3809
- //div.removeChild(canvas2);
3810
- obj.Set('line.visible', true);
3811
-
3812
- // Revert the filled status back to as it was
3813
- obj.Set('filled', RGraph.array_clone(obj2.Get('chart.filled')));
3814
- obj.Set('fillstyle', obj.Get('chart.animation.trace.original.fillstyle'));
3815
- obj.Set('colors', RGraph.array_clone(obj2.Get('chart.colors')));
3816
- obj.Set('key', RGraph.array_clone(obj2.Get('chart.key')));
3817
-
3818
- RGraph.RedrawCanvas(obj.canvas);
3819
-
3820
- obj.canvas.__rgraph_trace_div__.style.display = 'none';
3821
- obj.canvas.__rgraph_line_canvas2__.style.display = 'none';
3822
- obj.canvas.__rgraph_trace_cover__.style.display = 'none';
3823
- obj.canvas.__rgraph_trace_div__ = null;
3824
- obj.canvas.__rgraph_line_canvas2__ = null;
3825
- obj.canvas.__rgraph_trace_cover__ = null;
3826
-
3827
-
3828
- callback(obj);
3829
- };
3830
-
3800
+
3801
+ /**
3802
+ * Shows a line by setting the appropriate flag so that the .visible(index)
3803
+ * function returns the relevant result.
3804
+ *
3805
+ * @param int index The index of the line to show
3806
+ */
3807
+ this.show = function ()
3808
+ {
3809
+ // Show a single line
3810
+ if (typeof arguments[0] === 'number') {
3811
+ prop['chart.line.visible'][arguments[0]] = true;
3831
3812
 
3813
+ // Show multiple lines
3814
+ } else if (typeof arguments[0] === 'object') {
3815
+ for (var i=0; i<arguments[0].length; ++i) {
3816
+ prop['chart.line.visible'][arguments[0][i]] = true;
3817
+ }
3818
+
3819
+ // Show all lines
3820
+ } else {
3821
+ for (var i=0; i<this.original_data.length; ++i) {
3822
+ prop['chart.line.visible'][i] = true;
3823
+ }
3824
+ }
3832
3825
 
3833
-
3834
- /**
3835
- * Animate the DIV that contains the canvas
3836
- */
3837
- jQuery('#' + div.id).animate({
3838
- width: obj.canvas.width - obj.gutterRight + 'px'
3839
- }, opt.duration, function () {trace_complete(obj)});
3826
+ RG.redraw();
3840
3827
 
3828
+ // Facilitate chaining
3841
3829
  return this;
3842
3830
  };
3843
3831
 
3844
3832
 
3845
3833
 
3846
3834
 
3835
+ /**
3836
+ * Returns true/false as to wether a line is hidden or not
3837
+ *
3838
+ * @param int index The index of the line to hide
3839
+ */
3840
+ this.hidden = function (index)
3841
+ {
3842
+ return !prop['chart.line.visible'][index];
3843
+ };
3844
+
3845
+
3846
+
3847
3847
  /**
3848
3848
  * Unfold
3849
3849
  *
@@ -3895,6 +3895,7 @@
3895
3895
  * @param object Options for the effect. Currently only "frames" is available.
3896
3896
  * @param int A function that is called when the ffect is complete
3897
3897
  */
3898
+ this.trace =
3898
3899
  this.trace2 = function ()
3899
3900
  {
3900
3901
  var obj = this;
@@ -3998,18 +3999,18 @@
3998
3999
  this.unfoldFromCenterTrace =
3999
4000
  this.unfoldFromCenterTrace2 = function ()
4000
4001
  {
4001
- var obj = this;
4002
- var opt = arguments[0] || {};
4003
- var frames = opt.frames || 30;
4004
- var frame = 0;
4005
- var data = RG.array_clone(obj.original_data);
4006
- var callback = arguments[1] || function () {};
4002
+ var obj = this,
4003
+ opt = arguments[0] || {},
4004
+ frames = opt.frames || 30,
4005
+ frame = 0,
4006
+ data = RG.arrayClone(obj.original_data),
4007
+ callback = arguments[1] || function () {};
4007
4008
 
4008
4009
 
4009
4010
 
4010
4011
  // Draw the chart once to get the scale values
4011
4012
  obj.canvas.style.visibility = 'hidden';
4012
- obj.Draw();
4013
+ obj.draw();
4013
4014
  var max = obj.scale2.max;
4014
4015
  RG.clear(obj.canvas);
4015
4016
  obj.canvas.style.visibility = 'visible';
@@ -4152,4 +4153,11 @@
4152
4153
  if (parseConfObjectForOptions) {
4153
4154
  RG.parseObjectStyleConfig(this, conf.options);
4154
4155
  }
4156
+
4157
+ /**
4158
+ * Allow all lines to start off as visible
4159
+ */
4160
+ for (var i=0; i<this.original_data.length; ++i) {
4161
+ prop['chart.line.visible'][i] = true;
4162
+ }
4155
4163
  };