chartkick 3.2.1 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|