chartkick 3.2.1 → 3.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +71 -48
- data/README.md +45 -16
- data/lib/chartkick/helper.rb +29 -14
- data/lib/chartkick/version.rb +1 -1
- data/vendor/assets/javascripts/Chart.bundle.js +4432 -2965
- data/vendor/assets/javascripts/chartkick.js +199 -29
- metadata +3 -4
- data/CONTRIBUTING.md +0 -46
@@ -2,7 +2,7 @@
|
|
2
2
|
* Chartkick.js
|
3
3
|
* Create beautiful charts with one line of JavaScript
|
4
4
|
* https://github.com/ankane/chartkick.js
|
5
|
-
* v3.
|
5
|
+
* v3.2.1
|
6
6
|
* MIT License
|
7
7
|
*/
|
8
8
|
|
@@ -10,7 +10,7 @@
|
|
10
10
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
11
11
|
typeof define === 'function' && define.amd ? define(factory) :
|
12
12
|
(global = global || self, global.Chartkick = factory());
|
13
|
-
}(this, function () { 'use strict';
|
13
|
+
}(this, (function () { 'use strict';
|
14
14
|
|
15
15
|
function isArray(variable) {
|
16
16
|
return Object.prototype.toString.call(variable) === "[object Array]";
|
@@ -21,13 +21,17 @@
|
|
21
21
|
}
|
22
22
|
|
23
23
|
function isPlainObject(variable) {
|
24
|
-
|
24
|
+
// protect against prototype pollution, defense 2
|
25
|
+
return Object.prototype.toString.call(variable) === "[object Object]" && !isFunction(variable) && variable instanceof Object;
|
25
26
|
}
|
26
27
|
|
27
28
|
// https://github.com/madrobby/zepto/blob/master/src/zepto.js
|
28
29
|
function extend(target, source) {
|
29
30
|
var key;
|
30
31
|
for (key in source) {
|
32
|
+
// protect against prototype pollution, defense 1
|
33
|
+
if (key === "__proto__") { continue; }
|
34
|
+
|
31
35
|
if (isPlainObject(source[key]) || isArray(source[key])) {
|
32
36
|
if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
|
33
37
|
target[key] = {};
|
@@ -237,7 +241,9 @@
|
|
237
241
|
return typeof obj === "number";
|
238
242
|
}
|
239
243
|
|
240
|
-
|
244
|
+
var byteSuffixes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB"];
|
245
|
+
|
246
|
+
function formatValue(pre, value, options, axis) {
|
241
247
|
pre = pre || "";
|
242
248
|
if (options.prefix) {
|
243
249
|
if (value < 0) {
|
@@ -247,6 +253,74 @@
|
|
247
253
|
pre += options.prefix;
|
248
254
|
}
|
249
255
|
|
256
|
+
var suffix = options.suffix || "";
|
257
|
+
var precision = options.precision;
|
258
|
+
var round = options.round;
|
259
|
+
|
260
|
+
if (options.byteScale) {
|
261
|
+
var suffixIdx;
|
262
|
+
var baseValue = axis ? options.byteScale : value;
|
263
|
+
|
264
|
+
if (baseValue >= 1152921504606846976) {
|
265
|
+
value /= 1152921504606846976;
|
266
|
+
suffixIdx = 6;
|
267
|
+
} else if (baseValue >= 1125899906842624) {
|
268
|
+
value /= 1125899906842624;
|
269
|
+
suffixIdx = 5;
|
270
|
+
} else if (baseValue >= 1099511627776) {
|
271
|
+
value /= 1099511627776;
|
272
|
+
suffixIdx = 4;
|
273
|
+
} else if (baseValue >= 1073741824) {
|
274
|
+
value /= 1073741824;
|
275
|
+
suffixIdx = 3;
|
276
|
+
} else if (baseValue >= 1048576) {
|
277
|
+
value /= 1048576;
|
278
|
+
suffixIdx = 2;
|
279
|
+
} else if (baseValue >= 1024) {
|
280
|
+
value /= 1024;
|
281
|
+
suffixIdx = 1;
|
282
|
+
} else {
|
283
|
+
suffixIdx = 0;
|
284
|
+
}
|
285
|
+
|
286
|
+
// TODO handle manual precision case
|
287
|
+
if (precision === undefined && round === undefined) {
|
288
|
+
if (value >= 1023.5) {
|
289
|
+
if (suffixIdx < byteSuffixes.length - 1) {
|
290
|
+
value = 1.0;
|
291
|
+
suffixIdx += 1;
|
292
|
+
}
|
293
|
+
}
|
294
|
+
precision = value >= 1000 ? 4 : 3;
|
295
|
+
}
|
296
|
+
suffix = " " + byteSuffixes[suffixIdx];
|
297
|
+
}
|
298
|
+
|
299
|
+
if (precision !== undefined && round !== undefined) {
|
300
|
+
throw Error("Use either round or precision, not both");
|
301
|
+
}
|
302
|
+
|
303
|
+
if (!axis) {
|
304
|
+
if (precision !== undefined) {
|
305
|
+
value = value.toPrecision(precision);
|
306
|
+
if (!options.zeros) {
|
307
|
+
value = parseFloat(value);
|
308
|
+
}
|
309
|
+
}
|
310
|
+
|
311
|
+
if (round !== undefined) {
|
312
|
+
if (round < 0) {
|
313
|
+
var num = Math.pow(10, -1 * round);
|
314
|
+
value = parseInt((1.0 * value / num).toFixed(0)) * num;
|
315
|
+
} else {
|
316
|
+
value = value.toFixed(round);
|
317
|
+
if (!options.zeros) {
|
318
|
+
value = parseFloat(value);
|
319
|
+
}
|
320
|
+
}
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
250
324
|
if (options.thousands || options.decimal) {
|
251
325
|
value = toStr(value);
|
252
326
|
var parts = value.split(".");
|
@@ -259,7 +333,7 @@
|
|
259
333
|
}
|
260
334
|
}
|
261
335
|
|
262
|
-
return pre + value +
|
336
|
+
return pre + value + suffix;
|
263
337
|
}
|
264
338
|
|
265
339
|
function seriesOption(chart, series, option) {
|
@@ -420,18 +494,58 @@
|
|
420
494
|
prefix: chart.options.prefix,
|
421
495
|
suffix: chart.options.suffix,
|
422
496
|
thousands: chart.options.thousands,
|
423
|
-
decimal: chart.options.decimal
|
497
|
+
decimal: chart.options.decimal,
|
498
|
+
precision: chart.options.precision,
|
499
|
+
round: chart.options.round,
|
500
|
+
zeros: chart.options.zeros
|
424
501
|
};
|
425
502
|
|
503
|
+
if (chart.options.bytes) {
|
504
|
+
var series = chart.data;
|
505
|
+
if (chartType === "pie") {
|
506
|
+
series = [{data: series}];
|
507
|
+
}
|
508
|
+
|
509
|
+
// calculate max
|
510
|
+
var max = 0;
|
511
|
+
for (var i = 0; i < series.length; i++) {
|
512
|
+
var s = series[i];
|
513
|
+
for (var j = 0; j < s.data.length; j++) {
|
514
|
+
if (s.data[j][1] > max) {
|
515
|
+
max = s.data[j][1];
|
516
|
+
}
|
517
|
+
}
|
518
|
+
}
|
519
|
+
|
520
|
+
// calculate scale
|
521
|
+
var scale = 1;
|
522
|
+
while (max >= 1024) {
|
523
|
+
scale *= 1024;
|
524
|
+
max /= 1024;
|
525
|
+
}
|
526
|
+
|
527
|
+
// set step size
|
528
|
+
formatOptions.byteScale = scale;
|
529
|
+
}
|
530
|
+
|
426
531
|
if (chartType !== "pie") {
|
427
532
|
var myAxes = options.scales.yAxes;
|
428
533
|
if (chartType === "bar") {
|
429
534
|
myAxes = options.scales.xAxes;
|
430
535
|
}
|
431
536
|
|
537
|
+
if (formatOptions.byteScale) {
|
538
|
+
if (!myAxes[0].ticks.stepSize) {
|
539
|
+
myAxes[0].ticks.stepSize = formatOptions.byteScale / 2;
|
540
|
+
}
|
541
|
+
if (!myAxes[0].ticks.maxTicksLimit) {
|
542
|
+
myAxes[0].ticks.maxTicksLimit = 4;
|
543
|
+
}
|
544
|
+
}
|
545
|
+
|
432
546
|
if (!myAxes[0].ticks.callback) {
|
433
547
|
myAxes[0].ticks.callback = function (value) {
|
434
|
-
return formatValue("", value, formatOptions);
|
548
|
+
return formatValue("", value, formatOptions, true);
|
435
549
|
};
|
436
550
|
}
|
437
551
|
}
|
@@ -486,7 +600,7 @@
|
|
486
600
|
|
487
601
|
var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
|
488
602
|
|
489
|
-
var createDataTable = function (chart, options, chartType) {
|
603
|
+
var createDataTable = function (chart, options, chartType, library) {
|
490
604
|
var datasets = [];
|
491
605
|
var labels = [];
|
492
606
|
|
@@ -631,11 +745,15 @@
|
|
631
745
|
var xmax = chart.options.xmax;
|
632
746
|
|
633
747
|
if (chart.xtype === "datetime") {
|
748
|
+
// hacky check for Chart.js >= 2.9.0
|
749
|
+
// https://github.com/chartjs/Chart.js/compare/v2.8.0...v2.9.0
|
750
|
+
var gte29 = "math" in library.helpers;
|
751
|
+
var ticksKey = gte29 ? "ticks" : "time";
|
634
752
|
if (notnull(xmin)) {
|
635
|
-
options.scales.xAxes[0].
|
753
|
+
options.scales.xAxes[0][ticksKey].min = toDate(xmin).getTime();
|
636
754
|
}
|
637
755
|
if (notnull(xmax)) {
|
638
|
-
options.scales.xAxes[0].
|
756
|
+
options.scales.xAxes[0][ticksKey].max = toDate(xmax).getTime();
|
639
757
|
}
|
640
758
|
} else if (chart.xtype === "number") {
|
641
759
|
if (notnull(xmin)) {
|
@@ -646,6 +764,22 @@
|
|
646
764
|
}
|
647
765
|
}
|
648
766
|
|
767
|
+
// for empty datetime chart
|
768
|
+
if (chart.xtype === "datetime" && labels.length === 0) {
|
769
|
+
if (notnull(xmin)) {
|
770
|
+
labels.push(toDate(xmin));
|
771
|
+
}
|
772
|
+
if (notnull(xmax)) {
|
773
|
+
labels.push(toDate(xmax));
|
774
|
+
}
|
775
|
+
day = false;
|
776
|
+
week = false;
|
777
|
+
month = false;
|
778
|
+
year = false;
|
779
|
+
hour = false;
|
780
|
+
minute = false;
|
781
|
+
}
|
782
|
+
|
649
783
|
if (chart.xtype === "datetime" && labels.length > 0) {
|
650
784
|
var minTime = (notnull(xmin) ? toDate(xmin) : labels[0]).getTime();
|
651
785
|
var maxTime = (notnull(xmax) ? toDate(xmax) : labels[0]).getTime();
|
@@ -726,7 +860,7 @@
|
|
726
860
|
var options = jsOptions(chart, merge(chartOptions, chart.options));
|
727
861
|
setFormatOptions(chart, options, chartType);
|
728
862
|
|
729
|
-
var data = createDataTable(chart, options, chartType || "line");
|
863
|
+
var data = createDataTable(chart, options, chartType || "line", this.library);
|
730
864
|
|
731
865
|
if (chart.xtype === "number") {
|
732
866
|
options.scales.xAxes[0].type = "linear";
|
@@ -787,7 +921,7 @@
|
|
787
921
|
options = jsOptions(chart, chart.options);
|
788
922
|
}
|
789
923
|
setFormatOptions(chart, options, chartType);
|
790
|
-
var data = createDataTable(chart, options, "column");
|
924
|
+
var data = createDataTable(chart, options, "column", this.library);
|
791
925
|
if (chartType !== "bar") {
|
792
926
|
setLabelSize(chart, data, options);
|
793
927
|
}
|
@@ -812,7 +946,7 @@
|
|
812
946
|
options.showLines = false;
|
813
947
|
}
|
814
948
|
|
815
|
-
var data = createDataTable(chart, options, chartType);
|
949
|
+
var data = createDataTable(chart, options, chartType, this.library);
|
816
950
|
|
817
951
|
options.scales.xAxes[0].type = "linear";
|
818
952
|
options.scales.xAxes[0].position = "bottom";
|
@@ -886,6 +1020,7 @@
|
|
886
1020
|
},
|
887
1021
|
plotOptions: {
|
888
1022
|
areaspline: {},
|
1023
|
+
area: {},
|
889
1024
|
series: {
|
890
1025
|
marker: {}
|
891
1026
|
}
|
@@ -922,7 +1057,10 @@
|
|
922
1057
|
};
|
923
1058
|
|
924
1059
|
var setStacked$1 = function (options, stacked) {
|
925
|
-
|
1060
|
+
var stackedValue = stacked ? (stacked === true ? "normal" : stacked) : null;
|
1061
|
+
options.plotOptions.series.stacking = stackedValue;
|
1062
|
+
options.plotOptions.area.stacking = stackedValue;
|
1063
|
+
options.plotOptions.areaspline.stacking = stackedValue;
|
926
1064
|
};
|
927
1065
|
|
928
1066
|
var setXtitle$1 = function (options, title) {
|
@@ -940,7 +1078,10 @@
|
|
940
1078
|
prefix: chart.options.prefix,
|
941
1079
|
suffix: chart.options.suffix,
|
942
1080
|
thousands: chart.options.thousands,
|
943
|
-
decimal: chart.options.decimal
|
1081
|
+
decimal: chart.options.decimal,
|
1082
|
+
precision: chart.options.precision,
|
1083
|
+
round: chart.options.round,
|
1084
|
+
zeros: chart.options.zeros
|
944
1085
|
};
|
945
1086
|
|
946
1087
|
if (chartType !== "pie" && !options.yAxis.labels.formatter) {
|
@@ -1341,7 +1482,7 @@
|
|
1341
1482
|
defaultExport$2.prototype.renderGeoChart = function renderGeoChart (chart) {
|
1342
1483
|
var this$1 = this;
|
1343
1484
|
|
1344
|
-
this.waitForLoaded(chart, function () {
|
1485
|
+
this.waitForLoaded(chart, "geochart", function () {
|
1345
1486
|
var chartOptions = {
|
1346
1487
|
legend: "none",
|
1347
1488
|
colorAxis: {
|
@@ -1457,7 +1598,7 @@
|
|
1457
1598
|
if (config.language) {
|
1458
1599
|
loadOptions.language = config.language;
|
1459
1600
|
}
|
1460
|
-
if (pack === "
|
1601
|
+
if (pack === "geochart" && config.mapsApiKey) {
|
1461
1602
|
loadOptions.mapsApiKey = config.mapsApiKey;
|
1462
1603
|
}
|
1463
1604
|
|
@@ -1469,7 +1610,7 @@
|
|
1469
1610
|
var cb, call;
|
1470
1611
|
for (var i = 0; i < callbacks.length; i++) {
|
1471
1612
|
cb = callbacks[i];
|
1472
|
-
call = this.library.visualization && ((cb.pack === "corechart" && this.library.visualization.LineChart) || (cb.pack === "timeline" && this.library.visualization.Timeline));
|
1613
|
+
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));
|
1473
1614
|
if (call) {
|
1474
1615
|
cb.callback();
|
1475
1616
|
callbacks.splice(i, 1);
|
@@ -1568,7 +1709,7 @@
|
|
1568
1709
|
function ajaxCall(url, success, error) {
|
1569
1710
|
var $ = window.jQuery || window.Zepto || window.$;
|
1570
1711
|
|
1571
|
-
if ($) {
|
1712
|
+
if ($ && $.ajax) {
|
1572
1713
|
$.ajax({
|
1573
1714
|
dataType: "json",
|
1574
1715
|
url: url,
|
@@ -1605,8 +1746,12 @@
|
|
1605
1746
|
}
|
1606
1747
|
}
|
1607
1748
|
|
1608
|
-
|
1609
|
-
|
1749
|
+
// TODO remove prefix for all messages
|
1750
|
+
function chartError(element, message, noPrefix) {
|
1751
|
+
if (!noPrefix) {
|
1752
|
+
message = "Error Loading Chart: " + message;
|
1753
|
+
}
|
1754
|
+
setText(element, message);
|
1610
1755
|
element.style.color = "#ff0000";
|
1611
1756
|
}
|
1612
1757
|
|
@@ -1627,6 +1772,17 @@
|
|
1627
1772
|
}, function (message) {
|
1628
1773
|
chartError(chart.element, message);
|
1629
1774
|
});
|
1775
|
+
} else if (typeof dataSource === "function") {
|
1776
|
+
try {
|
1777
|
+
dataSource(function (data) {
|
1778
|
+
chart.rawData = data;
|
1779
|
+
errorCatcher(chart);
|
1780
|
+
}, function (message) {
|
1781
|
+
chartError(chart.element, message, true);
|
1782
|
+
});
|
1783
|
+
} catch (err) {
|
1784
|
+
chartError(chart.element, err, true);
|
1785
|
+
}
|
1630
1786
|
} else {
|
1631
1787
|
chart.rawData = dataSource;
|
1632
1788
|
errorCatcher(chart);
|
@@ -1829,8 +1985,14 @@
|
|
1829
1985
|
return r;
|
1830
1986
|
};
|
1831
1987
|
|
1832
|
-
function detectXType(series, noDatetime) {
|
1833
|
-
if (
|
1988
|
+
function detectXType(series, noDatetime, options) {
|
1989
|
+
if (dataEmpty(series)) {
|
1990
|
+
if ((options.xmin || options.xmax) && (!options.xmin || isDate(options.xmin)) && (!options.xmax || isDate(options.xmax))) {
|
1991
|
+
return "datetime";
|
1992
|
+
} else {
|
1993
|
+
return "number";
|
1994
|
+
}
|
1995
|
+
} else if (detectXTypeWithFunction(series, isNumber)) {
|
1834
1996
|
return "number";
|
1835
1997
|
} else if (!noDatetime && detectXTypeWithFunction(series, isDate)) {
|
1836
1998
|
return "datetime";
|
@@ -1882,12 +2044,18 @@
|
|
1882
2044
|
chart.hideLegend = false;
|
1883
2045
|
}
|
1884
2046
|
|
1885
|
-
|
2047
|
+
// convert to array
|
2048
|
+
// must come before dataEmpty check
|
2049
|
+
series = copySeries(series);
|
2050
|
+
for (i = 0; i < series.length; i++) {
|
2051
|
+
series[i].data = toArr(series[i].data);
|
2052
|
+
}
|
2053
|
+
|
2054
|
+
chart.xtype = keyType ? keyType : (opts.discrete ? "string" : detectXType(series, noDatetime, opts));
|
1886
2055
|
|
1887
2056
|
// right format
|
1888
|
-
series = copySeries(series);
|
1889
2057
|
for (i = 0; i < series.length; i++) {
|
1890
|
-
series[i].data = formatSeriesData(
|
2058
|
+
series[i].data = formatSeriesData(series[i].data, chart.xtype);
|
1891
2059
|
}
|
1892
2060
|
|
1893
2061
|
return series;
|
@@ -1972,6 +2140,8 @@
|
|
1972
2140
|
var sep = this.dataSource.indexOf("?") === -1 ? "?" : "&";
|
1973
2141
|
var url = this.dataSource + sep + "_=" + (new Date()).getTime();
|
1974
2142
|
fetchDataSource(this, url);
|
2143
|
+
} else if (typeof this.dataSource === "function") {
|
2144
|
+
fetchDataSource(this, this.dataSource);
|
1975
2145
|
}
|
1976
2146
|
};
|
1977
2147
|
|
@@ -1980,8 +2150,8 @@
|
|
1980
2150
|
|
1981
2151
|
var refresh = this.options.refresh;
|
1982
2152
|
|
1983
|
-
if (refresh && typeof this.dataSource !== "string") {
|
1984
|
-
throw new Error("Data source must be a URL for refresh");
|
2153
|
+
if (refresh && typeof this.dataSource !== "string" && typeof this.dataSource !== "function") {
|
2154
|
+
throw new Error("Data source must be a URL or callback for refresh");
|
1985
2155
|
}
|
1986
2156
|
|
1987
2157
|
if (!this.intervalId) {
|
@@ -2291,4 +2461,4 @@
|
|
2291
2461
|
|
2292
2462
|
return Chartkick;
|
2293
2463
|
|
2294
|
-
}));
|
2464
|
+
})));
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chartkick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -59,7 +59,6 @@ extensions: []
|
|
59
59
|
extra_rdoc_files: []
|
60
60
|
files:
|
61
61
|
- CHANGELOG.md
|
62
|
-
- CONTRIBUTING.md
|
63
62
|
- LICENSE.txt
|
64
63
|
- README.md
|
65
64
|
- lib/chartkick.rb
|
@@ -88,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
87
|
- !ruby/object:Gem::Version
|
89
88
|
version: '0'
|
90
89
|
requirements: []
|
91
|
-
rubygems_version: 3.
|
90
|
+
rubygems_version: 3.1.2
|
92
91
|
signing_key:
|
93
92
|
specification_version: 4
|
94
93
|
summary: Create beautiful JavaScript charts with one line of Ruby
|