pghero 3.1.0 → 3.2.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.
@@ -1,8 +1,7 @@
1
1
  /*!
2
- * Chartkick.js
2
+ * Chartkick.js v5.0.1
3
3
  * Create beautiful charts with one line of JavaScript
4
4
  * https://github.com/ankane/chartkick.js
5
- * v4.0.2
6
5
  * MIT License
7
6
  */
8
7
 
@@ -10,7 +9,7 @@
10
9
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
11
10
  typeof define === 'function' && define.amd ? define(factory) :
12
11
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Chartkick = factory());
13
- }(this, (function () { 'use strict';
12
+ })(this, (function () { 'use strict';
14
13
 
15
14
  function isArray(variable) {
16
15
  return Object.prototype.toString.call(variable) === "[object Array]";
@@ -27,8 +26,7 @@
27
26
 
28
27
  // https://github.com/madrobby/zepto/blob/master/src/zepto.js
29
28
  function extend(target, source) {
30
- var key;
31
- for (key in source) {
29
+ for (var key in source) {
32
30
  // protect against prototype pollution, defense 1
33
31
  if (key === "__proto__") { continue; }
34
32
 
@@ -53,13 +51,12 @@
53
51
  return target;
54
52
  }
55
53
 
56
- var DATE_PATTERN = /^(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)$/i;
54
+ var DATE_PATTERN = /^(\d\d\d\d)(?:-)?(\d\d)(?:-)?(\d\d)$/i;
57
55
 
58
56
  function negativeValues(series) {
59
- var i, j, data;
60
- for (i = 0; i < series.length; i++) {
61
- data = series[i].data;
62
- for (j = 0; j < data.length; j++) {
57
+ for (var i = 0; i < series.length; i++) {
58
+ var data = series[i].data;
59
+ for (var j = 0; j < data.length; j++) {
63
60
  if (data[j][1] < 0) {
64
61
  return true;
65
62
  }
@@ -68,49 +65,49 @@
68
65
  return false;
69
66
  }
70
67
 
71
- function toStr(n) {
72
- return "" + n;
68
+ function toStr(obj) {
69
+ return "" + obj;
73
70
  }
74
71
 
75
- function toFloat(n) {
76
- return parseFloat(n);
72
+ function toFloat(obj) {
73
+ return parseFloat(obj);
77
74
  }
78
75
 
79
- function toDate(n) {
80
- var matches, year, month, day;
81
- if (typeof n !== "object") {
82
- if (typeof n === "number") {
83
- n = new Date(n * 1000); // ms
76
+ function toDate(obj) {
77
+ if (obj instanceof Date) {
78
+ return obj;
79
+ } else if (typeof obj === "number") {
80
+ return new Date(obj * 1000); // ms
81
+ } else {
82
+ var s = toStr(obj);
83
+ var matches = s.match(DATE_PATTERN);
84
+ if (matches) {
85
+ var year = parseInt(matches[1], 10);
86
+ var month = parseInt(matches[2], 10) - 1;
87
+ var day = parseInt(matches[3], 10);
88
+ return new Date(year, month, day);
84
89
  } else {
85
- n = toStr(n);
86
- if ((matches = n.match(DATE_PATTERN))) {
87
- year = parseInt(matches[1], 10);
88
- month = parseInt(matches[3], 10) - 1;
89
- day = parseInt(matches[5], 10);
90
- return new Date(year, month, day);
91
- } else {
92
- // try our best to get the str into iso8601
93
- // TODO be smarter about this
94
- var str = n.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
95
- // Date.parse returns milliseconds if valid and NaN if invalid
96
- n = new Date(Date.parse(str) || n);
97
- }
90
+ // try our best to get the str into iso8601
91
+ // TODO be smarter about this
92
+ var str = s.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
93
+ // Date.parse returns milliseconds if valid and NaN if invalid
94
+ return new Date(Date.parse(str) || s);
98
95
  }
99
96
  }
100
- return n;
101
97
  }
102
98
 
103
- function toArr(n) {
104
- if (!isArray(n)) {
105
- var arr = [], i;
106
- for (i in n) {
107
- if (n.hasOwnProperty(i)) {
108
- arr.push([i, n[i]]);
99
+ function toArr(obj) {
100
+ if (isArray(obj)) {
101
+ return obj;
102
+ } else {
103
+ var arr = [];
104
+ for (var i in obj) {
105
+ if (Object.prototype.hasOwnProperty.call(obj, i)) {
106
+ arr.push([i, obj[i]]);
109
107
  }
110
108
  }
111
- n = arr;
109
+ return arr;
112
110
  }
113
- return n;
114
111
  }
115
112
 
116
113
  function jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle) {
@@ -170,32 +167,63 @@
170
167
  return a[0] - b[0];
171
168
  }
172
169
 
170
+ // needed since sort() without arguments does string comparison
173
171
  function sortByNumber(a, b) {
174
172
  return a - b;
175
173
  }
176
174
 
177
- function isMinute(d) {
178
- return d.getMilliseconds() === 0 && d.getSeconds() === 0;
175
+ function every(values, fn) {
176
+ for (var i = 0; i < values.length; i++) {
177
+ if (!fn(values[i])) {
178
+ return false;
179
+ }
180
+ }
181
+ return true;
179
182
  }
180
183
 
181
- function isHour(d) {
182
- return isMinute(d) && d.getMinutes() === 0;
184
+ function isDay(timeUnit) {
185
+ return timeUnit === "day" || timeUnit === "week" || timeUnit === "month" || timeUnit === "year";
183
186
  }
184
187
 
185
- function isDay(d) {
186
- return isHour(d) && d.getHours() === 0;
187
- }
188
+ function calculateTimeUnit(values, maxDay) {
189
+ if ( maxDay === void 0 ) maxDay = false;
188
190
 
189
- function isWeek(d, dayOfWeek) {
190
- return isDay(d) && d.getDay() === dayOfWeek;
191
- }
191
+ if (values.length === 0) {
192
+ return null;
193
+ }
192
194
 
193
- function isMonth(d) {
194
- return isDay(d) && d.getDate() === 1;
195
- }
195
+ var minute = every(values, function (d) { return d.getMilliseconds() === 0 && d.getSeconds() === 0; });
196
+ if (!minute) {
197
+ return null;
198
+ }
199
+
200
+ var hour = every(values, function (d) { return d.getMinutes() === 0; });
201
+ if (!hour) {
202
+ return "minute";
203
+ }
204
+
205
+ var day = every(values, function (d) { return d.getHours() === 0; });
206
+ if (!day) {
207
+ return "hour";
208
+ }
196
209
 
197
- function isYear(d) {
198
- return isMonth(d) && d.getMonth() === 0;
210
+ if (maxDay) {
211
+ return "day";
212
+ }
213
+
214
+ var month = every(values, function (d) { return d.getDate() === 1; });
215
+ if (!month) {
216
+ var dayOfWeek = values[0].getDay();
217
+ var week = every(values, function (d) { return d.getDay() === dayOfWeek; });
218
+ return (week ? "week" : "day");
219
+ }
220
+
221
+ var year = every(values, function (d) { return d.getMonth() === 0; });
222
+ if (!year) {
223
+ return "month";
224
+ }
225
+
226
+ return "year";
199
227
  }
200
228
 
201
229
  function isDate(obj) {
@@ -223,9 +251,14 @@
223
251
  var round = options.round;
224
252
 
225
253
  if (options.byteScale) {
226
- var suffixIdx;
254
+ var positive = value >= 0;
255
+ if (!positive) {
256
+ value *= -1;
257
+ }
258
+
227
259
  var baseValue = axis ? options.byteScale : value;
228
260
 
261
+ var suffixIdx;
229
262
  if (baseValue >= 1152921504606846976) {
230
263
  value /= 1152921504606846976;
231
264
  suffixIdx = 6;
@@ -259,6 +292,11 @@
259
292
  precision = value >= 1000 ? 4 : 3;
260
293
  }
261
294
  suffix = " " + byteSuffixes[suffixIdx];
295
+
296
+ // flip value back
297
+ if (!positive) {
298
+ value *= -1;
299
+ }
262
300
  }
263
301
 
264
302
  if (precision !== undefined && round !== undefined) {
@@ -310,19 +348,6 @@
310
348
  return null;
311
349
  }
312
350
 
313
- function allZeros(data) {
314
- var i, j, d;
315
- for (i = 0; i < data.length; i++) {
316
- d = data[i].data;
317
- for (j = 0; j < d.length; j++) {
318
- if (d[j][1] != 0) {
319
- return false;
320
- }
321
- }
322
- }
323
- return true;
324
- }
325
-
326
351
  var baseOptions = {
327
352
  maintainAspectRatio: false,
328
353
  animation: false,
@@ -379,7 +404,7 @@
379
404
  "#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#651067"
380
405
  ];
381
406
 
382
- var hideLegend$2 = function (options, legend, hideLegend) {
407
+ function hideLegend$2(options, legend, hideLegend) {
383
408
  if (legend !== undefined) {
384
409
  options.plugins.legend.display = !!legend;
385
410
  if (legend && legend !== true) {
@@ -388,61 +413,59 @@
388
413
  } else if (hideLegend) {
389
414
  options.plugins.legend.display = false;
390
415
  }
391
- };
416
+ }
392
417
 
393
- var setTitle$2 = function (options, title) {
418
+ function setTitle$2(options, title) {
394
419
  options.plugins.title.display = true;
395
420
  options.plugins.title.text = title;
396
- };
421
+ }
397
422
 
398
- var setMin$2 = function (options, min) {
423
+ function setMin$2(options, min) {
399
424
  if (min !== null) {
400
425
  options.scales.y.min = toFloat(min);
401
426
  }
402
- };
427
+ }
403
428
 
404
- var setMax$2 = function (options, max) {
429
+ function setMax$2(options, max) {
405
430
  options.scales.y.max = toFloat(max);
406
- };
431
+ }
407
432
 
408
- var setBarMin$1 = function (options, min) {
433
+ function setBarMin$1(options, min) {
409
434
  if (min !== null) {
410
435
  options.scales.x.min = toFloat(min);
411
436
  }
412
- };
437
+ }
413
438
 
414
- var setBarMax$1 = function (options, max) {
439
+ function setBarMax$1(options, max) {
415
440
  options.scales.x.max = toFloat(max);
416
- };
441
+ }
417
442
 
418
- var setStacked$2 = function (options, stacked) {
443
+ function setStacked$2(options, stacked) {
419
444
  options.scales.x.stacked = !!stacked;
420
445
  options.scales.y.stacked = !!stacked;
421
- };
446
+ }
422
447
 
423
- var setXtitle$2 = function (options, title) {
448
+ function setXtitle$2(options, title) {
424
449
  options.scales.x.title.display = true;
425
450
  options.scales.x.title.text = title;
426
- };
451
+ }
427
452
 
428
- var setYtitle$2 = function (options, title) {
453
+ function setYtitle$2(options, title) {
429
454
  options.scales.y.title.display = true;
430
455
  options.scales.y.title.text = title;
431
- };
456
+ }
432
457
 
433
458
  // https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
434
- var addOpacity = function (hex, opacity) {
459
+ function addOpacity(hex, opacity) {
435
460
  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
436
461
  return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
437
- };
462
+ }
438
463
 
439
- // check if not null or undefined
440
- // https://stackoverflow.com/a/27757708/1177228
441
- var notnull = function (x) {
442
- return x != null;
443
- };
464
+ function notnull(x) {
465
+ return x !== null && x !== undefined;
466
+ }
444
467
 
445
- var setLabelSize = function (chart, data, options) {
468
+ function setLabelSize(chart, data, options) {
446
469
  var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
447
470
  if (maxLabelSize > 25) {
448
471
  maxLabelSize = 25;
@@ -459,18 +482,33 @@
459
482
  }
460
483
  };
461
484
  }
462
- };
485
+ }
463
486
 
464
- var setFormatOptions$1 = function (chart, options, chartType) {
465
- var formatOptions = {
487
+ function calculateScale(series) {
488
+ var scale = 1;
489
+ var max = maxAbsY(series);
490
+ while (max >= 1024) {
491
+ scale *= 1024;
492
+ max /= 1024;
493
+ }
494
+ return scale;
495
+ }
496
+
497
+ function setFormatOptions$1(chart, options, chartType) {
498
+ // options to apply to x and r values for scatter and bubble
499
+ var numericOptions = {
500
+ thousands: chart.options.thousands,
501
+ decimal: chart.options.decimal
502
+ };
503
+
504
+ // options to apply to y value
505
+ var formatOptions = merge({
466
506
  prefix: chart.options.prefix,
467
507
  suffix: chart.options.suffix,
468
- thousands: chart.options.thousands,
469
- decimal: chart.options.decimal,
470
508
  precision: chart.options.precision,
471
509
  round: chart.options.round,
472
510
  zeros: chart.options.zeros
473
- };
511
+ }, numericOptions);
474
512
 
475
513
  if (chart.options.bytes) {
476
514
  var series = chart.data;
@@ -478,26 +516,8 @@
478
516
  series = [{data: series}];
479
517
  }
480
518
 
481
- // calculate max
482
- var max = 0;
483
- for (var i = 0; i < series.length; i++) {
484
- var s = series[i];
485
- for (var j = 0; j < s.data.length; j++) {
486
- if (s.data[j][1] > max) {
487
- max = s.data[j][1];
488
- }
489
- }
490
- }
491
-
492
- // calculate scale
493
- var scale = 1;
494
- while (max >= 1024) {
495
- scale *= 1024;
496
- max /= 1024;
497
- }
498
-
499
519
  // set step size
500
- formatOptions.byteScale = scale;
520
+ formatOptions.byteScale = calculateScale(series);
501
521
  }
502
522
 
503
523
  if (chartType !== "pie") {
@@ -520,6 +540,12 @@
520
540
  return formatValue("", value, formatOptions, true);
521
541
  };
522
542
  }
543
+
544
+ if ((chartType === "scatter" || chartType === "bubble") && !options.scales.x.ticks.callback) {
545
+ options.scales.x.ticks.callback = function (value) {
546
+ return formatValue("", value, numericOptions, true);
547
+ };
548
+ }
523
549
  }
524
550
 
525
551
  if (!options.plugins.tooltip.callbacks.label) {
@@ -529,7 +555,9 @@
529
555
  if (label) {
530
556
  label += ': ';
531
557
  }
532
- return label + '(' + context.label + ', ' + context.formattedValue + ')';
558
+
559
+ var dataPoint = context.parsed;
560
+ return label + '(' + formatValue('', dataPoint.x, numericOptions) + ', ' + formatValue('', dataPoint.y, formatOptions) + ')';
533
561
  };
534
562
  } else if (chartType === "bubble") {
535
563
  options.plugins.tooltip.callbacks.label = function (context) {
@@ -538,28 +566,21 @@
538
566
  label += ': ';
539
567
  }
540
568
  var dataPoint = context.raw;
541
- return label + '(' + dataPoint.x + ', ' + dataPoint.y + ', ' + dataPoint.v + ')';
569
+ return label + '(' + formatValue('', dataPoint.x, numericOptions) + ', ' + formatValue('', dataPoint.y, formatOptions) + ', ' + formatValue('', dataPoint.v, numericOptions) + ')';
542
570
  };
543
571
  } else if (chartType === "pie") {
544
572
  // need to use separate label for pie charts
545
573
  options.plugins.tooltip.callbacks.label = function (context) {
546
- var dataLabel = context.label;
547
- var value = ': ';
548
-
549
- if (isArray(dataLabel)) {
550
- // show value on first line of multiline label
551
- // need to clone because we are changing the value
552
- dataLabel = dataLabel.slice();
553
- dataLabel[0] += value;
554
- } else {
555
- dataLabel += value;
556
- }
557
-
558
- return formatValue(dataLabel, context.parsed, formatOptions);
574
+ return formatValue('', context.parsed, formatOptions);
559
575
  };
560
576
  } else {
561
577
  var valueLabel = chartType === "bar" ? "x" : "y";
562
578
  options.plugins.tooltip.callbacks.label = function (context) {
579
+ // don't show null values for stacked charts
580
+ if (context.parsed[valueLabel] === null) {
581
+ return;
582
+ }
583
+
563
584
  var label = context.dataset.label || '';
564
585
  if (label) {
565
586
  label += ': ';
@@ -568,124 +589,187 @@
568
589
  };
569
590
  }
570
591
  }
571
- };
572
-
573
- var jsOptions$2 = jsOptionsFunc(merge(baseOptions, defaultOptions$2), hideLegend$2, setTitle$2, setMin$2, setMax$2, setStacked$2, setXtitle$2, setYtitle$2);
574
-
575
- var createDataTable = function (chart, options, chartType) {
576
- var datasets = [];
577
- var labels = [];
578
592
 
579
- var colors = chart.options.colors || defaultColors;
593
+ // avoid formatting x-axis labels
594
+ // by default, Chart.js applies locale
595
+ if ((chartType === "line" || chartType === "area") && chart.xtype === "number") {
596
+ if (!options.scales.x.ticks.callback) {
597
+ options.scales.x.ticks.callback = function (value) {
598
+ return toStr(value);
599
+ };
600
+ }
580
601
 
581
- var day = true;
582
- var week = true;
583
- var dayOfWeek;
584
- var month = true;
585
- var year = true;
586
- var hour = true;
587
- var minute = true;
602
+ if (!options.plugins.tooltip.callbacks.title) {
603
+ options.plugins.tooltip.callbacks.title = function (context) {
604
+ return toStr(context[0].parsed.x);
605
+ };
606
+ }
607
+ }
608
+ }
588
609
 
589
- var series = chart.data;
610
+ function maxAbsY(series) {
611
+ var max = 0;
612
+ for (var i = 0; i < series.length; i++) {
613
+ var data = series[i].data;
614
+ for (var j = 0; j < data.length; j++) {
615
+ var v = Math.abs(data[j][1]);
616
+ if (v > max) {
617
+ max = v;
618
+ }
619
+ }
620
+ }
621
+ return max;
622
+ }
590
623
 
624
+ function maxR(series) {
625
+ // start at zero since radius must be positive
591
626
  var max = 0;
592
- if (chartType === "bubble") {
593
- for (var i$1 = 0; i$1 < series.length; i$1++) {
594
- var s$1 = series[i$1];
595
- for (var j$1 = 0; j$1 < s$1.data.length; j$1++) {
596
- if (s$1.data[j$1][2] > max) {
597
- max = s$1.data[j$1][2];
598
- }
627
+ for (var i = 0; i < series.length; i++) {
628
+ var data = series[i].data;
629
+ for (var j = 0; j < data.length; j++) {
630
+ var v = data[j][2];
631
+ if (v > max) {
632
+ max = v;
599
633
  }
600
634
  }
601
635
  }
636
+ return max;
637
+ }
602
638
 
603
- var i, j, s, d, key, rows = [], rows2 = [];
639
+ var jsOptions$2 = jsOptionsFunc(merge(baseOptions, defaultOptions$2), hideLegend$2, setTitle$2, setMin$2, setMax$2, setStacked$2, setXtitle$2, setYtitle$2);
604
640
 
605
- if (chartType === "bar" || chartType === "column" || (chart.xtype !== "number" && chart.xtype !== "bubble")) {
606
- var sortedLabels = [];
641
+ function prepareDefaultData(chart) {
642
+ var series = chart.data;
643
+ var rows = {};
644
+ var keys = [];
645
+ var labels = [];
646
+ var values = [];
607
647
 
608
- for (i = 0; i < series.length; i++) {
609
- s = series[i];
648
+ for (var i = 0; i < series.length; i++) {
649
+ var data = series[i].data;
610
650
 
611
- for (j = 0; j < s.data.length; j++) {
612
- d = s.data[j];
613
- key = chart.xtype == "datetime" ? d[0].getTime() : d[0];
614
- if (!rows[key]) {
615
- rows[key] = new Array(series.length);
616
- }
617
- rows[key][i] = toFloat(d[1]);
618
- if (sortedLabels.indexOf(key) === -1) {
619
- sortedLabels.push(key);
620
- }
651
+ for (var j = 0; j < data.length; j++) {
652
+ var d = data[j];
653
+ var key = chart.xtype === "datetime" ? d[0].getTime() : d[0];
654
+ if (!rows[key]) {
655
+ rows[key] = new Array(series.length);
656
+ keys.push(key);
621
657
  }
658
+ rows[key][i] = d[1];
622
659
  }
660
+ }
661
+
662
+ if (chart.xtype === "datetime" || chart.xtype === "number") {
663
+ keys.sort(sortByNumber);
664
+ }
665
+
666
+ for (var i$1 = 0; i$1 < series.length; i$1++) {
667
+ values.push([]);
668
+ }
669
+
670
+ for (var i$2 = 0; i$2 < keys.length; i$2++) {
671
+ var key$1 = keys[i$2];
623
672
 
624
- if (chart.xtype === "datetime" || chart.xtype === "number") {
625
- sortedLabels.sort(sortByNumber);
673
+ var label = chart.xtype === "datetime" ? new Date(key$1) : key$1;
674
+ labels.push(label);
675
+
676
+ var row = rows[key$1];
677
+ for (var j$1 = 0; j$1 < series.length; j$1++) {
678
+ var v = row[j$1];
679
+ // Chart.js doesn't like undefined
680
+ values[j$1].push(v === undefined ? null : v);
626
681
  }
682
+ }
683
+
684
+ return {
685
+ labels: labels,
686
+ values: values
687
+ };
688
+ }
627
689
 
628
- for (j = 0; j < series.length; j++) {
629
- rows2.push([]);
690
+ function prepareBubbleData(chart) {
691
+ var series = chart.data;
692
+ var values = [];
693
+ var max = maxR(series);
694
+
695
+ for (var i = 0; i < series.length; i++) {
696
+ var data = series[i].data;
697
+ var points = [];
698
+ for (var j = 0; j < data.length; j++) {
699
+ var v = data[j];
700
+ points.push({
701
+ x: v[0],
702
+ y: v[1],
703
+ r: v[2] * 20 / max,
704
+ // custom attribute, for tooltip
705
+ v: v[2]
706
+ });
630
707
  }
708
+ values.push(points);
709
+ }
631
710
 
632
- var value;
633
- var k;
634
- for (k = 0; k < sortedLabels.length; k++) {
635
- i = sortedLabels[k];
636
- if (chart.xtype === "datetime") {
637
- value = new Date(toFloat(i));
638
- // TODO make this efficient
639
- day = day && isDay(value);
640
- if (!dayOfWeek) {
641
- dayOfWeek = value.getDay();
642
- }
643
- week = week && isWeek(value, dayOfWeek);
644
- month = month && isMonth(value);
645
- year = year && isYear(value);
646
- hour = hour && isHour(value);
647
- minute = minute && isMinute(value);
648
- } else {
649
- value = i;
650
- }
651
- labels.push(value);
652
- for (j = 0; j < series.length; j++) {
653
- // Chart.js doesn't like undefined
654
- rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
655
- }
711
+ return {
712
+ labels: [],
713
+ values: values
714
+ };
715
+ }
716
+
717
+ // scatter or numeric line/area
718
+ function prepareNumberData(chart) {
719
+ var series = chart.data;
720
+ var values = [];
721
+
722
+ for (var i = 0; i < series.length; i++) {
723
+ var data = series[i].data;
724
+
725
+ data.sort(sortByNumberSeries);
726
+
727
+ var points = [];
728
+ for (var j = 0; j < data.length; j++) {
729
+ var v = data[j];
730
+ points.push({
731
+ x: v[0],
732
+ y: v[1]
733
+ });
656
734
  }
735
+ values.push(points);
736
+ }
737
+
738
+ return {
739
+ labels: [],
740
+ values: values
741
+ };
742
+ }
743
+
744
+ function prepareData(chart, chartType) {
745
+ if (chartType === "bubble") {
746
+ return prepareBubbleData(chart);
747
+ } else if (chart.xtype === "number" && chartType !== "bar" && chartType !== "column") {
748
+ return prepareNumberData(chart);
657
749
  } else {
658
- for (var i$2 = 0; i$2 < series.length; i$2++) {
659
- var s$2 = series[i$2];
660
- var d$1 = [];
661
- for (var j$2 = 0; j$2 < s$2.data.length; j$2++) {
662
- var point = {
663
- x: toFloat(s$2.data[j$2][0]),
664
- y: toFloat(s$2.data[j$2][1])
665
- };
666
- if (chartType === "bubble") {
667
- point.r = toFloat(s$2.data[j$2][2]) * 20 / max;
668
- // custom attribute, for tooltip
669
- point.v = s$2.data[j$2][2];
670
- }
671
- d$1.push(point);
672
- }
673
- rows2.push(d$1);
674
- }
750
+ return prepareDefaultData(chart);
675
751
  }
752
+ }
676
753
 
677
- var color;
678
- var backgroundColor;
754
+ function createDataTable(chart, options, chartType) {
755
+ var ref = prepareData(chart, chartType);
756
+ var labels = ref.labels;
757
+ var values = ref.values;
679
758
 
680
- for (i = 0; i < series.length; i++) {
681
- s = series[i];
759
+ var series = chart.data;
760
+ var datasets = [];
761
+ var colors = chart.options.colors || defaultColors;
762
+ for (var i = 0; i < series.length; i++) {
763
+ var s = series[i];
682
764
 
683
765
  // use colors for each bar for single series format
684
- if (chart.options.colors && chart.singleSeriesFormat && (chartType === "bar" || chartType === "column") && !s.color) {
766
+ var color = (void 0);
767
+ var backgroundColor = (void 0);
768
+ if (chart.options.colors && chart.singleSeriesFormat && (chartType === "bar" || chartType === "column") && !s.color && isArray(chart.options.colors) && !isArray(chart.options.colors[0])) {
685
769
  color = colors;
686
770
  backgroundColor = [];
687
- for (var j$3 = 0; j$3 < colors.length; j$3++) {
688
- backgroundColor[j$3] = addOpacity(color[j$3], 0.5);
771
+ for (var j = 0; j < colors.length; j++) {
772
+ backgroundColor[j] = addOpacity(color[j], 0.5);
689
773
  }
690
774
  } else {
691
775
  color = s.color || colors[i];
@@ -694,7 +778,7 @@
694
778
 
695
779
  var dataset = {
696
780
  label: s.name || "",
697
- data: rows2[i],
781
+ data: values[i],
698
782
  fill: chartType === "area",
699
783
  borderColor: color,
700
784
  backgroundColor: backgroundColor,
@@ -743,100 +827,104 @@
743
827
 
744
828
  if (chart.xtype === "datetime") {
745
829
  if (notnull(xmin)) {
746
- options.scales.x.ticks.min = toDate(xmin).getTime();
830
+ options.scales.x.min = toDate(xmin).getTime();
747
831
  }
748
832
  if (notnull(xmax)) {
749
- options.scales.x.ticks.max = toDate(xmax).getTime();
833
+ options.scales.x.max = toDate(xmax).getTime();
750
834
  }
751
835
  } else if (chart.xtype === "number") {
752
836
  if (notnull(xmin)) {
753
- options.scales.x.ticks.min = xmin;
754
- }
755
- if (notnull(xmax)) {
756
- options.scales.x.ticks.max = xmax;
757
- }
758
- }
759
-
760
- // for empty datetime chart
761
- if (chart.xtype === "datetime" && labels.length === 0) {
762
- if (notnull(xmin)) {
763
- labels.push(toDate(xmin));
837
+ options.scales.x.min = xmin;
764
838
  }
765
839
  if (notnull(xmax)) {
766
- labels.push(toDate(xmax));
840
+ options.scales.x.max = xmax;
767
841
  }
768
- day = false;
769
- week = false;
770
- month = false;
771
- year = false;
772
- hour = false;
773
- minute = false;
774
842
  }
775
843
 
776
- if (chart.xtype === "datetime" && labels.length > 0) {
777
- var minTime = (notnull(xmin) ? toDate(xmin) : labels[0]).getTime();
778
- var maxTime = (notnull(xmax) ? toDate(xmax) : labels[0]).getTime();
844
+ if (chart.xtype === "datetime") {
845
+ var timeUnit = calculateTimeUnit(labels);
779
846
 
780
- for (i = 1; i < labels.length; i++) {
781
- var value$1 = labels[i].getTime();
782
- if (value$1 < minTime) {
783
- minTime = value$1;
847
+ // for empty datetime chart
848
+ if (labels.length === 0) {
849
+ if (notnull(xmin)) {
850
+ labels.push(toDate(xmin));
784
851
  }
785
- if (value$1 > maxTime) {
786
- maxTime = value$1;
852
+ if (notnull(xmax)) {
853
+ labels.push(toDate(xmax));
787
854
  }
788
855
  }
789
856
 
790
- var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
791
-
792
- if (!options.scales.x.time.unit) {
793
- var step;
794
- if (year || timeDiff > 365 * 10) {
795
- options.scales.x.time.unit = "year";
796
- step = 365;
797
- } else if (month || timeDiff > 30 * 10) {
798
- options.scales.x.time.unit = "month";
799
- step = 30;
800
- } else if (day || timeDiff > 10) {
801
- options.scales.x.time.unit = "day";
802
- step = 1;
803
- } else if (hour || timeDiff > 0.5) {
804
- options.scales.x.time.displayFormats = {hour: "MMM d, h a"};
805
- options.scales.x.time.unit = "hour";
806
- step = 1 / 24.0;
807
- } else if (minute) {
808
- options.scales.x.time.displayFormats = {minute: "h:mm a"};
809
- options.scales.x.time.unit = "minute";
810
- step = 1 / 24.0 / 60.0;
857
+ if (labels.length > 0) {
858
+ var minTime = (notnull(xmin) ? toDate(xmin) : labels[0]).getTime();
859
+ var maxTime = (notnull(xmax) ? toDate(xmax) : labels[0]).getTime();
860
+
861
+ for (var i$1 = 1; i$1 < labels.length; i$1++) {
862
+ var value = labels[i$1].getTime();
863
+ if (value < minTime) {
864
+ minTime = value;
865
+ }
866
+ if (value > maxTime) {
867
+ maxTime = value;
868
+ }
811
869
  }
812
870
 
813
- if (step && timeDiff > 0) {
814
- var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
815
- if (week && step === 1) {
816
- unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
871
+ var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
872
+
873
+ if (!options.scales.x.time.unit) {
874
+ var step;
875
+ if (timeUnit === "year" || timeDiff > 365 * 10) {
876
+ options.scales.x.time.unit = "year";
877
+ step = 365;
878
+ } else if (timeUnit === "month" || timeDiff > 30 * 10) {
879
+ options.scales.x.time.unit = "month";
880
+ step = 30;
881
+ } else if (timeUnit === "week" || timeUnit === "day" || timeDiff > 10) {
882
+ options.scales.x.time.unit = "day";
883
+ step = 1;
884
+ } else if (timeUnit === "hour" || timeDiff > 0.5) {
885
+ options.scales.x.time.displayFormats = {hour: "MMM d, h a"};
886
+ options.scales.x.time.unit = "hour";
887
+ step = 1 / 24.0;
888
+ } else if (timeUnit === "minute") {
889
+ options.scales.x.time.displayFormats = {minute: "h:mm a"};
890
+ options.scales.x.time.unit = "minute";
891
+ step = 1 / 24.0 / 60.0;
892
+ }
893
+
894
+ if (step && timeDiff > 0) {
895
+ // width not available for hidden elements
896
+ var width = chart.element.offsetWidth;
897
+ if (width > 0) {
898
+ var unitStepSize = Math.ceil(timeDiff / step / (width / 100.0));
899
+ if (timeUnit === "week" && step === 1) {
900
+ unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
901
+ }
902
+ options.scales.x.ticks.stepSize = unitStepSize;
903
+ }
817
904
  }
818
- options.scales.x.time.stepSize = unitStepSize;
819
905
  }
820
- }
821
906
 
822
- if (!options.scales.x.time.tooltipFormat) {
823
- if (day) {
824
- options.scales.x.time.tooltipFormat = "PP";
825
- } else if (hour) {
826
- options.scales.x.time.tooltipFormat = "MMM d, h a";
827
- } else if (minute) {
828
- options.scales.x.time.tooltipFormat = "h:mm a";
907
+ if (!options.scales.x.time.tooltipFormat) {
908
+ if (timeUnit === "year") {
909
+ options.scales.x.time.tooltipFormat = "yyyy";
910
+ } else if (timeUnit === "month") {
911
+ options.scales.x.time.tooltipFormat = "MMM yyyy";
912
+ } else if (timeUnit === "week" || timeUnit === "day") {
913
+ options.scales.x.time.tooltipFormat = "PP";
914
+ } else if (timeUnit === "hour") {
915
+ options.scales.x.time.tooltipFormat = "MMM d, h a";
916
+ } else if (timeUnit === "minute") {
917
+ options.scales.x.time.tooltipFormat = "h:mm a";
918
+ }
829
919
  }
830
920
  }
831
921
  }
832
922
 
833
- var data = {
923
+ return {
834
924
  labels: labels,
835
925
  datasets: datasets
836
926
  };
837
-
838
- return data;
839
- };
927
+ }
840
928
 
841
929
  var defaultExport$2 = function defaultExport(library) {
842
930
  this.name = "chartjs";
@@ -844,20 +932,20 @@
844
932
  };
845
933
 
846
934
  defaultExport$2.prototype.renderLineChart = function renderLineChart (chart, chartType) {
847
- var chartOptions = {};
848
- // fix for https://github.com/chartjs/Chart.js/issues/2441
849
- if (!chart.options.max && allZeros(chart.data)) {
850
- chartOptions.max = 1;
935
+ if (!chartType) {
936
+ chartType = "line";
851
937
  }
852
938
 
939
+ var chartOptions = {};
940
+
853
941
  var options = jsOptions$2(chart, merge(chartOptions, chart.options));
854
942
  setFormatOptions$1(chart, options, chartType);
855
943
 
856
- var data = createDataTable(chart, options, chartType || "line");
944
+ var data = createDataTable(chart, options, chartType);
857
945
 
858
946
  if (chart.xtype === "number") {
859
- options.scales.x.type = "linear";
860
- options.scales.x.position = "bottom";
947
+ options.scales.x.type = options.scales.x.type || "linear";
948
+ options.scales.x.position = options.scales.x.position || "bottom";
861
949
  } else {
862
950
  options.scales.x.type = chart.xtype === "string" ? "category" : "time";
863
951
  }
@@ -924,6 +1012,9 @@
924
1012
  if (chartType !== "bar") {
925
1013
  setLabelSize(chart, data, options);
926
1014
  }
1015
+ if (!("mode" in options.interaction)) {
1016
+ options.interaction.mode = "index";
1017
+ }
927
1018
  this.drawChart(chart, "bar", data, options);
928
1019
  };
929
1020
 
@@ -947,8 +1038,8 @@
947
1038
 
948
1039
  var data = createDataTable(chart, options, chartType);
949
1040
 
950
- options.scales.x.type = "linear";
951
- options.scales.x.position = "bottom";
1041
+ options.scales.x.type = options.scales.x.type || "linear";
1042
+ options.scales.x.position = options.scales.x.position || "bottom";
952
1043
 
953
1044
  // prevent grouping hover and tooltips
954
1045
  if (!("mode" in options.interaction)) {
@@ -1035,7 +1126,7 @@
1035
1126
  }
1036
1127
  };
1037
1128
 
1038
- var hideLegend$1 = function (options, legend, hideLegend) {
1129
+ function hideLegend$1(options, legend, hideLegend) {
1039
1130
  if (legend !== undefined) {
1040
1131
  options.legend.enabled = !!legend;
1041
1132
  if (legend && legend !== true) {
@@ -1050,38 +1141,38 @@
1050
1141
  } else if (hideLegend) {
1051
1142
  options.legend.enabled = false;
1052
1143
  }
1053
- };
1144
+ }
1054
1145
 
1055
- var setTitle$1 = function (options, title) {
1146
+ function setTitle$1(options, title) {
1056
1147
  options.title.text = title;
1057
- };
1148
+ }
1058
1149
 
1059
- var setMin$1 = function (options, min) {
1150
+ function setMin$1(options, min) {
1060
1151
  options.yAxis.min = min;
1061
- };
1152
+ }
1062
1153
 
1063
- var setMax$1 = function (options, max) {
1154
+ function setMax$1(options, max) {
1064
1155
  options.yAxis.max = max;
1065
- };
1156
+ }
1066
1157
 
1067
- var setStacked$1 = function (options, stacked) {
1158
+ function setStacked$1(options, stacked) {
1068
1159
  var stackedValue = stacked ? (stacked === true ? "normal" : stacked) : null;
1069
1160
  options.plotOptions.series.stacking = stackedValue;
1070
1161
  options.plotOptions.area.stacking = stackedValue;
1071
1162
  options.plotOptions.areaspline.stacking = stackedValue;
1072
- };
1163
+ }
1073
1164
 
1074
- var setXtitle$1 = function (options, title) {
1165
+ function setXtitle$1(options, title) {
1075
1166
  options.xAxis.title.text = title;
1076
- };
1167
+ }
1077
1168
 
1078
- var setYtitle$1 = function (options, title) {
1169
+ function setYtitle$1(options, title) {
1079
1170
  options.yAxis.title.text = title;
1080
- };
1171
+ }
1081
1172
 
1082
1173
  var jsOptions$1 = jsOptionsFunc(defaultOptions$1, hideLegend$1, setTitle$1, setMin$1, setMax$1, setStacked$1, setXtitle$1, setYtitle$1);
1083
1174
 
1084
- var setFormatOptions = function(chart, options, chartType) {
1175
+ function setFormatOptions(chart, options, chartType) {
1085
1176
  var formatOptions = {
1086
1177
  prefix: chart.options.prefix,
1087
1178
  suffix: chart.options.suffix,
@@ -1092,18 +1183,19 @@
1092
1183
  zeros: chart.options.zeros
1093
1184
  };
1094
1185
 
1095
- if (chartType !== "pie" && !options.yAxis.labels.formatter) {
1186
+ // skip when axis is an array (like with min/max)
1187
+ if (chartType !== "pie" && !isArray(options.yAxis) && !options.yAxis.labels.formatter) {
1096
1188
  options.yAxis.labels.formatter = function () {
1097
1189
  return formatValue("", this.value, formatOptions);
1098
1190
  };
1099
1191
  }
1100
1192
 
1101
- if (!options.tooltip.pointFormatter) {
1193
+ if (!options.tooltip.pointFormatter && !options.tooltip.pointFormat) {
1102
1194
  options.tooltip.pointFormatter = function () {
1103
1195
  return '<span style="color:' + this.color + '">\u25CF</span> ' + formatValue(this.series.name + ': <b>', this.y, formatOptions) + '</b><br/>';
1104
1196
  };
1105
1197
  }
1106
- };
1198
+ }
1107
1199
 
1108
1200
  var defaultExport$1 = function defaultExport(library) {
1109
1201
  this.name = "highcharts";
@@ -1139,21 +1231,27 @@
1139
1231
  }
1140
1232
  }
1141
1233
 
1142
- var options = jsOptions$1(chart, chart.options, chartOptions), data, i, j;
1143
- options.xAxis.type = chart.xtype === "string" ? "category" : (chart.xtype === "number" ? "linear" : "datetime");
1234
+ var options = jsOptions$1(chart, chart.options, chartOptions);
1235
+ if (chart.xtype === "number") {
1236
+ options.xAxis.type = options.xAxis.type || "linear";
1237
+ } else {
1238
+ options.xAxis.type = chart.xtype === "string" ? "category" : "datetime";
1239
+ }
1144
1240
  if (!options.chart.type) {
1145
1241
  options.chart.type = chartType;
1146
1242
  }
1147
1243
  setFormatOptions(chart, options, chartType);
1148
1244
 
1149
1245
  var series = chart.data;
1150
- for (i = 0; i < series.length; i++) {
1246
+ for (var i = 0; i < series.length; i++) {
1151
1247
  series[i].name = series[i].name || "Value";
1152
- data = series[i].data;
1248
+ var data = series[i].data;
1153
1249
  if (chart.xtype === "datetime") {
1154
- for (j = 0; j < data.length; j++) {
1250
+ for (var j = 0; j < data.length; j++) {
1155
1251
  data[j][0] = data[j][0].getTime();
1156
1252
  }
1253
+ } else if (chart.xtype === "number") {
1254
+ data.sort(sortByNumberSeries);
1157
1255
  }
1158
1256
  series[i].marker = {symbol: "circle"};
1159
1257
  if (chart.options.points === false) {
@@ -1202,15 +1300,17 @@
1202
1300
  defaultExport$1.prototype.renderColumnChart = function renderColumnChart (chart, chartType) {
1203
1301
  chartType = chartType || "column";
1204
1302
  var series = chart.data;
1205
- var options = jsOptions$1(chart, chart.options), i, j, s, d, rows = [], categories = [];
1303
+ var options = jsOptions$1(chart, chart.options);
1304
+ var rows = [];
1305
+ var categories = [];
1206
1306
  options.chart.type = chartType;
1207
1307
  setFormatOptions(chart, options, chartType);
1208
1308
 
1209
- for (i = 0; i < series.length; i++) {
1210
- s = series[i];
1309
+ for (var i = 0; i < series.length; i++) {
1310
+ var s = series[i];
1211
1311
 
1212
- for (j = 0; j < s.data.length; j++) {
1213
- d = s.data[j];
1312
+ for (var j = 0; j < s.data.length; j++) {
1313
+ var d = s.data[j];
1214
1314
  if (!rows[d[0]]) {
1215
1315
  rows[d[0]] = new Array(series.length);
1216
1316
  categories.push(d[0]);
@@ -1225,19 +1325,19 @@
1225
1325
 
1226
1326
  options.xAxis.categories = categories;
1227
1327
 
1228
- var newSeries = [], d2;
1229
- for (i = 0; i < series.length; i++) {
1230
- d = [];
1231
- for (j = 0; j < categories.length; j++) {
1232
- d.push(rows[categories[j]][i] || 0);
1328
+ var newSeries = [];
1329
+ for (var i$1 = 0; i$1 < series.length; i$1++) {
1330
+ var d$1 = [];
1331
+ for (var j$1 = 0; j$1 < categories.length; j$1++) {
1332
+ d$1.push(rows[categories[j$1]][i$1] || 0);
1233
1333
  }
1234
1334
 
1235
- d2 = {
1236
- name: series[i].name || "Value",
1237
- data: d
1335
+ var d2 = {
1336
+ name: series[i$1].name || "Value",
1337
+ data: d$1
1238
1338
  };
1239
- if (series[i].stack) {
1240
- d2.stack = series[i].stack;
1339
+ if (series[i$1].stack) {
1340
+ d2.stack = series[i$1].stack;
1241
1341
  }
1242
1342
 
1243
1343
  newSeries.push(d2);
@@ -1320,7 +1420,7 @@
1320
1420
  }
1321
1421
  };
1322
1422
 
1323
- var hideLegend = function (options, legend, hideLegend) {
1423
+ function hideLegend(options, legend, hideLegend) {
1324
1424
  if (legend !== undefined) {
1325
1425
  var position;
1326
1426
  if (!legend) {
@@ -1334,53 +1434,53 @@
1334
1434
  } else if (hideLegend) {
1335
1435
  options.legend.position = "none";
1336
1436
  }
1337
- };
1437
+ }
1338
1438
 
1339
- var setTitle = function (options, title) {
1439
+ function setTitle(options, title) {
1340
1440
  options.title = title;
1341
1441
  options.titleTextStyle = {color: "#333", fontSize: "20px"};
1342
- };
1442
+ }
1343
1443
 
1344
- var setMin = function (options, min) {
1444
+ function setMin(options, min) {
1345
1445
  options.vAxis.viewWindow.min = min;
1346
- };
1446
+ }
1347
1447
 
1348
- var setMax = function (options, max) {
1448
+ function setMax(options, max) {
1349
1449
  options.vAxis.viewWindow.max = max;
1350
- };
1450
+ }
1351
1451
 
1352
- var setBarMin = function (options, min) {
1452
+ function setBarMin(options, min) {
1353
1453
  options.hAxis.viewWindow.min = min;
1354
- };
1454
+ }
1355
1455
 
1356
- var setBarMax = function (options, max) {
1456
+ function setBarMax(options, max) {
1357
1457
  options.hAxis.viewWindow.max = max;
1358
- };
1458
+ }
1359
1459
 
1360
- var setStacked = function (options, stacked) {
1361
- options.isStacked = stacked ? stacked : false;
1362
- };
1460
+ function setStacked(options, stacked) {
1461
+ options.isStacked = stacked || false;
1462
+ }
1363
1463
 
1364
- var setXtitle = function (options, title) {
1464
+ function setXtitle(options, title) {
1365
1465
  options.hAxis.title = title;
1366
1466
  options.hAxis.titleTextStyle.italic = false;
1367
- };
1467
+ }
1368
1468
 
1369
- var setYtitle = function (options, title) {
1469
+ function setYtitle(options, title) {
1370
1470
  options.vAxis.title = title;
1371
1471
  options.vAxis.titleTextStyle.italic = false;
1372
- };
1472
+ }
1373
1473
 
1374
1474
  var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
1375
1475
 
1376
- var resize = function (callback) {
1476
+ function resize(callback) {
1377
1477
  if (window.attachEvent) {
1378
1478
  window.attachEvent("onresize", callback);
1379
1479
  } else if (window.addEventListener) {
1380
1480
  window.addEventListener("resize", callback, true);
1381
1481
  }
1382
1482
  callback();
1383
- };
1483
+ }
1384
1484
 
1385
1485
  var defaultExport = function defaultExport(library) {
1386
1486
  this.name = "google";
@@ -1388,7 +1488,7 @@
1388
1488
  };
1389
1489
 
1390
1490
  defaultExport.prototype.renderLineChart = function renderLineChart (chart) {
1391
- var this$1 = this;
1491
+ var this$1$1 = this;
1392
1492
 
1393
1493
  this.waitForLoaded(chart, function () {
1394
1494
  var chartOptions = {};
@@ -1402,14 +1502,14 @@
1402
1502
  }
1403
1503
 
1404
1504
  var options = jsOptions(chart, chart.options, chartOptions);
1405
- var data = this$1.createDataTable(chart.data, chart.xtype);
1505
+ var data = this$1$1.createDataTable(chart.data, chart.xtype);
1406
1506
 
1407
- this$1.drawChart(chart, "LineChart", data, options);
1507
+ this$1$1.drawChart(chart, "LineChart", data, options);
1408
1508
  });
1409
1509
  };
1410
1510
 
1411
1511
  defaultExport.prototype.renderPieChart = function renderPieChart (chart) {
1412
- var this$1 = this;
1512
+ var this$1$1 = this;
1413
1513
 
1414
1514
  this.waitForLoaded(chart, function () {
1415
1515
  var chartOptions = {
@@ -1433,28 +1533,28 @@
1433
1533
  }
1434
1534
  var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
1435
1535
 
1436
- var data = new this$1.library.visualization.DataTable();
1536
+ var data = new this$1$1.library.visualization.DataTable();
1437
1537
  data.addColumn("string", "");
1438
1538
  data.addColumn("number", "Value");
1439
1539
  data.addRows(chart.data);
1440
1540
 
1441
- this$1.drawChart(chart, "PieChart", data, options);
1541
+ this$1$1.drawChart(chart, "PieChart", data, options);
1442
1542
  });
1443
1543
  };
1444
1544
 
1445
1545
  defaultExport.prototype.renderColumnChart = function renderColumnChart (chart) {
1446
- var this$1 = this;
1546
+ var this$1$1 = this;
1447
1547
 
1448
1548
  this.waitForLoaded(chart, function () {
1449
1549
  var options = jsOptions(chart, chart.options);
1450
- var data = this$1.createDataTable(chart.data, chart.xtype);
1550
+ var data = this$1$1.createDataTable(chart.data, chart.xtype);
1451
1551
 
1452
- this$1.drawChart(chart, "ColumnChart", data, options);
1552
+ this$1$1.drawChart(chart, "ColumnChart", data, options);
1453
1553
  });
1454
1554
  };
1455
1555
 
1456
1556
  defaultExport.prototype.renderBarChart = function renderBarChart (chart) {
1457
- var this$1 = this;
1557
+ var this$1$1 = this;
1458
1558
 
1459
1559
  this.waitForLoaded(chart, function () {
1460
1560
  var chartOptions = {
@@ -1465,14 +1565,14 @@
1465
1565
  }
1466
1566
  };
1467
1567
  var options = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options, chartOptions);
1468
- var data = this$1.createDataTable(chart.data, chart.xtype);
1568
+ var data = this$1$1.createDataTable(chart.data, chart.xtype);
1469
1569
 
1470
- this$1.drawChart(chart, "BarChart", data, options);
1570
+ this$1$1.drawChart(chart, "BarChart", data, options);
1471
1571
  });
1472
1572
  };
1473
1573
 
1474
1574
  defaultExport.prototype.renderAreaChart = function renderAreaChart (chart) {
1475
- var this$1 = this;
1575
+ var this$1$1 = this;
1476
1576
 
1477
1577
  this.waitForLoaded(chart, function () {
1478
1578
  var chartOptions = {
@@ -1482,14 +1582,14 @@
1482
1582
  };
1483
1583
 
1484
1584
  var options = jsOptions(chart, chart.options, chartOptions);
1485
- var data = this$1.createDataTable(chart.data, chart.xtype);
1585
+ var data = this$1$1.createDataTable(chart.data, chart.xtype);
1486
1586
 
1487
- this$1.drawChart(chart, "AreaChart", data, options);
1587
+ this$1$1.drawChart(chart, "AreaChart", data, options);
1488
1588
  });
1489
1589
  };
1490
1590
 
1491
1591
  defaultExport.prototype.renderGeoChart = function renderGeoChart (chart) {
1492
- var this$1 = this;
1592
+ var this$1$1 = this;
1493
1593
 
1494
1594
  this.waitForLoaded(chart, "geochart", function () {
1495
1595
  var chartOptions = {
@@ -1500,27 +1600,28 @@
1500
1600
  };
1501
1601
  var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
1502
1602
 
1503
- var data = new this$1.library.visualization.DataTable();
1603
+ var data = new this$1$1.library.visualization.DataTable();
1504
1604
  data.addColumn("string", "");
1505
1605
  data.addColumn("number", chart.options.label || "Value");
1506
1606
  data.addRows(chart.data);
1507
1607
 
1508
- this$1.drawChart(chart, "GeoChart", data, options);
1608
+ this$1$1.drawChart(chart, "GeoChart", data, options);
1509
1609
  });
1510
1610
  };
1511
1611
 
1512
1612
  defaultExport.prototype.renderScatterChart = function renderScatterChart (chart) {
1513
- var this$1 = this;
1613
+ var this$1$1 = this;
1514
1614
 
1515
1615
  this.waitForLoaded(chart, function () {
1516
1616
  var chartOptions = {};
1517
1617
  var options = jsOptions(chart, chart.options, chartOptions);
1518
1618
 
1519
- var series = chart.data, rows2 = [], i, j, data, d;
1520
- for (i = 0; i < series.length; i++) {
1619
+ var series = chart.data;
1620
+ var rows2 = [];
1621
+ for (var i = 0; i < series.length; i++) {
1521
1622
  series[i].name = series[i].name || "Value";
1522
- d = series[i].data;
1523
- for (j = 0; j < d.length; j++) {
1623
+ var d = series[i].data;
1624
+ for (var j = 0; j < d.length; j++) {
1524
1625
  var row = new Array(series.length + 1);
1525
1626
  row[0] = d[j][0];
1526
1627
  row[i + 1] = d[j][1];
@@ -1528,19 +1629,19 @@
1528
1629
  }
1529
1630
  }
1530
1631
 
1531
- data = new this$1.library.visualization.DataTable();
1632
+ var data = new this$1$1.library.visualization.DataTable();
1532
1633
  data.addColumn("number", "");
1533
- for (i = 0; i < series.length; i++) {
1534
- data.addColumn("number", series[i].name);
1634
+ for (var i$1 = 0; i$1 < series.length; i$1++) {
1635
+ data.addColumn("number", series[i$1].name);
1535
1636
  }
1536
1637
  data.addRows(rows2);
1537
1638
 
1538
- this$1.drawChart(chart, "ScatterChart", data, options);
1639
+ this$1$1.drawChart(chart, "ScatterChart", data, options);
1539
1640
  });
1540
1641
  };
1541
1642
 
1542
1643
  defaultExport.prototype.renderTimeline = function renderTimeline (chart) {
1543
- var this$1 = this;
1644
+ var this$1$1 = this;
1544
1645
 
1545
1646
  this.waitForLoaded(chart, "timeline", function () {
1546
1647
  var chartOptions = {
@@ -1552,7 +1653,7 @@
1552
1653
  }
1553
1654
  var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
1554
1655
 
1555
- var data = new this$1.library.visualization.DataTable();
1656
+ var data = new this$1$1.library.visualization.DataTable();
1556
1657
  data.addColumn({type: "string", id: "Name"});
1557
1658
  data.addColumn({type: "date", id: "Start"});
1558
1659
  data.addColumn({type: "date", id: "End"});
@@ -1560,7 +1661,7 @@
1560
1661
 
1561
1662
  chart.element.style.lineHeight = "normal";
1562
1663
 
1563
- this$1.drawChart(chart, "Timeline", data, options);
1664
+ this$1$1.drawChart(chart, "Timeline", data, options);
1564
1665
  });
1565
1666
  };
1566
1667
 
@@ -1586,7 +1687,7 @@
1586
1687
  };
1587
1688
 
1588
1689
  defaultExport.prototype.waitForLoaded = function waitForLoaded (chart, pack, callback) {
1589
- var this$1 = this;
1690
+ var this$1$1 = this;
1590
1691
 
1591
1692
  if (!callback) {
1592
1693
  callback = pack;
@@ -1603,7 +1704,7 @@
1603
1704
  // https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
1604
1705
  var loadOptions = {
1605
1706
  packages: [pack],
1606
- callback: function () { this$1.runCallbacks(); }
1707
+ callback: function () { this$1$1.runCallbacks(); }
1607
1708
  };
1608
1709
  var config = chart.__config();
1609
1710
  if (config.language) {
@@ -1618,10 +1719,9 @@
1618
1719
  };
1619
1720
 
1620
1721
  defaultExport.prototype.runCallbacks = function runCallbacks () {
1621
- var cb, call;
1622
1722
  for (var i = 0; i < callbacks.length; i++) {
1623
- cb = callbacks[i];
1624
- call = this.library.visualization && ((cb.pack === "corechart" && this.library.visualization.LineChart) || (cb.pack === "timeline" && this.library.visualization.Timeline) || (cb.pack === "geochart" && this.library.visualization.GeoChart));
1723
+ var cb = callbacks[i];
1724
+ var call = this.library.visualization && ((cb.pack === "corechart" && this.library.visualization.LineChart) || (cb.pack === "timeline" && this.library.visualization.Timeline) || (cb.pack === "geochart" && this.library.visualization.GeoChart));
1625
1725
  if (call) {
1626
1726
  cb.callback();
1627
1727
  callbacks.splice(i, 1);
@@ -1632,44 +1732,48 @@
1632
1732
 
1633
1733
  // cant use object as key
1634
1734
  defaultExport.prototype.createDataTable = function createDataTable (series, columnType) {
1635
- var i, j, s, d, key, rows = [], sortedLabels = [];
1636
- for (i = 0; i < series.length; i++) {
1637
- s = series[i];
1735
+ var rows = [];
1736
+ var sortedLabels = [];
1737
+ for (var i = 0; i < series.length; i++) {
1738
+ var s = series[i];
1638
1739
  series[i].name = series[i].name || "Value";
1639
1740
 
1640
- for (j = 0; j < s.data.length; j++) {
1641
- d = s.data[j];
1642
- key = (columnType === "datetime") ? d[0].getTime() : d[0];
1741
+ for (var j = 0; j < s.data.length; j++) {
1742
+ var d = s.data[j];
1743
+ var key = columnType === "datetime" ? d[0].getTime() : d[0];
1643
1744
  if (!rows[key]) {
1644
1745
  rows[key] = new Array(series.length);
1645
1746
  sortedLabels.push(key);
1646
1747
  }
1647
- rows[key][i] = toFloat(d[1]);
1748
+ rows[key][i] = d[1];
1648
1749
  }
1649
1750
  }
1650
1751
 
1651
1752
  var rows2 = [];
1652
- var day = true;
1653
- var value;
1654
- for (j = 0; j < sortedLabels.length; j++) {
1655
- i = sortedLabels[j];
1753
+ var values = [];
1754
+ for (var j$1 = 0; j$1 < sortedLabels.length; j$1++) {
1755
+ var i$1 = sortedLabels[j$1];
1756
+ var value = (void 0);
1656
1757
  if (columnType === "datetime") {
1657
- value = new Date(toFloat(i));
1658
- day = day && isDay(value);
1659
- } else if (columnType === "number") {
1660
- value = toFloat(i);
1758
+ value = new Date(i$1);
1759
+ values.push(value);
1661
1760
  } else {
1662
- value = i;
1761
+ value = i$1;
1663
1762
  }
1664
- rows2.push([value].concat(rows[i]));
1763
+ rows2.push([value].concat(rows[i$1]));
1665
1764
  }
1765
+
1766
+ var day = true;
1666
1767
  if (columnType === "datetime") {
1667
1768
  rows2.sort(sortByTime);
1769
+
1770
+ var timeUnit = calculateTimeUnit(values, true);
1771
+ day = isDay(timeUnit);
1668
1772
  } else if (columnType === "number") {
1669
1773
  rows2.sort(sortByNumberSeries);
1670
1774
 
1671
- for (i = 0; i < rows2.length; i++) {
1672
- rows2[i][0] = toStr(rows2[i][0]);
1775
+ for (var i$2 = 0; i$2 < rows2.length; i$2++) {
1776
+ rows2[i$2][0] = toStr(rows2[i$2][0]);
1673
1777
  }
1674
1778
 
1675
1779
  columnType = "string";
@@ -1679,232 +1783,39 @@
1679
1783
  var data = new this.library.visualization.DataTable();
1680
1784
  columnType = columnType === "datetime" && day ? "date" : columnType;
1681
1785
  data.addColumn(columnType, "");
1682
- for (i = 0; i < series.length; i++) {
1683
- data.addColumn("number", series[i].name);
1786
+ for (var i$3 = 0; i$3 < series.length; i$3++) {
1787
+ data.addColumn("number", series[i$3].name);
1684
1788
  }
1685
1789
  data.addRows(rows2);
1686
1790
 
1687
1791
  return data;
1688
1792
  };
1689
1793
 
1690
- var pendingRequests = [], runningRequests = 0, maxRequests = 4;
1691
-
1692
- function pushRequest(url, success, error) {
1693
- pendingRequests.push([url, success, error]);
1694
- runNext();
1695
- }
1794
+ var adapters = [];
1696
1795
 
1697
- function runNext() {
1698
- if (runningRequests < maxRequests) {
1699
- var request = pendingRequests.shift();
1700
- if (request) {
1701
- runningRequests++;
1702
- getJSON(request[0], request[1], request[2]);
1703
- runNext();
1796
+ function getAdapterType(library) {
1797
+ if (library) {
1798
+ if (library.product === "Highcharts") {
1799
+ return defaultExport$1;
1800
+ } else if (library.charts) {
1801
+ return defaultExport;
1802
+ } else if (isFunction(library)) {
1803
+ return defaultExport$2;
1704
1804
  }
1705
1805
  }
1706
- }
1707
-
1708
- function requestComplete() {
1709
- runningRequests--;
1710
- runNext();
1711
- }
1712
-
1713
- function getJSON(url, success, error) {
1714
- ajaxCall(url, success, function (jqXHR, textStatus, errorThrown) {
1715
- var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
1716
- error(message);
1717
- });
1718
- }
1719
-
1720
- function ajaxCall(url, success, error) {
1721
- var $ = window.jQuery || window.Zepto || window.$;
1722
-
1723
- if ($ && $.ajax) {
1724
- $.ajax({
1725
- dataType: "json",
1726
- url: url,
1727
- success: success,
1728
- error: error,
1729
- complete: requestComplete
1730
- });
1731
- } else {
1732
- var xhr = new XMLHttpRequest();
1733
- xhr.open("GET", url, true);
1734
- xhr.setRequestHeader("Content-Type", "application/json");
1735
- xhr.onload = function () {
1736
- requestComplete();
1737
- if (xhr.status === 200) {
1738
- success(JSON.parse(xhr.responseText), xhr.statusText, xhr);
1739
- } else {
1740
- error(xhr, "error", xhr.statusText);
1741
- }
1742
- };
1743
- xhr.send();
1744
- }
1745
- }
1746
-
1747
- var config = {};
1748
- var adapters = [];
1749
-
1750
- // helpers
1751
-
1752
- function setText(element, text) {
1753
- if (document.body.innerText) {
1754
- element.innerText = text;
1755
- } else {
1756
- element.textContent = text;
1757
- }
1758
- }
1759
-
1760
- // TODO remove prefix for all messages
1761
- function chartError(element, message, noPrefix) {
1762
- if (!noPrefix) {
1763
- message = "Error Loading Chart: " + message;
1764
- }
1765
- setText(element, message);
1766
- element.style.color = "#ff0000";
1767
- }
1768
-
1769
- function errorCatcher(chart) {
1770
- try {
1771
- chart.__render();
1772
- } catch (err) {
1773
- chartError(chart.element, err.message);
1774
- throw err;
1775
- }
1776
- }
1777
-
1778
- function fetchDataSource(chart, dataSource, showLoading) {
1779
- // only show loading message for urls and callbacks
1780
- if (showLoading && chart.options.loading && (typeof dataSource === "string" || typeof dataSource === "function")) {
1781
- setText(chart.element, chart.options.loading);
1782
- }
1783
-
1784
- if (typeof dataSource === "string") {
1785
- pushRequest(dataSource, function (data) {
1786
- chart.rawData = data;
1787
- errorCatcher(chart);
1788
- }, function (message) {
1789
- chartError(chart.element, message);
1790
- });
1791
- } else if (typeof dataSource === "function") {
1792
- try {
1793
- dataSource(function (data) {
1794
- chart.rawData = data;
1795
- errorCatcher(chart);
1796
- }, function (message) {
1797
- chartError(chart.element, message, true);
1798
- });
1799
- } catch (err) {
1800
- chartError(chart.element, err, true);
1801
- }
1802
- } else {
1803
- chart.rawData = dataSource;
1804
- errorCatcher(chart);
1805
- }
1806
- }
1807
-
1808
- function addDownloadButton(chart) {
1809
- var element = chart.element;
1810
- var link = document.createElement("a");
1811
-
1812
- var download = chart.options.download;
1813
- if (download === true) {
1814
- download = {};
1815
- } else if (typeof download === "string") {
1816
- download = {filename: download};
1817
- }
1818
- link.download = download.filename || "chart.png"; // https://caniuse.com/download
1819
-
1820
- link.style.position = "absolute";
1821
- link.style.top = "20px";
1822
- link.style.right = "20px";
1823
- link.style.zIndex = 1000;
1824
- link.style.lineHeight = "20px";
1825
- link.target = "_blank"; // for safari
1826
- var image = document.createElement("img");
1827
- image.alt = "Download";
1828
- image.style.border = "none";
1829
- // icon from font-awesome
1830
- // http://fa2png.io/
1831
- image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAABCFBMVEUAAADMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMywEsqxAAAAV3RSTlMAAQIDBggJCgsMDQ4PERQaHB0eISIjJCouLzE0OTo/QUJHSUpLTU5PUllhYmltcHh5foWLjI+SlaCio6atr7S1t7m6vsHHyM7R2tze5Obo7fHz9ff5+/1hlxK2AAAA30lEQVQYGUXBhVYCQQBA0TdYWAt2d3d3YWAHyur7/z9xgD16Lw0DW+XKx+1GgX+FRzM3HWQWrHl5N/oapW5RPe0PkBu+UYeICvozTWZVK23Ao04B79oJrOsJDOoxkZoQPWgX29pHpCZEk7rEvQYiNSFq1UMqvlCjJkRBS1R8hb00Vb/TajtBL7nTHE1X1vyMQF732dQhyF2o6SAwrzP06iUQzvwsArlnzcOdrgBhJyHa1QOgO9U1GsKuvjUTjavliZYQ8nNPapG6sap/3nrIdJ6bOWzmX/fy0XVpfzZP3S8OJT3g9EEiJwAAAABJRU5ErkJggg==";
1832
- link.appendChild(image);
1833
- element.style.position = "relative";
1834
-
1835
- chart.__downloadAttached = true;
1836
-
1837
- // mouseenter
1838
- chart.__enterEvent = addEvent(element, "mouseover", function(e) {
1839
- var related = e.relatedTarget;
1840
- // check download option again to ensure it wasn't changed
1841
- if ((!related || (related !== this && !childOf(this, related))) && chart.options.download) {
1842
- link.href = chart.toImage(download);
1843
- element.appendChild(link);
1844
- }
1845
- });
1846
-
1847
- // mouseleave
1848
- chart.__leaveEvent = addEvent(element, "mouseout", function(e) {
1849
- var related = e.relatedTarget;
1850
- if (!related || (related !== this && !childOf(this, related))) {
1851
- if (link.parentNode) {
1852
- link.parentNode.removeChild(link);
1853
- }
1854
- }
1855
- });
1856
- }
1857
-
1858
- // https://stackoverflow.com/questions/10149963/adding-event-listener-cross-browser
1859
- function addEvent(elem, event, fn) {
1860
- if (elem.addEventListener) {
1861
- elem.addEventListener(event, fn, false);
1862
- return fn;
1863
- } else {
1864
- var fn2 = function() {
1865
- // set the this pointer same as addEventListener when fn is called
1866
- return(fn.call(elem, window.event));
1867
- };
1868
- elem.attachEvent("on" + event, fn2);
1869
- return fn2;
1870
- }
1871
- }
1872
-
1873
- function removeEvent(elem, event, fn) {
1874
- if (elem.removeEventListener) {
1875
- elem.removeEventListener(event, fn, false);
1876
- } else {
1877
- elem.detachEvent("on" + event, fn);
1878
- }
1879
- }
1880
-
1881
- // https://gist.github.com/shawnbot/4166283
1882
- function childOf(p, c) {
1883
- if (p === c) { return false; }
1884
- while (c && c !== p) { c = c.parentNode; }
1885
- return c === p;
1886
- }
1887
-
1888
- function getAdapterType(library) {
1889
- if (library) {
1890
- if (library.product === "Highcharts") {
1891
- return defaultExport$1;
1892
- } else if (library.charts) {
1893
- return defaultExport;
1894
- } else if (isFunction(library)) {
1895
- return defaultExport$2;
1896
- }
1897
- }
1898
- throw new Error("Unknown adapter");
1806
+ throw new Error("Unknown adapter");
1899
1807
  }
1900
1808
 
1901
1809
  function addAdapter(library) {
1902
1810
  var adapterType = getAdapterType(library);
1903
- var adapter = new adapterType(library);
1904
1811
 
1905
- if (adapters.indexOf(adapter) === -1) {
1906
- adapters.push(adapter);
1812
+ for (var i = 0; i < adapters.length; i++) {
1813
+ if (adapters[i].library === library) {
1814
+ return;
1815
+ }
1907
1816
  }
1817
+
1818
+ adapters.push(new adapterType(library));
1908
1819
  }
1909
1820
 
1910
1821
  function loadAdapters() {
@@ -1921,42 +1832,16 @@
1921
1832
  }
1922
1833
  }
1923
1834
 
1924
- function dataEmpty(data, chartType) {
1925
- if (chartType === "PieChart" || chartType === "GeoChart" || chartType === "Timeline") {
1926
- return data.length === 0;
1927
- } else {
1928
- for (var i = 0; i < data.length; i++) {
1929
- if (data[i].data.length > 0) {
1930
- return false;
1931
- }
1932
- }
1933
- return true;
1934
- }
1935
- }
1936
-
1937
- function renderChart(chartType, chart) {
1938
- if (dataEmpty(chart.data, chartType)) {
1939
- var message = chart.options.empty || (chart.options.messages && chart.options.messages.empty) || "No data";
1940
- setText(chart.element, message);
1941
- } else {
1942
- callAdapter(chartType, chart);
1943
- if (chart.options.download && !chart.__downloadAttached && chart.adapter === "chartjs") {
1944
- addDownloadButton(chart);
1945
- }
1946
- }
1947
- }
1948
-
1949
1835
  // TODO remove chartType if cross-browser way
1950
1836
  // to get the name of the chart class
1951
1837
  function callAdapter(chartType, chart) {
1952
- var i, adapter, fnName, adapterName;
1953
- fnName = "render" + chartType;
1954
- adapterName = chart.options.adapter;
1838
+ var fnName = "render" + chartType;
1839
+ var adapterName = chart.options.adapter;
1955
1840
 
1956
1841
  loadAdapters();
1957
1842
 
1958
- for (i = 0; i < adapters.length; i++) {
1959
- adapter = adapters[i];
1843
+ for (var i = 0; i < adapters.length; i++) {
1844
+ var adapter = adapters[i];
1960
1845
  if ((!adapterName || adapterName === adapter.name) && isFunction(adapter[fnName])) {
1961
1846
  chart.adapter = adapter.name;
1962
1847
  chart.__adapterObject = adapter;
@@ -1971,36 +1856,73 @@
1971
1856
  }
1972
1857
  }
1973
1858
 
1974
- // process data
1859
+ var Chartkick = {
1860
+ charts: {},
1861
+ configure: function (options) {
1862
+ for (var key in options) {
1863
+ if (Object.prototype.hasOwnProperty.call(options, key)) {
1864
+ Chartkick.config[key] = options[key];
1865
+ }
1866
+ }
1867
+ },
1868
+ setDefaultOptions: function (opts) {
1869
+ Chartkick.options = opts;
1870
+ },
1871
+ eachChart: function (callback) {
1872
+ for (var chartId in Chartkick.charts) {
1873
+ if (Object.prototype.hasOwnProperty.call(Chartkick.charts, chartId)) {
1874
+ callback(Chartkick.charts[chartId]);
1875
+ }
1876
+ }
1877
+ },
1878
+ destroyAll: function () {
1879
+ for (var chartId in Chartkick.charts) {
1880
+ if (Object.prototype.hasOwnProperty.call(Chartkick.charts, chartId)) {
1881
+ Chartkick.charts[chartId].destroy();
1882
+ delete Chartkick.charts[chartId];
1883
+ }
1884
+ }
1885
+ },
1886
+ config: {},
1887
+ options: {},
1888
+ adapters: adapters,
1889
+ addAdapter: addAdapter,
1890
+ use: function (adapter) {
1891
+ addAdapter(adapter);
1892
+ return Chartkick;
1893
+ }
1894
+ };
1895
+
1896
+ function formatSeriesBubble(data) {
1897
+ var r = [];
1898
+ for (var i = 0; i < data.length; i++) {
1899
+ r.push([toFloat(data[i][0]), toFloat(data[i][1]), toFloat(data[i][2])]);
1900
+ }
1901
+ return r;
1902
+ }
1903
+
1904
+ // casts data to proper type
1905
+ // sorting is left to adapters
1906
+ function formatSeriesData(data, keyType) {
1907
+ if (keyType === "bubble") {
1908
+ return formatSeriesBubble(data);
1909
+ }
1975
1910
 
1976
- var toFormattedKey = function (key, keyType) {
1911
+ var keyFunc;
1977
1912
  if (keyType === "number") {
1978
- key = toFloat(key);
1913
+ keyFunc = toFloat;
1979
1914
  } else if (keyType === "datetime") {
1980
- key = toDate(key);
1915
+ keyFunc = toDate;
1981
1916
  } else {
1982
- key = toStr(key);
1917
+ keyFunc = toStr;
1983
1918
  }
1984
- return key;
1985
- };
1986
1919
 
1987
- var formatSeriesData = function (data, keyType) {
1988
- var r = [], key, j;
1989
- for (j = 0; j < data.length; j++) {
1990
- if (keyType === "bubble") {
1991
- r.push([toFloat(data[j][0]), toFloat(data[j][1]), toFloat(data[j][2])]);
1992
- } else {
1993
- key = toFormattedKey(data[j][0], keyType);
1994
- r.push([key, toFloat(data[j][1])]);
1995
- }
1996
- }
1997
- if (keyType === "datetime") {
1998
- r.sort(sortByTime);
1999
- } else if (keyType === "number") {
2000
- r.sort(sortByNumberSeries);
1920
+ var r = [];
1921
+ for (var i = 0; i < data.length; i++) {
1922
+ r.push([keyFunc(data[i][0]), toFloat(data[i][1])]);
2001
1923
  }
2002
1924
  return r;
2003
- };
1925
+ }
2004
1926
 
2005
1927
  function detectXType(series, noDatetime, options) {
2006
1928
  if (dataEmpty(series)) {
@@ -2019,10 +1941,9 @@
2019
1941
  }
2020
1942
 
2021
1943
  function detectXTypeWithFunction(series, func) {
2022
- var i, j, data;
2023
- for (i = 0; i < series.length; i++) {
2024
- data = toArr(series[i].data);
2025
- for (j = 0; j < data.length; j++) {
1944
+ for (var i = 0; i < series.length; i++) {
1945
+ var data = toArr(series[i].data);
1946
+ for (var j = 0; j < data.length; j++) {
2026
1947
  if (!func(data[j][0])) {
2027
1948
  return false;
2028
1949
  }
@@ -2034,11 +1955,11 @@
2034
1955
  // creates a shallow copy of each element of the array
2035
1956
  // elements are expected to be objects
2036
1957
  function copySeries(series) {
2037
- var newSeries = [], i, j;
2038
- for (i = 0; i < series.length; i++) {
1958
+ var newSeries = [];
1959
+ for (var i = 0; i < series.length; i++) {
2039
1960
  var copy = {};
2040
- for (j in series[i]) {
2041
- if (series[i].hasOwnProperty(j)) {
1961
+ for (var j in series[i]) {
1962
+ if (Object.prototype.hasOwnProperty.call(series[i], j)) {
2042
1963
  copy[j] = series[i][j];
2043
1964
  }
2044
1965
  }
@@ -2048,60 +1969,235 @@
2048
1969
  }
2049
1970
 
2050
1971
  function processSeries(chart, keyType, noDatetime) {
2051
- var i;
2052
-
2053
1972
  var opts = chart.options;
2054
1973
  var series = chart.rawData;
2055
1974
 
2056
1975
  // see if one series or multiple
2057
- if (!isArray(series) || typeof series[0] !== "object" || isArray(series[0])) {
1976
+ chart.singleSeriesFormat = !isArray(series) || !isPlainObject(series[0]);
1977
+ if (chart.singleSeriesFormat) {
2058
1978
  series = [{name: opts.label, data: series}];
2059
- chart.singleSeriesFormat = true;
2060
- } else {
2061
- chart.singleSeriesFormat = false;
2062
1979
  }
2063
1980
 
2064
1981
  // convert to array
2065
1982
  // must come before dataEmpty check
2066
1983
  series = copySeries(series);
2067
- for (i = 0; i < series.length; i++) {
1984
+ for (var i = 0; i < series.length; i++) {
2068
1985
  series[i].data = toArr(series[i].data);
2069
1986
  }
2070
1987
 
2071
- chart.xtype = keyType ? keyType : (opts.discrete ? "string" : detectXType(series, noDatetime, opts));
1988
+ chart.xtype = keyType || (opts.discrete ? "string" : detectXType(series, noDatetime, opts));
2072
1989
 
2073
1990
  // right format
2074
- for (i = 0; i < series.length; i++) {
2075
- series[i].data = formatSeriesData(series[i].data, chart.xtype);
1991
+ for (var i$1 = 0; i$1 < series.length; i$1++) {
1992
+ series[i$1].data = formatSeriesData(series[i$1].data, chart.xtype);
2076
1993
  }
2077
1994
 
2078
1995
  return series;
2079
1996
  }
2080
1997
 
2081
1998
  function processSimple(chart) {
2082
- var perfectData = toArr(chart.rawData), i;
2083
- for (i = 0; i < perfectData.length; i++) {
1999
+ var perfectData = toArr(chart.rawData);
2000
+ for (var i = 0; i < perfectData.length; i++) {
2084
2001
  perfectData[i] = [toStr(perfectData[i][0]), toFloat(perfectData[i][1])];
2085
2002
  }
2086
2003
  return perfectData;
2087
2004
  }
2088
2005
 
2089
- // define classes
2006
+ function dataEmpty(data, chartType) {
2007
+ if (chartType === "PieChart" || chartType === "GeoChart" || chartType === "Timeline") {
2008
+ return data.length === 0;
2009
+ } else {
2010
+ for (var i = 0; i < data.length; i++) {
2011
+ if (data[i].data.length > 0) {
2012
+ return false;
2013
+ }
2014
+ }
2015
+ return true;
2016
+ }
2017
+ }
2090
2018
 
2091
- var Chart = function Chart(element, dataSource, options) {
2092
- var elementId;
2019
+ function addDownloadButton(chart) {
2020
+ var download = chart.options.download;
2021
+ if (download === true) {
2022
+ download = {};
2023
+ } else if (typeof download === "string") {
2024
+ download = {filename: download};
2025
+ }
2026
+
2027
+ var link = document.createElement("a");
2028
+ link.download = download.filename || "chart.png";
2029
+ link.style.position = "absolute";
2030
+ link.style.top = "20px";
2031
+ link.style.right = "20px";
2032
+ link.style.zIndex = 1000;
2033
+ link.style.lineHeight = "20px";
2034
+ link.target = "_blank"; // for safari
2035
+
2036
+ var image = document.createElement("img");
2037
+ // icon from Font Awesome, modified to set fill color
2038
+ var svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path fill=\"#CCCCCC\" d=\"M344 240h-56L287.1 152c0-13.25-10.75-24-24-24h-16C234.7 128 223.1 138.8 223.1 152L224 240h-56c-9.531 0-18.16 5.656-22 14.38C142.2 263.1 143.9 273.3 150.4 280.3l88.75 96C243.7 381.2 250.1 384 256.8 384c7.781-.3125 13.25-2.875 17.75-7.844l87.25-96c6.406-7.031 8.031-17.19 4.188-25.88S353.5 240 344 240zM256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 464c-114.7 0-208-93.31-208-208S141.3 48 256 48s208 93.31 208 208S370.7 464 256 464z\"/></svg>";
2039
+ image.src = "data:image/svg+xml;utf8," + (encodeURIComponent(svg));
2040
+ image.alt = "Download";
2041
+ image.style.width = "20px";
2042
+ image.style.height = "20px";
2043
+ image.style.border = "none";
2044
+ link.appendChild(image);
2045
+
2046
+ var element = chart.element;
2047
+ element.style.position = "relative";
2048
+
2049
+ chart.__downloadAttached = true;
2050
+
2051
+ // mouseenter
2052
+ chart.__enterEvent = element.addEventListener("mouseover", function (e) {
2053
+ var related = e.relatedTarget;
2054
+ // check download option again to ensure it wasn't changed
2055
+ if ((!related || (related !== this && !this.contains(related))) && chart.options.download) {
2056
+ link.href = chart.toImage(download);
2057
+ element.appendChild(link);
2058
+ }
2059
+ });
2060
+
2061
+ // mouseleave
2062
+ chart.__leaveEvent = element.addEventListener("mouseout", function (e) {
2063
+ var related = e.relatedTarget;
2064
+ if (!related || (related !== this && !this.contains(related))) {
2065
+ if (link.parentNode) {
2066
+ link.parentNode.removeChild(link);
2067
+ }
2068
+ }
2069
+ });
2070
+ }
2071
+
2072
+ var pendingRequests = [];
2073
+ var runningRequests = 0;
2074
+ var maxRequests = 4;
2075
+
2076
+ function pushRequest(url, success, error) {
2077
+ pendingRequests.push([url, success, error]);
2078
+ runNext();
2079
+ }
2080
+
2081
+ function runNext() {
2082
+ if (runningRequests < maxRequests) {
2083
+ var request = pendingRequests.shift();
2084
+ if (request) {
2085
+ runningRequests++;
2086
+ getJSON(request[0], request[1], request[2]);
2087
+ runNext();
2088
+ }
2089
+ }
2090
+ }
2091
+
2092
+ function requestComplete() {
2093
+ runningRequests--;
2094
+ runNext();
2095
+ }
2096
+
2097
+ function getJSON(url, success, error) {
2098
+ var xhr = new XMLHttpRequest();
2099
+ xhr.open("GET", url, true);
2100
+ xhr.setRequestHeader("Content-Type", "application/json");
2101
+ xhr.onload = function () {
2102
+ requestComplete();
2103
+ if (xhr.status === 200) {
2104
+ success(JSON.parse(xhr.responseText));
2105
+ } else {
2106
+ error(xhr.statusText);
2107
+ }
2108
+ };
2109
+ xhr.send();
2110
+ }
2111
+
2112
+ // helpers
2113
+
2114
+ function setText(element, text) {
2115
+ element.textContent = text;
2116
+ }
2117
+
2118
+ // TODO remove prefix for all messages
2119
+ function chartError(element, message, noPrefix) {
2120
+ if (!noPrefix) {
2121
+ message = "Error Loading Chart: " + message;
2122
+ }
2123
+ setText(element, message);
2124
+ element.style.color = "#ff0000";
2125
+ }
2126
+
2127
+ function errorCatcher(chart) {
2128
+ try {
2129
+ chart.__render();
2130
+ } catch (err) {
2131
+ chartError(chart.element, err.message);
2132
+ throw err;
2133
+ }
2134
+ }
2135
+
2136
+ function fetchDataSource(chart, dataSource, showLoading) {
2137
+ // only show loading message for urls and callbacks
2138
+ if (showLoading && chart.options.loading && (typeof dataSource === "string" || typeof dataSource === "function")) {
2139
+ setText(chart.element, chart.options.loading);
2140
+ }
2141
+
2142
+ if (typeof dataSource === "string") {
2143
+ pushRequest(dataSource, function (data) {
2144
+ chart.rawData = data;
2145
+ errorCatcher(chart);
2146
+ }, function (message) {
2147
+ chartError(chart.element, message);
2148
+ });
2149
+ } else if (typeof dataSource === "function") {
2150
+ try {
2151
+ dataSource(function (data) {
2152
+ chart.rawData = data;
2153
+ errorCatcher(chart);
2154
+ }, function (message) {
2155
+ chartError(chart.element, message, true);
2156
+ });
2157
+ } catch (err) {
2158
+ chartError(chart.element, err, true);
2159
+ }
2160
+ } else {
2161
+ chart.rawData = dataSource;
2162
+ errorCatcher(chart);
2163
+ }
2164
+ }
2165
+
2166
+ function renderChart(chartType, chart) {
2167
+ if (dataEmpty(chart.data, chartType)) {
2168
+ var message = chart.options.empty || (chart.options.messages && chart.options.messages.empty) || "No data";
2169
+ setText(chart.element, message);
2170
+ } else {
2171
+ callAdapter(chartType, chart);
2172
+ // TODO add downloadSupported method to adapter
2173
+ if (chart.options.download && !chart.__downloadAttached && chart.adapter === "chartjs") {
2174
+ addDownloadButton(chart);
2175
+ }
2176
+ }
2177
+ }
2178
+
2179
+ function getElement(element) {
2093
2180
  if (typeof element === "string") {
2094
- elementId = element;
2181
+ var elementId = element;
2095
2182
  element = document.getElementById(element);
2096
2183
  if (!element) {
2097
2184
  throw new Error("No element with id " + elementId);
2098
2185
  }
2099
2186
  }
2100
- this.element = element;
2187
+ return element;
2188
+ }
2189
+
2190
+ // define classes
2191
+
2192
+ var Chart = function Chart(element, dataSource, options) {
2193
+ this.element = getElement(element);
2101
2194
  this.options = merge(Chartkick.options, options || {});
2102
2195
  this.dataSource = dataSource;
2103
2196
 
2104
- Chartkick.charts[element.id] = this;
2197
+ // TODO handle charts without an id for eachChart and destroyAll
2198
+ if (this.element.id) {
2199
+ Chartkick.charts[this.element.id] = this;
2200
+ }
2105
2201
 
2106
2202
  fetchDataSource(this, dataSource, true);
2107
2203
 
@@ -2163,7 +2259,7 @@
2163
2259
  };
2164
2260
 
2165
2261
  Chart.prototype.startRefresh = function startRefresh () {
2166
- var this$1 = this;
2262
+ var this$1$1 = this;
2167
2263
 
2168
2264
  var refresh = this.options.refresh;
2169
2265
 
@@ -2173,8 +2269,8 @@
2173
2269
 
2174
2270
  if (!this.intervalId) {
2175
2271
  if (refresh) {
2176
- this.intervalId = setInterval( function () {
2177
- this$1.refreshData();
2272
+ this.intervalId = setInterval(function () {
2273
+ this$1$1.refreshData();
2178
2274
  }, refresh * 1000);
2179
2275
  } else {
2180
2276
  throw new Error("No refresh interval");
@@ -2190,11 +2286,12 @@
2190
2286
  };
2191
2287
 
2192
2288
  Chart.prototype.toImage = function toImage (download) {
2289
+ // TODO move logic to adapter
2193
2290
  if (this.adapter === "chartjs") {
2194
2291
  if (download && download.background && download.background !== "transparent") {
2195
2292
  // https://stackoverflow.com/questions/30464750/chartjs-line-chart-set-background-color
2196
- var canvas = this.chart.chart.canvas;
2197
- var ctx = this.chart.chart.ctx;
2293
+ var canvas = this.chart.canvas;
2294
+ var ctx = this.chart.ctx;
2198
2295
  var tmpCanvas = document.createElement("canvas");
2199
2296
  var tmpCtx = tmpCanvas.getContext("2d");
2200
2297
  tmpCanvas.width = ctx.canvas.width;
@@ -2220,11 +2317,11 @@
2220
2317
  }
2221
2318
 
2222
2319
  if (this.__enterEvent) {
2223
- removeEvent(this.element, "mouseover", this.__enterEvent);
2320
+ this.element.removeEventListener("mouseover", this.__enterEvent);
2224
2321
  }
2225
2322
 
2226
2323
  if (this.__leaveEvent) {
2227
- removeEvent(this.element, "mouseout", this.__leaveEvent);
2324
+ this.element.removeEventListener("mouseout", this.__leaveEvent);
2228
2325
  }
2229
2326
  };
2230
2327
 
@@ -2243,7 +2340,7 @@
2243
2340
  };
2244
2341
 
2245
2342
  Chart.prototype.__config = function __config () {
2246
- return config;
2343
+ return Chartkick.config;
2247
2344
  };
2248
2345
 
2249
2346
  var LineChart = /*@__PURE__*/(function (Chart) {
@@ -2416,8 +2513,8 @@
2416
2513
  Timeline.prototype.constructor = Timeline;
2417
2514
 
2418
2515
  Timeline.prototype.__processData = function __processData () {
2419
- var i, data = this.rawData;
2420
- for (i = 0; i < data.length; i++) {
2516
+ var data = this.rawData;
2517
+ for (var i = 0; i < data.length; i++) {
2421
2518
  data[i][1] = toDate(data[i][1]);
2422
2519
  data[i][2] = toDate(data[i][2]);
2423
2520
  }
@@ -2431,63 +2528,36 @@
2431
2528
  return Timeline;
2432
2529
  }(Chart));
2433
2530
 
2434
- var Chartkick = {
2435
- LineChart: LineChart,
2436
- PieChart: PieChart,
2437
- ColumnChart: ColumnChart,
2438
- BarChart: BarChart,
2439
- AreaChart: AreaChart,
2440
- GeoChart: GeoChart,
2441
- ScatterChart: ScatterChart,
2442
- BubbleChart: BubbleChart,
2443
- Timeline: Timeline,
2444
- charts: {},
2445
- configure: function (options) {
2446
- for (var key in options) {
2447
- if (options.hasOwnProperty(key)) {
2448
- config[key] = options[key];
2449
- }
2450
- }
2451
- },
2452
- setDefaultOptions: function (opts) {
2453
- Chartkick.options = opts;
2454
- },
2455
- eachChart: function (callback) {
2456
- for (var chartId in Chartkick.charts) {
2457
- if (Chartkick.charts.hasOwnProperty(chartId)) {
2458
- callback(Chartkick.charts[chartId]);
2459
- }
2460
- }
2461
- },
2462
- destroyAll: function() {
2463
- for (var chartId in Chartkick.charts) {
2464
- if (Chartkick.charts.hasOwnProperty(chartId)) {
2465
- Chartkick.charts[chartId].destroy();
2466
- delete Chartkick.charts[chartId];
2467
- }
2468
- }
2469
- },
2470
- config: config,
2471
- options: {},
2472
- adapters: adapters,
2473
- addAdapter: addAdapter,
2474
- use: function(adapter) {
2475
- addAdapter(adapter);
2476
- return Chartkick;
2477
- }
2478
- };
2531
+ Chartkick.LineChart = LineChart;
2532
+ Chartkick.PieChart = PieChart;
2533
+ Chartkick.ColumnChart = ColumnChart;
2534
+ Chartkick.BarChart = BarChart;
2535
+ Chartkick.AreaChart = AreaChart;
2536
+ Chartkick.GeoChart = GeoChart;
2537
+ Chartkick.ScatterChart = ScatterChart;
2538
+ Chartkick.BubbleChart = BubbleChart;
2539
+ Chartkick.Timeline = Timeline;
2479
2540
 
2480
2541
  // not ideal, but allows for simpler integration
2481
2542
  if (typeof window !== "undefined" && !window.Chartkick) {
2482
2543
  window.Chartkick = Chartkick;
2483
2544
 
2484
2545
  // clean up previous charts before Turbolinks loads new page
2485
- document.addEventListener("turbolinks:before-render", function() {
2486
- Chartkick.destroyAll();
2546
+ document.addEventListener("turbolinks:before-render", function () {
2547
+ if (Chartkick.config.autoDestroy !== false) {
2548
+ Chartkick.destroyAll();
2549
+ }
2550
+ });
2551
+
2552
+ // clean up previous charts before Turbo loads new page
2553
+ document.addEventListener("turbo:before-render", function () {
2554
+ if (Chartkick.config.autoDestroy !== false) {
2555
+ Chartkick.destroyAll();
2556
+ }
2487
2557
  });
2488
2558
 
2489
2559
  // use setTimeout so charting library can come later in same JS file
2490
- setTimeout(function() {
2560
+ setTimeout(function () {
2491
2561
  window.dispatchEvent(new Event("chartkick:load"));
2492
2562
  }, 0);
2493
2563
  }
@@ -2497,4 +2567,4 @@
2497
2567
 
2498
2568
  return Chartkick;
2499
2569
 
2500
- })));
2570
+ }));