highcharts-rails 5.0.14 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.markdown +60 -0
  3. data/Rakefile +54 -5
  4. data/app/assets/images/highcharts/earth.svg +432 -0
  5. data/app/assets/javascripts/highcharts.js +5103 -3147
  6. data/app/assets/javascripts/highcharts/highcharts-3d.js +930 -277
  7. data/app/assets/javascripts/highcharts/highcharts-more.js +1374 -249
  8. data/app/assets/javascripts/highcharts/lib/canvg.js +3073 -0
  9. data/app/assets/javascripts/highcharts/lib/jspdf.js +16624 -0
  10. data/app/assets/javascripts/highcharts/lib/rgbcolor.js +299 -0
  11. data/app/assets/javascripts/highcharts/lib/svg2pdf.js +3488 -0
  12. data/app/assets/javascripts/highcharts/modules/accessibility.js +654 -212
  13. data/app/assets/javascripts/highcharts/modules/annotations.js +1552 -274
  14. data/app/assets/javascripts/highcharts/modules/boost-canvas.js +773 -0
  15. data/app/assets/javascripts/highcharts/modules/boost.js +636 -210
  16. data/app/assets/javascripts/highcharts/modules/broken-axis.js +2 -2
  17. data/app/assets/javascripts/highcharts/modules/bullet.js +364 -0
  18. data/app/assets/javascripts/highcharts/modules/data.js +766 -38
  19. data/app/assets/javascripts/highcharts/modules/drag-panes.js +588 -0
  20. data/app/assets/javascripts/highcharts/modules/drilldown.js +106 -36
  21. data/app/assets/javascripts/highcharts/modules/export-data.js +597 -0
  22. data/app/assets/javascripts/highcharts/modules/exporting.js +424 -162
  23. data/app/assets/javascripts/highcharts/modules/funnel.js +144 -22
  24. data/app/assets/javascripts/highcharts/modules/gantt.js +1154 -0
  25. data/app/assets/javascripts/highcharts/modules/grid-axis.js +1 -1
  26. data/app/assets/javascripts/highcharts/modules/heatmap.js +406 -80
  27. data/app/assets/javascripts/highcharts/modules/histogram-bellcurve.js +513 -0
  28. data/app/assets/javascripts/highcharts/modules/item-series.js +126 -0
  29. data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +31 -13
  30. data/app/assets/javascripts/highcharts/modules/offline-exporting.js +179 -57
  31. data/app/assets/javascripts/highcharts/modules/oldie.js +1378 -0
  32. data/app/assets/javascripts/highcharts/modules/overlapping-datalabels.js +8 -6
  33. data/app/assets/javascripts/highcharts/modules/parallel-coordinates.js +494 -0
  34. data/app/assets/javascripts/highcharts/modules/pareto.js +275 -0
  35. data/app/assets/javascripts/highcharts/modules/sankey.js +641 -0
  36. data/app/assets/javascripts/highcharts/modules/series-label.js +355 -145
  37. data/app/assets/javascripts/highcharts/modules/solid-gauge.js +122 -1
  38. data/app/assets/javascripts/highcharts/modules/static-scale.js +64 -0
  39. data/app/assets/javascripts/highcharts/modules/stock.js +1944 -676
  40. data/app/assets/javascripts/highcharts/modules/streamgraph.js +139 -0
  41. data/app/assets/javascripts/highcharts/modules/sunburst.js +2403 -0
  42. data/app/assets/javascripts/highcharts/modules/tilemap.js +1199 -0
  43. data/app/assets/javascripts/highcharts/modules/treemap.js +538 -134
  44. data/app/assets/javascripts/highcharts/modules/variable-pie.js +490 -0
  45. data/app/assets/javascripts/highcharts/modules/variwide.js +283 -0
  46. data/app/assets/javascripts/highcharts/modules/vector.js +294 -0
  47. data/app/assets/javascripts/highcharts/modules/windbarb.js +490 -0
  48. data/app/assets/javascripts/highcharts/modules/wordcloud.js +681 -0
  49. data/app/assets/javascripts/highcharts/modules/xrange.js +615 -0
  50. data/app/assets/javascripts/highcharts/themes/avocado.js +54 -0
  51. data/app/assets/javascripts/highcharts/themes/dark-blue.js +6 -6
  52. data/app/assets/javascripts/highcharts/themes/dark-green.js +6 -6
  53. data/app/assets/javascripts/highcharts/themes/dark-unica.js +6 -6
  54. data/app/assets/javascripts/highcharts/themes/gray.js +14 -10
  55. data/app/assets/javascripts/highcharts/themes/grid-light.js +6 -6
  56. data/app/assets/javascripts/highcharts/themes/grid.js +7 -5
  57. data/app/assets/javascripts/highcharts/themes/sand-signika.js +8 -7
  58. data/app/assets/javascripts/highcharts/themes/skies.js +15 -9
  59. data/app/assets/javascripts/highcharts/themes/sunset.js +53 -0
  60. data/app/assets/stylesheets/highcharts/highcharts.css +802 -0
  61. data/app/assets/stylesheets/highcharts/highcharts.scss +665 -0
  62. data/lib/highcharts/version.rb +1 -1
  63. metadata +31 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v5.0.14 (2017-07-28)
2
+ * @license Highcharts JS v6.0.0 (2017-10-04)
3
3
  *
4
4
  * (c) 2009-2017 Torstein Honsi
5
5
  *
@@ -384,7 +384,7 @@
384
384
  * @type {String}
385
385
  * @see [gapSize](plotOptions.series.gapSize)
386
386
  * @default relative
387
- * @validvalues ["relative", "value"]
387
+ * @validvalue ["relative", "value"]
388
388
  * @since 5.0.13
389
389
  * @product highstock
390
390
  * @apioption plotOptions.series.gapUnit
@@ -0,0 +1,364 @@
1
+ /**
2
+ * @license Highcharts JS v6.0.0 (2017-10-04)
3
+ *
4
+ * Bullet graph series type for Highcharts
5
+ *
6
+ * (c) 2010-2017 Kacper Madej
7
+ *
8
+ * License: www.highcharts.com/license
9
+ */
10
+ 'use strict';
11
+ (function(factory) {
12
+ if (typeof module === 'object' && module.exports) {
13
+ module.exports = factory;
14
+ } else {
15
+ factory(Highcharts);
16
+ }
17
+ }(function(Highcharts) {
18
+ (function(H) {
19
+ /**
20
+ * (c) 2010-2017 Kacper Madej
21
+ *
22
+ * License: www.highcharts.com/license
23
+ */
24
+
25
+
26
+ var each = H.each,
27
+ pick = H.pick,
28
+ isNumber = H.isNumber,
29
+ relativeLength = H.relativeLength,
30
+ seriesType = H.seriesType,
31
+ columnProto = H.seriesTypes.column.prototype;
32
+
33
+ /**
34
+ * The bullet series type.
35
+ *
36
+ * @constructor seriesTypes.bullet
37
+ * @augments seriesTypes.column
38
+ */
39
+ seriesType('bullet', 'column',
40
+ /**
41
+ * A bullet graph is a variation of a bar graph. The bullet graph features
42
+ * a single measure, compares it to a target, and displays it in the context
43
+ * of qualitative ranges of performance that could be set using
44
+ * [plotBands](#yAxis.plotBands) on [yAxis](#yAxis).
45
+ *
46
+ * @extends {plotOptions.column}
47
+ * @product highcharts
48
+ * @sample {highcharts} highcharts/demo/bullet-graph/ Bullet graph
49
+ * @since 6.0.0
50
+ * @excluding allAreas,boostThreshold,colorAxis,compare,compareBase
51
+ * @optionparent plotOptions.bullet
52
+ */
53
+ {
54
+ /**
55
+ * All options related with look and positiong of targets.
56
+ *
57
+ * @sample {highcharts} highcharts/plotoptions/bullet-targetoptions/
58
+ * Target options
59
+ *
60
+ * @type {Object}
61
+ * @since 6.0.0
62
+ * @product highcharts
63
+ */
64
+ targetOptions: {
65
+ /**
66
+ * The width of the rectangle representing the target. Could be set as
67
+ * a pixel value or as a percentage of a column width.
68
+ *
69
+ * @type {Number|String}
70
+ * @since 6.0.0
71
+ * @product highcharts
72
+ */
73
+ width: '140%',
74
+
75
+ /**
76
+ * The height of the rectangle representing the target.
77
+ *
78
+ * @since 6.0.0
79
+ * @product highcharts
80
+ */
81
+ height: 3,
82
+
83
+
84
+ /**
85
+ * The border width of the rectangle representing the target.
86
+ *
87
+ * In styled mode, use class `highcharts-bullet-target` instead.
88
+ *
89
+ * @since 6.0.0
90
+ * @product highcharts
91
+ */
92
+ borderWidth: 0
93
+
94
+ /**
95
+ * The border color of the rectangle representing the target. When
96
+ * not set, the point's border color is used.
97
+ *
98
+ * In styled mode, use class `highcharts-bullet-target` instead.
99
+ *
100
+ * @type {Color}
101
+ * @since 6.0.0
102
+ * @product highcharts
103
+ * @apioption plotOptions.bullet.targetOptions.borderColor
104
+ */
105
+
106
+ /**
107
+ * The color of the rectangle representing the target. When not set,
108
+ * point's color (if set in point's options -
109
+ * [`color`](#series.bullet.data.color)) or zone of the target value
110
+ * (if [`zones`](#plotOptions.bullet.zones) or
111
+ * [`negativeColor`](#plotOptions.bullet.negativeColor) are set)
112
+ * or the same color as the point has is used.
113
+ *
114
+ * In styled mode, use class `highcharts-bullet-target` instead.
115
+ *
116
+ * @type {Color}
117
+ * @since 6.0.0
118
+ * @product highcharts
119
+ * @apioption plotOptions.bullet.targetOptions.color
120
+ */
121
+
122
+ },
123
+
124
+ tooltip: {
125
+
126
+ pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: <b>{point.y}</b>. Target: <b>{point.target}</b><br/>'
127
+
128
+ }
129
+ }, {
130
+ pointArrayMap: ['y', 'target'],
131
+ parallelArrays: ['x', 'y', 'target'],
132
+
133
+ /**
134
+ * Draws the targets. For inverted chart, the `series.group` is rotated,
135
+ * so the same coordinates apply. This method is based on
136
+ * column series drawPoints function.
137
+ */
138
+ drawPoints: function() {
139
+ var series = this,
140
+ chart = series.chart,
141
+ options = series.options,
142
+ animationLimit = options.animationLimit || 250;
143
+
144
+ columnProto.drawPoints.apply(this);
145
+
146
+ each(series.points, function(point) {
147
+ var pointOptions = point.options,
148
+ shapeArgs,
149
+ targetGraphic = point.targetGraphic,
150
+ targetShapeArgs,
151
+ targetVal = point.target,
152
+ pointVal = point.y,
153
+ width,
154
+ height,
155
+ targetOptions,
156
+ y;
157
+
158
+ if (isNumber(targetVal) && targetVal !== null) {
159
+ targetOptions = H.merge(
160
+ options.targetOptions,
161
+ pointOptions.targetOptions
162
+ );
163
+ height = targetOptions.height;
164
+
165
+ shapeArgs = point.shapeArgs;
166
+ width = relativeLength(
167
+ targetOptions.width,
168
+ shapeArgs.width
169
+ );
170
+ y = series.yAxis.translate(
171
+ targetVal,
172
+ false,
173
+ true,
174
+ false,
175
+ true
176
+ ) - targetOptions.height / 2 - 0.5;
177
+
178
+ targetShapeArgs = series.crispCol.apply({
179
+ // Use fake series object to set borderWidth of target
180
+ chart: chart,
181
+ borderWidth: targetOptions.borderWidth,
182
+ options: {
183
+ crisp: options.crisp
184
+ }
185
+ }, [
186
+ shapeArgs.x + shapeArgs.width / 2 - width / 2,
187
+ y,
188
+ width,
189
+ height
190
+ ]);
191
+
192
+ if (targetGraphic) {
193
+ // Update
194
+ targetGraphic[
195
+ chart.pointCount < animationLimit ?
196
+ 'animate' :
197
+ 'attr'
198
+ ](targetShapeArgs);
199
+
200
+ // Add or remove tooltip reference
201
+ if (isNumber(pointVal) && pointVal !== null) {
202
+ targetGraphic.element.point = point;
203
+ } else {
204
+ targetGraphic.element.point = undefined;
205
+ }
206
+ } else {
207
+ point.targetGraphic = targetGraphic = chart.renderer
208
+ .rect()
209
+ .attr(targetShapeArgs)
210
+ .add(series.group);
211
+ }
212
+
213
+ // Presentational
214
+ targetGraphic.attr({
215
+ fill: pick(
216
+ targetOptions.color,
217
+ pointOptions.color,
218
+ (series.zones.length && (point.getZone.call({
219
+ series: series,
220
+ x: point.x,
221
+ y: targetVal,
222
+ options: {}
223
+ }).color || series.color)) || undefined,
224
+ point.color,
225
+ series.color
226
+ ),
227
+ stroke: pick(
228
+ targetOptions.borderColor,
229
+ point.borderColor,
230
+ series.options.borderColor
231
+ ),
232
+ 'stroke-width': targetOptions.borderWidth
233
+ });
234
+
235
+
236
+ // Add tooltip reference
237
+ if (isNumber(pointVal) && pointVal !== null) {
238
+ targetGraphic.element.point = point;
239
+ }
240
+
241
+ targetGraphic.addClass(point.getClassName() +
242
+ ' highcharts-bullet-target', true);
243
+ } else if (targetGraphic) {
244
+ point.targetGraphic = targetGraphic.destroy(); // #1269
245
+ }
246
+ });
247
+ },
248
+
249
+ /**
250
+ * Includes target values to extend extremes from y values.
251
+ */
252
+ getExtremes: function(yData) {
253
+ var series = this,
254
+ targetData = series.targetData,
255
+ yMax,
256
+ yMin;
257
+
258
+ columnProto.getExtremes.call(this, yData);
259
+
260
+ if (targetData && targetData.length) {
261
+ yMax = series.dataMax;
262
+ yMin = series.dataMin;
263
+ columnProto.getExtremes.call(this, targetData);
264
+ series.dataMax = Math.max(series.dataMax, yMax);
265
+ series.dataMin = Math.min(series.dataMin, yMin);
266
+ }
267
+ }
268
+ }, /** @lends seriesTypes.ohlc.prototype.pointClass.prototype */ {
269
+ /**
270
+ * Destroys target graphic.
271
+ */
272
+ destroy: function() {
273
+ if (this.targetGraphic) {
274
+ this.targetGraphic = this.targetGraphic.destroy();
275
+ }
276
+ columnProto.pointClass.prototype.destroy.apply(this, arguments);
277
+ }
278
+ });
279
+
280
+
281
+ /**
282
+ * A `bullet` series. If the [type](#series.bullet.type) option is not
283
+ * specified, it is inherited from [chart.type](#chart.type).
284
+ *
285
+ * For options that apply to multiple series, it is recommended to add
286
+ * them to the [plotOptions.series](#plotOptions.series) options structure.
287
+ * To apply to all series of this specific type, apply it to [plotOptions.
288
+ * bullet](#plotOptions.bullet).
289
+ *
290
+ * @type {Object}
291
+ * @since 6.0.0
292
+ * @extends series,plotOptions.bullet
293
+ * @excluding dataParser,dataURL
294
+ * @product highcharts
295
+ * @apioption series.bullet
296
+ */
297
+
298
+ /**
299
+ * An array of data points for the series. For the `bullet` series type,
300
+ * points can be given in the following ways:
301
+ *
302
+ * 1. An array of arrays with 3 or 2 values. In this case, the values
303
+ * correspond to `x,y,target`. If the first value is a string,
304
+ * it is applied as the name of the point, and the `x` value is inferred.
305
+ * The `x` value can also be omitted, in which case the inner arrays
306
+ * should be of length 2\. Then the `x` value is automatically calculated,
307
+ * either starting at 0 and incremented by 1, or from `pointStart`
308
+ * and `pointInterval` given in the series options.
309
+ *
310
+ * ```js
311
+ * data: [
312
+ * [0, 40, 75],
313
+ * [1, 50, 50],
314
+ * [2, 60, 40]
315
+ * ]
316
+ * ```
317
+ *
318
+ * 2. An array of objects with named values. The objects are point
319
+ * configuration objects as seen below. If the total number of data
320
+ * points exceeds the series' [turboThreshold](#series.bullet.turboThreshold),
321
+ * this option is not available.
322
+ *
323
+ * ```js
324
+ * data: [{
325
+ * x: 0,
326
+ * y: 40,
327
+ * target: 75,
328
+ * name: "Point1",
329
+ * color: "#00FF00"
330
+ * }, {
331
+ * x: 1,
332
+ * y: 60,
333
+ * target: 40,
334
+ * name: "Point2",
335
+ * color: "#FF00FF"
336
+ * }]
337
+ * ```
338
+ *
339
+ * @type {Array<Object|Array>}
340
+ * @since 6.0.0
341
+ * @extends series.column.data
342
+ * @product highcharts
343
+ * @apioption series.bullet.data
344
+ */
345
+
346
+ /**
347
+ * The target value of a point.
348
+ *
349
+ * @type {Number}
350
+ * @since 6.0.0
351
+ * @product highcharts
352
+ * @apioption series.bullet.data.target
353
+ */
354
+
355
+ /**
356
+ * Individual target options for each point.
357
+ *
358
+ * @extends series.bullet.targetOptions
359
+ * @product highcharts
360
+ * @apioption series.bullet.data.targetOptions
361
+ */
362
+
363
+ }(Highcharts));
364
+ }));
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v5.0.14 (2017-07-28)
2
+ * @license Highcharts JS v6.0.0 (2017-10-04)
3
3
  * Data module
4
4
  *
5
5
  * (c) 2012-2017 Torstein Honsi
@@ -34,8 +34,311 @@
34
34
  inArray = Highcharts.inArray,
35
35
  isNumber = Highcharts.isNumber,
36
36
  splat = Highcharts.splat,
37
+ fireEvent = Highcharts.fireEvent,
38
+ some,
37
39
  SeriesBuilder;
38
40
 
41
+ // `some` function
42
+ if (!Array.prototype.some) {
43
+ some = function(arr, fn, ctx) { // legacy
44
+ var i = 0,
45
+ len = arr.length;
46
+
47
+ for (; i < len; i++) {
48
+ if (fn.call(ctx, arr[i], i, arr) === true) {
49
+ return;
50
+ }
51
+ }
52
+ };
53
+ } else {
54
+ some = function(arr, fn, ctx) {
55
+ Array.prototype.some.call(arr, fn, ctx);
56
+ };
57
+ }
58
+
59
+ /**
60
+ * The Data module provides a simplified interface for adding data to
61
+ * a chart from sources like CVS, HTML tables or grid views. See also
62
+ * the [tutorial article on the Data module](http://www.highcharts.com/docs/working-
63
+ * with-data/data-module).
64
+ *
65
+ * It requires the `modules/data.js` file to be loaded.
66
+ *
67
+ * Please note that the default way of adding data in Highcharts, without
68
+ * the need of a module, is through the [series.data](#series.data)
69
+ * option.
70
+ *
71
+ * @sample {highcharts} highcharts/demo/column-parsed/ HTML table
72
+ * @sample {highcharts} highcharts/data/csv/ CSV
73
+ * @since 4.0
74
+ * @product highcharts
75
+ * @apioption data
76
+ */
77
+
78
+ /**
79
+ * A two-dimensional array representing the input data on tabular form.
80
+ * This input can be used when the data is already parsed, for example
81
+ * from a grid view component. Each cell can be a string or number.
82
+ * If not switchRowsAndColumns is set, the columns are interpreted as
83
+ * series.
84
+ *
85
+ * @type {Array<Array<Mixed>>}
86
+ * @see [data.rows](#data.rows)
87
+ * @sample {highcharts} highcharts/data/columns/ Columns
88
+ * @since 4.0
89
+ * @product highcharts
90
+ * @apioption data.columns
91
+ */
92
+
93
+ /**
94
+ * The callback that is evaluated when the data is finished loading,
95
+ * optionally from an external source, and parsed. The first argument
96
+ * passed is a finished chart options object, containing the series.
97
+ * These options can be extended with additional options and passed
98
+ * directly to the chart constructor.
99
+ *
100
+ * @type {Function}
101
+ * @see [data.parsed](#data.parsed)
102
+ * @sample {highcharts} highcharts/data/complete/ Modify data on complete
103
+ * @since 4.0
104
+ * @product highcharts
105
+ * @apioption data.complete
106
+ */
107
+
108
+ /**
109
+ * A comma delimited string to be parsed. Related options are [startRow](#data.
110
+ * startRow), [endRow](#data.endRow), [startColumn](#data.startColumn)
111
+ * and [endColumn](#data.endColumn) to delimit what part of the table
112
+ * is used. The [lineDelimiter](#data.lineDelimiter) and [itemDelimiter](#data.
113
+ * itemDelimiter) options define the CSV delimiter formats.
114
+ *
115
+ * The built-in CSV parser doesn't support all flavours of CSV, so in
116
+ * some cases it may be necessary to use an external CSV parser. See
117
+ * [this example](http://jsfiddle.net/highcharts/u59176h4/) of parsing
118
+ * CSV through the MIT licensed [Papa Parse](http://papaparse.com/)
119
+ * library.
120
+ *
121
+ * @type {String}
122
+ * @sample {highcharts} highcharts/data/csv/ Data from CSV
123
+ * @since 4.0
124
+ * @product highcharts
125
+ * @apioption data.csv
126
+ */
127
+
128
+ /**
129
+ * Which of the predefined date formats in Date.prototype.dateFormats
130
+ * to use to parse date values. Defaults to a best guess based on what
131
+ * format gives valid and ordered dates.
132
+ *
133
+ * Valid options include:
134
+ *
135
+ * * `YYYY-mm-dd`
136
+ * * `dd/mm/YYYY`
137
+ * * `mm/dd/YYYY`
138
+ * * `dd/mm/YY`
139
+ * * `mm/dd/YY`
140
+ *
141
+ * @validvalue [undefined, "YYYY-mm-dd", "dd/mm/YYYY", "mm/dd/YYYY", "dd/mm/YYYY", "dd/mm/YY", "mm/dd/YY"]
142
+ * @type {String}
143
+ * @see [data.parseDate](#data.parseDate)
144
+ * @sample {highcharts} highcharts/data/dateformat-auto/ Best guess date format
145
+ * @since 4.0
146
+ * @product highcharts
147
+ * @apioption data.dateFormat
148
+ */
149
+
150
+ /**
151
+ * The decimal point used for parsing numbers in the CSV.
152
+ *
153
+ * If both this and data.delimiter is set to false, the parser will
154
+ * attempt to deduce the decimal point automatically.
155
+ *
156
+ * @type {String}
157
+ * @sample {highcharts} highcharts/data/delimiters/ Comma as decimal point
158
+ * @default .
159
+ * @since 4.1.0
160
+ * @product highcharts
161
+ * @apioption data.decimalPoint
162
+ */
163
+
164
+ /**
165
+ * In tabular input data, the last column (indexed by 0) to use. Defaults
166
+ * to the last column containing data.
167
+ *
168
+ * @type {Number}
169
+ * @sample {highcharts} highcharts/data/start-end/ Limited data
170
+ * @since 4.0
171
+ * @product highcharts
172
+ * @apioption data.endColumn
173
+ */
174
+
175
+ /**
176
+ * In tabular input data, the last row (indexed by 0) to use. Defaults
177
+ * to the last row containing data.
178
+ *
179
+ * @type {Number}
180
+ * @sample {highcharts} highcharts/data/start-end/ Limited data
181
+ * @since 4.0.4
182
+ * @product highcharts
183
+ * @apioption data.endRow
184
+ */
185
+
186
+ /**
187
+ * Whether to use the first row in the data set as series names.
188
+ *
189
+ * @type {Boolean}
190
+ * @sample {highcharts} highcharts/data/start-end/ Don't get series names from the CSV
191
+ * @sample {highstock} highcharts/data/start-end/ Don't get series names from the CSV
192
+ * @default true
193
+ * @since 4.1.0
194
+ * @product highcharts highstock
195
+ * @apioption data.firstRowAsNames
196
+ */
197
+
198
+ /**
199
+ * The key for a Google Spreadsheet to load. See [general information
200
+ * on GS](https://developers.google.com/gdata/samples/spreadsheet_sample).
201
+ *
202
+ * @type {String}
203
+ * @sample {highcharts} highcharts/data/google-spreadsheet/ Load a Google Spreadsheet
204
+ * @since 4.0
205
+ * @product highcharts
206
+ * @apioption data.googleSpreadsheetKey
207
+ */
208
+
209
+ /**
210
+ * The Google Spreadsheet worksheet to use in combination with [googleSpreadsheetKey](#data.
211
+ * googleSpreadsheetKey). The available id's from your sheet can be
212
+ * read from `https://spreadsheets.google.com/feeds/worksheets/{key}/public/basic`
213
+ *
214
+ * @type {String}
215
+ * @sample {highcharts} highcharts/data/google-spreadsheet/ Load a Google Spreadsheet
216
+ * @since 4.0
217
+ * @product highcharts
218
+ * @apioption data.googleSpreadsheetWorksheet
219
+ */
220
+
221
+ /**
222
+ * Item or cell delimiter for parsing CSV. Defaults to the tab character
223
+ * `\t` if a tab character is found in the CSV string, if not it defaults
224
+ * to `,`.
225
+ *
226
+ * If this is set to false or undefined, the parser will attempt to deduce
227
+ * the delimiter automatically.
228
+ *
229
+ * @type {String}
230
+ * @sample {highcharts} highcharts/data/delimiters/ Delimiters
231
+ * @since 4.0
232
+ * @product highcharts
233
+ * @apioption data.itemDelimiter
234
+ */
235
+
236
+ /**
237
+ * Line delimiter for parsing CSV.
238
+ *
239
+ * @type {String}
240
+ * @sample {highcharts} highcharts/data/delimiters/ Delimiters
241
+ * @default \n
242
+ * @since 4.0
243
+ * @product highcharts
244
+ * @apioption data.lineDelimiter
245
+ */
246
+
247
+ /**
248
+ * A callback function to parse string representations of dates into
249
+ * JavaScript timestamps. Should return an integer timestamp on success.
250
+ *
251
+ * @type {Function}
252
+ * @see [dateFormat](#data.dateFormat)
253
+ * @since 4.0
254
+ * @product highcharts
255
+ * @apioption data.parseDate
256
+ */
257
+
258
+ /**
259
+ * A callback function to access the parsed columns, the two-dimentional
260
+ * input data array directly, before they are interpreted into series
261
+ * data and categories. Return `false` to stop completion, or call `this.
262
+ * complete()` to continue async.
263
+ *
264
+ * @type {Function}
265
+ * @see [data.complete](#data.complete)
266
+ * @sample {highcharts} highcharts/data/parsed/ Modify data after parse
267
+ * @since 4.0
268
+ * @product highcharts
269
+ * @apioption data.parsed
270
+ */
271
+
272
+ /**
273
+ * The same as the columns input option, but defining rows intead of
274
+ * columns.
275
+ *
276
+ * @type {Array<Array<Mixed>>}
277
+ * @see [data.columns](#data.columns)
278
+ * @sample {highcharts} highcharts/data/rows/ Data in rows
279
+ * @since 4.0
280
+ * @product highcharts
281
+ * @apioption data.rows
282
+ */
283
+
284
+ /**
285
+ * An array containing object with Point property names along with what
286
+ * column id the property should be taken from.
287
+ *
288
+ * @type {Array<Object>}
289
+ * @sample {highcharts} highcharts/data/seriesmapping-label/ Label from data set
290
+ * @since 4.0.4
291
+ * @product highcharts
292
+ * @apioption data.seriesMapping
293
+ */
294
+
295
+ /**
296
+ * In tabular input data, the first column (indexed by 0) to use.
297
+ *
298
+ * @type {Number}
299
+ * @sample {highcharts} highcharts/data/start-end/ Limited data
300
+ * @default 0
301
+ * @since 4.0
302
+ * @product highcharts
303
+ * @apioption data.startColumn
304
+ */
305
+
306
+ /**
307
+ * In tabular input data, the first row (indexed by 0) to use.
308
+ *
309
+ * @type {Number}
310
+ * @sample {highcharts} highcharts/data/start-end/ Limited data
311
+ * @default 0
312
+ * @since 4.0
313
+ * @product highcharts
314
+ * @apioption data.startRow
315
+ */
316
+
317
+ /**
318
+ * Switch rows and columns of the input data, so that `this.columns`
319
+ * effectively becomes the rows of the data set, and the rows are interpreted
320
+ * as series.
321
+ *
322
+ * @type {Boolean}
323
+ * @sample {highcharts} highcharts/data/switchrowsandcolumns/ Switch rows and columns
324
+ * @default false
325
+ * @since 4.0
326
+ * @product highcharts
327
+ * @apioption data.switchRowsAndColumns
328
+ */
329
+
330
+ /**
331
+ * A HTML table or the id of such to be parsed as input data. Related
332
+ * options are `startRow`, `endRow`, `startColumn` and `endColumn` to
333
+ * delimit what part of the table is used.
334
+ *
335
+ * @type {String|HTMLElement}
336
+ * @sample {highcharts} highcharts/demo/column-parsed/ Parsed table
337
+ * @since 4.0
338
+ * @product highcharts
339
+ * @apioption data.table
340
+ */
341
+
39
342
 
40
343
  // The Data constructor
41
344
  var Data = function(dataOptions, chartOptions) {
@@ -74,14 +377,14 @@
74
377
  // Parse a HTML table if options.table is given
75
378
  this.parseTable();
76
379
 
77
- // Parse a Google Spreadsheet
380
+ // Parse a Google Spreadsheet
78
381
  this.parseGoogleSpreadsheet();
79
382
  }
80
383
 
81
384
  },
82
385
 
83
386
  /**
84
- * Get the column distribution. For example, a line series takes a single column for
387
+ * Get the column distribution. For example, a line series takes a single column for
85
388
  * Y values. A range series takes two columns for low and high values respectively,
86
389
  * and an OHLC series takes four columns.
87
390
  */
@@ -138,7 +441,7 @@
138
441
  // Add missing columns
139
442
  for (i = 0; i < numberOfValueColumnsNeeded; i++) {
140
443
  if (!builder.hasReader(pointArrayMap[i])) {
141
- //builder.addNextColumnReader(pointArrayMap[i]);
444
+ // builder.addNextColumnReader(pointArrayMap[i]);
142
445
  // Create and add a column reader for the next free column index
143
446
  builder.addColumnReader(undefined, pointArrayMap[i]);
144
447
  }
@@ -190,18 +493,369 @@
190
493
  /**
191
494
  * Parse a CSV input string
192
495
  */
193
- parseCSV: function() {
496
+ parseCSV: function(inOptions) {
194
497
  var self = this,
195
- options = this.options,
498
+ options = this.options || inOptions,
196
499
  csv = options.csv,
197
- columns = this.columns,
500
+ columns,
198
501
  startRow = options.startRow || 0,
199
502
  endRow = options.endRow || Number.MAX_VALUE,
200
503
  startColumn = options.startColumn || 0,
201
504
  endColumn = options.endColumn || Number.MAX_VALUE,
202
505
  itemDelimiter,
203
506
  lines,
204
- activeRowNo = 0;
507
+ rowIt = 0,
508
+ // activeRowNo = 0,
509
+ dataTypes = [],
510
+ // We count potential delimiters in the prepass, and use the
511
+ // result as the basis of half-intelligent guesses.
512
+ potDelimiters = {
513
+ ',': 0,
514
+ ';': 0,
515
+ '\t': 0
516
+ };
517
+
518
+ columns = this.columns = this.columns || [];
519
+
520
+ /*
521
+ This implementation is quite verbose. It will be shortened once
522
+ it's stable and passes all the test.
523
+
524
+ It's also not written with speed in mind, instead everything is
525
+ very seggregated, and there a several redundant loops.
526
+ This is to make it easier to stabilize the code initially.
527
+
528
+ We do a pre-pass on the first 4 rows to make some intelligent
529
+ guesses on the set. Guessed delimiters are in this pass counted.
530
+
531
+ Auto detecting delimiters
532
+ - If we meet a quoted string, the next symbol afterwards
533
+ (that's not \s, \t) is the delimiter
534
+ - If we meet a date, the next symbol afterwards is the delimiter
535
+
536
+ Date formats
537
+ - If we meet a column with date formats, check all of them to
538
+ see if one of the potential months crossing 12. If it does,
539
+ we now know the format
540
+
541
+ It would make things easier to guess the delimiter before
542
+ doing the actual parsing.
543
+
544
+ General rules:
545
+ - Quoting is allowed, e.g: "Col 1",123,321
546
+ - Quoting is optional, e.g.: Col1,123,321
547
+ - Doubble quoting is escaping, e.g. "Col ""Hello world""",123
548
+ - Spaces are considered part of the data: Col1 ,123
549
+ - New line is always the row delimiter
550
+ - Potential column delimiters are , ; \t
551
+ - First row may optionally contain headers
552
+ - The last row may or may not have a row delimiter
553
+ - Comments are optionally supported, in which case the comment
554
+ must start at the first column, and the rest of the line will
555
+ be ignored
556
+ */
557
+
558
+ // Parse a single row
559
+ function parseRow(columnStr, rowNumber, noAdd, callbacks) {
560
+ var i = 0,
561
+ c = '',
562
+ cl = '',
563
+ cn = '',
564
+ token = '',
565
+ column = 0;
566
+
567
+ function read(j) {
568
+ c = columnStr[j];
569
+ cl = columnStr[j - 1];
570
+ cn = columnStr[j + 1];
571
+ }
572
+
573
+ function pushType(type) {
574
+ if (dataTypes.length < column + 1) {
575
+ dataTypes.push([type]);
576
+ }
577
+ if (dataTypes[column][dataTypes[column].length - 1] !== type) {
578
+ dataTypes[column].push(type);
579
+ }
580
+ }
581
+
582
+ function push() {
583
+ if (startColumn > column || column > endColumn) {
584
+ // Skip this column
585
+ return;
586
+ }
587
+
588
+ if (!isNaN(parseFloat(token)) && isFinite(token)) {
589
+ token = parseFloat(token);
590
+ pushType('number');
591
+ } else if (!isNaN(Date.parse(token))) {
592
+ token = token.replace(/\//g, '-');
593
+ pushType('date');
594
+ } else {
595
+ pushType('string');
596
+ }
597
+
598
+ if (columns.length < column + 1) {
599
+ columns.push([]);
600
+ }
601
+
602
+ if (!noAdd) {
603
+ columns[column].push(token);
604
+ }
605
+
606
+ token = '';
607
+ ++column;
608
+ }
609
+
610
+ if (!columnStr.trim().length) {
611
+ return;
612
+ }
613
+
614
+ if (columnStr.trim()[0] === '#') {
615
+ return;
616
+ }
617
+
618
+ for (; i < columnStr.length; i++) {
619
+ read(i);
620
+
621
+ // Quoted string
622
+ if (c === '#') {
623
+ // The rest of the row is a comment
624
+ return;
625
+ } else if (c === '"') {
626
+ read(++i);
627
+
628
+ while (i < columnStr.length) {
629
+ if (c === '"' && cl !== '"' && cn !== '"') {
630
+ break;
631
+ }
632
+
633
+ if (c !== '"' || (c === '"' && cl !== '"')) {
634
+ token += c;
635
+ }
636
+
637
+ read(++i);
638
+ }
639
+
640
+ // Perform "plugin" handling
641
+ } else if (callbacks && callbacks[c]) {
642
+ if (callbacks[c](c, token)) {
643
+ push();
644
+ }
645
+
646
+ // Delimiter - push current token
647
+ } else if (c === itemDelimiter) {
648
+ push();
649
+
650
+ // Actual column data
651
+ } else {
652
+ token += c;
653
+ }
654
+ }
655
+
656
+ push();
657
+
658
+ if (column < columns.length) {
659
+ // There might be an issue.
660
+ // This set is either
661
+
662
+ // Fill in
663
+ if (!noAdd) {
664
+ for (var z = column; z < columns.length; z++) {
665
+ columns[z].push(0);
666
+ }
667
+ }
668
+ }
669
+ }
670
+
671
+ // Attempt to guess the delimiter
672
+ function guessDelimiter(lines) {
673
+ var points = 0,
674
+ commas = 0,
675
+ guessed = false,
676
+ handler = function(c, token) {
677
+ if (c === ',') {
678
+ commas++;
679
+ }
680
+ if (c === '.') {
681
+ points++;
682
+ }
683
+
684
+ if (typeof potDelimiters[c] !== 'undefined') {
685
+ // Check what we have in token now
686
+
687
+ if (
688
+ // We can't make a deduction when token is a number,
689
+ // since the decimal delimiter may interfere.
690
+ (isNaN(parseFloat(token)) || !isFinite(token)) &&
691
+ (
692
+ // Highcharts.isString(token) ||
693
+ !isNaN(Date.parse(token))
694
+ )
695
+ ) {
696
+ potDelimiters[c]++;
697
+ return true;
698
+ }
699
+ }
700
+ },
701
+ callbacks = {
702
+ ';': handler,
703
+ ',': handler,
704
+ '\t': handler
705
+ };
706
+
707
+ some(lines, function(columnStr, i) {
708
+ // We should be able to detect dateformats within 13 rows
709
+ if (i > 13) {
710
+ return true;
711
+ }
712
+ parseRow(columnStr, i, true, callbacks);
713
+ });
714
+
715
+ // Count the potential delimiters.
716
+ // This could be improved by checking if the number of delimiters
717
+ // equals the number of columns - 1
718
+ if (potDelimiters[';'] > potDelimiters[',']) {
719
+ guessed = ';';
720
+ } else if (potDelimiters[','] > potDelimiters[';']) {
721
+ guessed = ',';
722
+ } else {
723
+ // No good guess could be made..
724
+ guessed = ',';
725
+ }
726
+
727
+ // Try to deduce the decimal point if it's not explicitly set.
728
+ // If both commas or points is > 0 there is likely an issue
729
+ if (!options.decimalPoint) {
730
+ if (points > commas) {
731
+ options.decimalPoint = '.';
732
+ } else {
733
+ options.decimalPoint = ',';
734
+ }
735
+
736
+ // Apply a new decimal regex based on the pressumed decimal sep.
737
+ self.decimalRegex = new RegExp(
738
+ '^(-?[0-9]+)' +
739
+ options.decimalPoint +
740
+ '([0-9]+)$'
741
+ );
742
+ }
743
+
744
+ return guessed;
745
+ }
746
+
747
+ /* Tries to guess the date format
748
+ * - Check if either month candidate exceeds 12
749
+ * - Check if year is missing (use current year)
750
+ * - Check if a shortened year format is used (e.g. 1/1/99)
751
+ * - If no guess can be made, the user must be prompted
752
+ * data is the data to deduce a format based on
753
+ */
754
+ function deduceDateFormat(data, limit) {
755
+ var format = 'YYYY-mm-dd',
756
+ thing,
757
+ guessedFormat,
758
+ calculatedFormat,
759
+ i = 0,
760
+ madeDeduction = false,
761
+ // candidates = {},
762
+ stable = [],
763
+ max = [],
764
+ j;
765
+
766
+ if (!limit || limit > data.length) {
767
+ limit = data.length;
768
+ }
769
+
770
+ for (; i < limit; i++) {
771
+ if (typeof data[i] !== 'undefined' && data[i] && data[i].length) {
772
+ thing = data[i]
773
+ .trim()
774
+ .replace(/\//g, ' ')
775
+ .replace(/\-/g, ' ')
776
+ .split(' ');
777
+
778
+ guessedFormat = [
779
+ '',
780
+ '',
781
+ ''
782
+ ];
783
+
784
+
785
+ for (j = 0; j < thing.length; j++) {
786
+ if (j < guessedFormat.length) {
787
+ thing[j] = parseInt(thing[j], 10);
788
+
789
+ if (thing[j]) {
790
+
791
+ max[j] = (!max[j] || max[j] < thing[j]) ? thing[j] : max[j];
792
+
793
+ if (typeof stable[j] !== 'undefined') {
794
+ if (stable[j] !== thing[j]) {
795
+ stable[j] = false;
796
+ }
797
+ } else {
798
+ stable[j] = thing[j];
799
+ }
800
+
801
+ if (thing[j] > 31) {
802
+ if (thing[j] < 100) {
803
+ guessedFormat[j] = 'YY';
804
+ } else {
805
+ guessedFormat[j] = 'YYYY';
806
+ }
807
+ // madeDeduction = true;
808
+ } else if (thing[j] > 12 && thing[j] <= 31) {
809
+ guessedFormat[j] = 'dd';
810
+ madeDeduction = true;
811
+ } else if (!guessedFormat[j].length) {
812
+ guessedFormat[j] = 'mm';
813
+ }
814
+ }
815
+ }
816
+ }
817
+ }
818
+ }
819
+
820
+ if (madeDeduction) {
821
+
822
+ // This handles a few edge cases with hard to guess dates
823
+ for (j = 0; j < stable.length; j++) {
824
+ if (stable[j] !== false) {
825
+ if (max[j] > 12 && guessedFormat[j] !== 'YY' && guessedFormat[j] !== 'YYYY') {
826
+ guessedFormat[j] = 'YY';
827
+ }
828
+ } else if (max[j] > 12 && guessedFormat[j] === 'mm') {
829
+ guessedFormat[j] = 'dd';
830
+ }
831
+ }
832
+
833
+ calculatedFormat = guessedFormat.join('/');
834
+
835
+
836
+ // If the caculated format is not valid, we need to present an error.
837
+
838
+ if (!(options.dateFormats || self.dateFormats)[calculatedFormat]) {
839
+ // This should emit an event instead
840
+ fireEvent('invalidDateFormat');
841
+ Highcharts.error('Could not deduce date format');
842
+ return format;
843
+ }
844
+
845
+ return calculatedFormat;
846
+ }
847
+
848
+ return format;
849
+ }
850
+
851
+ /* Figure out the best axis types for the data
852
+ * - If the first column is a number, we're good
853
+ * - If the first column is a date, set to date/time
854
+ * - If the first column is a string, set to categories
855
+ */
856
+ function deduceAxisTypes() {
857
+
858
+ }
205
859
 
206
860
  if (csv) {
207
861
 
@@ -210,31 +864,67 @@
210
864
  .replace(/\r/g, '\n') // Mac
211
865
  .split(options.lineDelimiter || '\n');
212
866
 
213
- itemDelimiter = options.itemDelimiter || (csv.indexOf('\t') !== -1 ? '\t' : ',');
867
+ if (!startRow || startRow < 0) {
868
+ startRow = 0;
869
+ }
214
870
 
215
- each(lines, function(line, rowNo) {
216
- var trimmed = self.trim(line),
217
- isComment = trimmed.indexOf('#') === 0,
218
- isBlank = trimmed === '',
219
- items;
871
+ if (!endRow || endRow > lines.length) {
872
+ endRow = lines.length;
873
+ }
220
874
 
221
- if (rowNo >= startRow && rowNo <= endRow && !isComment && !isBlank) {
222
- items = line.split(itemDelimiter);
223
- each(items, function(item, colNo) {
224
- if (colNo >= startColumn && colNo <= endColumn) {
225
- if (!columns[colNo - startColumn]) {
226
- columns[colNo - startColumn] = [];
227
- }
875
+ if (options.itemDelimiter) {
876
+ itemDelimiter = options.itemDelimiter;
877
+ } else {
878
+ itemDelimiter = null;
879
+ itemDelimiter = guessDelimiter(lines);
880
+ }
228
881
 
229
- columns[colNo - startColumn][activeRowNo] = item;
230
- }
231
- });
232
- activeRowNo += 1;
233
- }
234
- });
882
+ for (rowIt = startRow; rowIt < endRow; rowIt++) {
883
+ parseRow(lines[rowIt], rowIt);
884
+ }
885
+
886
+ // //Make sure that there's header columns for everything
887
+ // each(columns, function (col) {
888
+
889
+ // });
890
+
891
+ deduceAxisTypes();
892
+
893
+ if ((!options.columnTypes || options.columnTypes.length === 0) &&
894
+ dataTypes.length &&
895
+ dataTypes[0].length &&
896
+ dataTypes[0][1] === 'date' &&
897
+ !options.dateFormat) {
898
+ options.dateFormat = deduceDateFormat(columns[0]);
899
+ }
900
+
901
+
902
+ // each(lines, function (line, rowNo) {
903
+ // var trimmed = self.trim(line),
904
+ // isComment = trimmed.indexOf('#') === 0,
905
+ // isBlank = trimmed === '',
906
+ // items;
907
+
908
+ // if (rowNo >= startRow && rowNo <= endRow && !isComment && !isBlank) {
909
+ // items = line.split(itemDelimiter);
910
+ // each(items, function (item, colNo) {
911
+ // if (colNo >= startColumn && colNo <= endColumn) {
912
+ // if (!columns[colNo - startColumn]) {
913
+ // columns[colNo - startColumn] = [];
914
+ // }
915
+
916
+ // columns[colNo - startColumn][activeRowNo] = item;
917
+ // }
918
+ // });
919
+ // activeRowNo += 1;
920
+ // }
921
+ // });
922
+ //
235
923
 
236
924
  this.dataFound();
237
925
  }
926
+
927
+ return columns;
238
928
  },
239
929
 
240
930
  /**
@@ -274,6 +964,7 @@
274
964
  },
275
965
 
276
966
  /**
967
+ * Parse a Google spreadsheet.
277
968
  */
278
969
  parseGoogleSpreadsheet: function() {
279
970
  var self = this,
@@ -303,7 +994,7 @@
303
994
  rowCount = 0,
304
995
  i;
305
996
 
306
- // First, find the total number of columns and rows that
997
+ // First, find the total number of columns and rows that
307
998
  // are actually filled with data
308
999
  for (i = 0; i < cellCount; i++) {
309
1000
  cell = cells[i];
@@ -423,7 +1114,7 @@
423
1114
 
424
1115
  // Disable number or date parsing by setting the X axis type to category
425
1116
  if (forceCategory || (row === 0 && firstRowAsNames)) {
426
- column[row] = trimVal;
1117
+ column[row] = '' + trimVal;
427
1118
 
428
1119
  } else if (+trimInsideVal === floatVal) { // is numeric
429
1120
 
@@ -449,7 +1140,7 @@
449
1140
  column[row] = dateVal;
450
1141
  column.isDatetime = true;
451
1142
 
452
- // Check if the dates are uniformly descending or ascending. If they
1143
+ // Check if the dates are uniformly descending or ascending. If they
453
1144
  // are not, chances are that they are a different time format, so check
454
1145
  // for alternative.
455
1146
  if (column[row + 1] !== undefined) {
@@ -476,14 +1167,14 @@
476
1167
  }
477
1168
 
478
1169
  // If strings are intermixed with numbers or dates in a parsed column, it is an indication
479
- // that parsing went wrong or the data was not intended to display as numbers or dates and
480
- // parsing is too aggressive. Fall back to categories. Demonstrated in the
1170
+ // that parsing went wrong or the data was not intended to display as numbers or dates and
1171
+ // parsing is too aggressive. Fall back to categories. Demonstrated in the
481
1172
  // highcharts/demo/column-drilldown sample.
482
1173
  if (isXColumn && column.mixed) {
483
1174
  columns[col] = rawColumns[col];
484
1175
  }
485
1176
 
486
- // If the 0 column is date or number and descending, reverse all columns.
1177
+ // If the 0 column is date or number and descending, reverse all columns.
487
1178
  if (isXColumn && descending && this.options.sort) {
488
1179
  for (col = 0; col < columns.length; col++) {
489
1180
  columns[col].reverse();
@@ -505,6 +1196,12 @@
505
1196
  return Date.UTC(+match[1], match[2] - 1, +match[3]);
506
1197
  }
507
1198
  },
1199
+ 'YYYY/mm/dd': {
1200
+ regex: /^([0-9]{4})[\-\/\.]([0-9]{2})[\-\/\.]([0-9]{2})$/,
1201
+ parser: function(match) {
1202
+ return Date.UTC(+match[1], match[2] - 1, +match[3]);
1203
+ }
1204
+ },
508
1205
  'dd/mm/YYYY': {
509
1206
  regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{4})$/,
510
1207
  parser: function(match) {
@@ -521,7 +1218,16 @@
521
1218
  'dd/mm/YY': {
522
1219
  regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{2})$/,
523
1220
  parser: function(match) {
524
- return Date.UTC(+match[3] + 2000, match[2] - 1, +match[1]);
1221
+ var year = +match[3],
1222
+ d = new Date();
1223
+
1224
+ if (year > (d.getFullYear() - 2000)) {
1225
+ year += 1900;
1226
+ } else {
1227
+ year += 2000;
1228
+ }
1229
+
1230
+ return Date.UTC(year, match[2] - 1, +match[1]);
525
1231
  },
526
1232
  alternative: 'mm/dd/YY' // different format with the same regex
527
1233
  },
@@ -563,12 +1269,20 @@
563
1269
  // Next time, use the one previously found
564
1270
  } else {
565
1271
  format = this.dateFormats[dateFormat];
1272
+
1273
+
1274
+ if (!format) {
1275
+ // The selected format is invalid
1276
+ format = this.dateFormats['YYYY-mm-dd'];
1277
+ }
1278
+
566
1279
  match = val.match(format.regex);
567
1280
  if (match) {
568
1281
  ret = format.parser(match);
569
1282
  }
1283
+
570
1284
  }
571
- // Fall back to Date.parse
1285
+ // Fall back to Date.parse
572
1286
  if (!match) {
573
1287
  match = Date.parse(val);
574
1288
  // External tools like Date.js and MooTools extend Date object and
@@ -652,7 +1366,7 @@
652
1366
  },
653
1367
 
654
1368
  /**
655
- * If a complete callback function is provided in the options, interpret the
1369
+ * If a complete callback function is provided in the options, interpret the
656
1370
  * columns into a Highcharts options object.
657
1371
  */
658
1372
  complete: function() {
@@ -790,6 +1504,19 @@
790
1504
  options.afterComplete(chartOptions);
791
1505
  }
792
1506
  }
1507
+
1508
+ },
1509
+
1510
+ update: function(options, redraw) {
1511
+ var chart = this.chart;
1512
+ if (options) {
1513
+ // Set the complete handler
1514
+ options.afterComplete = function(dataOptions) {
1515
+ chart.update(dataOptions, redraw);
1516
+ };
1517
+ // Apply it
1518
+ Highcharts.data(options);
1519
+ }
793
1520
  }
794
1521
  });
795
1522
 
@@ -805,7 +1532,7 @@
805
1532
  var chart = this;
806
1533
 
807
1534
  if (userOptions && userOptions.data) {
808
- Highcharts.data(Highcharts.extend(userOptions.data, {
1535
+ chart.data = new Data(Highcharts.extend(userOptions.data, {
809
1536
 
810
1537
  afterComplete: function(dataOptions) {
811
1538
  var i, series;
@@ -829,6 +1556,7 @@
829
1556
  proceed.call(chart, userOptions, callback);
830
1557
  }
831
1558
  }), userOptions);
1559
+ chart.data.chart = chart;
832
1560
  } else {
833
1561
  proceed.call(chart, userOptions, callback);
834
1562
  }
@@ -840,7 +1568,7 @@
840
1568
  * Ex: A series builder can be constructed to read column 3 as 'x' and
841
1569
  * column 7 and 8 as 'y1' and 'y2'.
842
1570
  * The output would then be points/rows of the form {x: 11, y1: 22, y2: 33}
843
- *
1571
+ *
844
1572
  * The name of the builder is taken from the second column. In the above
845
1573
  * example it would be the column with index 7.
846
1574
  * @constructor