rgraph-rails 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +1 -0
  3. data/README.md +2 -2
  4. data/lib/rgraph-rails/version.rb +1 -1
  5. data/vendor/assets/images/bullet.png +0 -0
  6. data/vendor/assets/images/facebook-large.png +0 -0
  7. data/vendor/assets/images/google-plus-large.png +0 -0
  8. data/vendor/assets/images/logo.png +0 -0
  9. data/vendor/assets/images/rgraph.jpg +0 -0
  10. data/vendor/assets/javascripts/RGraph.bar.js +533 -242
  11. data/vendor/assets/javascripts/RGraph.bipolar.js +152 -169
  12. data/vendor/assets/javascripts/RGraph.common.annotate.js +2 -2
  13. data/vendor/assets/javascripts/RGraph.common.context.js +2 -2
  14. data/vendor/assets/javascripts/RGraph.common.core.js +688 -373
  15. data/vendor/assets/javascripts/RGraph.common.csv.js +2 -2
  16. data/vendor/assets/javascripts/RGraph.common.deprecated.js +2 -2
  17. data/vendor/assets/javascripts/RGraph.common.dynamic.js +188 -193
  18. data/vendor/assets/javascripts/RGraph.common.effects.js +62 -38
  19. data/vendor/assets/javascripts/RGraph.common.key.js +35 -15
  20. data/vendor/assets/javascripts/RGraph.common.resizing.js +38 -21
  21. data/vendor/assets/javascripts/RGraph.common.sheets.js +2 -2
  22. data/vendor/assets/javascripts/RGraph.common.tooltips.js +48 -40
  23. data/vendor/assets/javascripts/RGraph.common.zoom.js +2 -2
  24. data/vendor/assets/javascripts/RGraph.drawing.background.js +33 -49
  25. data/vendor/assets/javascripts/RGraph.drawing.circle.js +27 -30
  26. data/vendor/assets/javascripts/RGraph.drawing.image.js +23 -26
  27. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +47 -40
  28. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +38 -42
  29. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +24 -28
  30. data/vendor/assets/javascripts/RGraph.drawing.poly.js +25 -39
  31. data/vendor/assets/javascripts/RGraph.drawing.rect.js +27 -32
  32. data/vendor/assets/javascripts/RGraph.drawing.text.js +53 -58
  33. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +24 -29
  34. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +45 -51
  35. data/vendor/assets/javascripts/RGraph.fuel.js +11 -9
  36. data/vendor/assets/javascripts/RGraph.funnel.js +40 -43
  37. data/vendor/assets/javascripts/RGraph.gantt.js +34 -34
  38. data/vendor/assets/javascripts/RGraph.gauge.js +64 -55
  39. data/vendor/assets/javascripts/RGraph.hbar.js +194 -137
  40. data/vendor/assets/javascripts/RGraph.hprogress.js +261 -167
  41. data/vendor/assets/javascripts/RGraph.line.js +520 -512
  42. data/vendor/assets/javascripts/RGraph.meter.js +11 -10
  43. data/vendor/assets/javascripts/RGraph.modaldialog.js +11 -2
  44. data/vendor/assets/javascripts/RGraph.odo.js +11 -9
  45. data/vendor/assets/javascripts/RGraph.pie.js +385 -100
  46. data/vendor/assets/javascripts/RGraph.radar.js +36 -29
  47. data/vendor/assets/javascripts/RGraph.rose.js +58 -41
  48. data/vendor/assets/javascripts/RGraph.rscatter.js +40 -36
  49. data/vendor/assets/javascripts/RGraph.scatter.js +441 -499
  50. data/vendor/assets/javascripts/RGraph.semicircularprogress.js +1015 -0
  51. data/vendor/assets/javascripts/RGraph.thermometer.js +37 -37
  52. data/vendor/assets/javascripts/RGraph.vprogress.js +285 -157
  53. data/vendor/assets/javascripts/RGraph.waterfall.js +62 -62
  54. data/vendor/assets/stylesheets/website.css +30 -16
  55. metadata +3 -2
@@ -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
  };