chartkick 3.2.0 → 3.3.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of chartkick might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +70 -47
- data/README.md +45 -16
- data/lib/chartkick/helper.rb +12 -10
- data/lib/chartkick/version.rb +1 -1
- data/vendor/assets/javascripts/Chart.bundle.js +4432 -2965
- data/vendor/assets/javascripts/chartkick.js +202 -30
- 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.1
|
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";
|
@@ -780,12 +914,14 @@
|
|
780
914
|
defaultExport.prototype.renderColumnChart = function renderColumnChart (chart, chartType) {
|
781
915
|
var options;
|
782
916
|
if (chartType === "bar") {
|
783
|
-
|
917
|
+
var barOptions = merge(baseOptions, defaultOptions);
|
918
|
+
delete barOptions.scales.yAxes[0].ticks.maxTicksLimit;
|
919
|
+
options = jsOptionsFunc(barOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options);
|
784
920
|
} else {
|
785
921
|
options = jsOptions(chart, chart.options);
|
786
922
|
}
|
787
923
|
setFormatOptions(chart, options, chartType);
|
788
|
-
var data = createDataTable(chart, options, "column");
|
924
|
+
var data = createDataTable(chart, options, "column", this.library);
|
789
925
|
if (chartType !== "bar") {
|
790
926
|
setLabelSize(chart, data, options);
|
791
927
|
}
|
@@ -810,7 +946,7 @@
|
|
810
946
|
options.showLines = false;
|
811
947
|
}
|
812
948
|
|
813
|
-
var data = createDataTable(chart, options, chartType);
|
949
|
+
var data = createDataTable(chart, options, chartType, this.library);
|
814
950
|
|
815
951
|
options.scales.xAxes[0].type = "linear";
|
816
952
|
options.scales.xAxes[0].position = "bottom";
|
@@ -884,6 +1020,7 @@
|
|
884
1020
|
},
|
885
1021
|
plotOptions: {
|
886
1022
|
areaspline: {},
|
1023
|
+
area: {},
|
887
1024
|
series: {
|
888
1025
|
marker: {}
|
889
1026
|
}
|
@@ -920,7 +1057,10 @@
|
|
920
1057
|
};
|
921
1058
|
|
922
1059
|
var setStacked$1 = function (options, stacked) {
|
923
|
-
|
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;
|
924
1064
|
};
|
925
1065
|
|
926
1066
|
var setXtitle$1 = function (options, title) {
|
@@ -938,7 +1078,10 @@
|
|
938
1078
|
prefix: chart.options.prefix,
|
939
1079
|
suffix: chart.options.suffix,
|
940
1080
|
thousands: chart.options.thousands,
|
941
|
-
decimal: chart.options.decimal
|
1081
|
+
decimal: chart.options.decimal,
|
1082
|
+
precision: chart.options.precision,
|
1083
|
+
round: chart.options.round,
|
1084
|
+
zeros: chart.options.zeros
|
942
1085
|
};
|
943
1086
|
|
944
1087
|
if (chartType !== "pie" && !options.yAxis.labels.formatter) {
|
@@ -1339,7 +1482,7 @@
|
|
1339
1482
|
defaultExport$2.prototype.renderGeoChart = function renderGeoChart (chart) {
|
1340
1483
|
var this$1 = this;
|
1341
1484
|
|
1342
|
-
this.waitForLoaded(chart, function () {
|
1485
|
+
this.waitForLoaded(chart, "geochart", function () {
|
1343
1486
|
var chartOptions = {
|
1344
1487
|
legend: "none",
|
1345
1488
|
colorAxis: {
|
@@ -1455,7 +1598,7 @@
|
|
1455
1598
|
if (config.language) {
|
1456
1599
|
loadOptions.language = config.language;
|
1457
1600
|
}
|
1458
|
-
if (pack === "
|
1601
|
+
if (pack === "geochart" && config.mapsApiKey) {
|
1459
1602
|
loadOptions.mapsApiKey = config.mapsApiKey;
|
1460
1603
|
}
|
1461
1604
|
|
@@ -1467,7 +1610,7 @@
|
|
1467
1610
|
var cb, call;
|
1468
1611
|
for (var i = 0; i < callbacks.length; i++) {
|
1469
1612
|
cb = callbacks[i];
|
1470
|
-
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));
|
1471
1614
|
if (call) {
|
1472
1615
|
cb.callback();
|
1473
1616
|
callbacks.splice(i, 1);
|
@@ -1566,7 +1709,7 @@
|
|
1566
1709
|
function ajaxCall(url, success, error) {
|
1567
1710
|
var $ = window.jQuery || window.Zepto || window.$;
|
1568
1711
|
|
1569
|
-
if ($) {
|
1712
|
+
if ($ && $.ajax) {
|
1570
1713
|
$.ajax({
|
1571
1714
|
dataType: "json",
|
1572
1715
|
url: url,
|
@@ -1603,8 +1746,12 @@
|
|
1603
1746
|
}
|
1604
1747
|
}
|
1605
1748
|
|
1606
|
-
|
1607
|
-
|
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);
|
1608
1755
|
element.style.color = "#ff0000";
|
1609
1756
|
}
|
1610
1757
|
|
@@ -1625,6 +1772,17 @@
|
|
1625
1772
|
}, function (message) {
|
1626
1773
|
chartError(chart.element, message);
|
1627
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
|
+
}
|
1628
1786
|
} else {
|
1629
1787
|
chart.rawData = dataSource;
|
1630
1788
|
errorCatcher(chart);
|
@@ -1827,8 +1985,14 @@
|
|
1827
1985
|
return r;
|
1828
1986
|
};
|
1829
1987
|
|
1830
|
-
function detectXType(series, noDatetime) {
|
1831
|
-
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)) {
|
1832
1996
|
return "number";
|
1833
1997
|
} else if (!noDatetime && detectXTypeWithFunction(series, isDate)) {
|
1834
1998
|
return "datetime";
|
@@ -1880,12 +2044,18 @@
|
|
1880
2044
|
chart.hideLegend = false;
|
1881
2045
|
}
|
1882
2046
|
|
1883
|
-
|
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));
|
1884
2055
|
|
1885
2056
|
// right format
|
1886
|
-
series = copySeries(series);
|
1887
2057
|
for (i = 0; i < series.length; i++) {
|
1888
|
-
series[i].data = formatSeriesData(
|
2058
|
+
series[i].data = formatSeriesData(series[i].data, chart.xtype);
|
1889
2059
|
}
|
1890
2060
|
|
1891
2061
|
return series;
|
@@ -1970,6 +2140,8 @@
|
|
1970
2140
|
var sep = this.dataSource.indexOf("?") === -1 ? "?" : "&";
|
1971
2141
|
var url = this.dataSource + sep + "_=" + (new Date()).getTime();
|
1972
2142
|
fetchDataSource(this, url);
|
2143
|
+
} else if (typeof this.dataSource === "function") {
|
2144
|
+
fetchDataSource(this, this.dataSource);
|
1973
2145
|
}
|
1974
2146
|
};
|
1975
2147
|
|
@@ -1978,8 +2150,8 @@
|
|
1978
2150
|
|
1979
2151
|
var refresh = this.options.refresh;
|
1980
2152
|
|
1981
|
-
if (refresh && typeof this.dataSource !== "string") {
|
1982
|
-
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");
|
1983
2155
|
}
|
1984
2156
|
|
1985
2157
|
if (!this.intervalId) {
|
@@ -2289,4 +2461,4 @@
|
|
2289
2461
|
|
2290
2462
|
return Chartkick;
|
2291
2463
|
|
2292
|
-
}));
|
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.2
|
4
|
+
version: 3.3.2
|
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-07-24 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
|