chartkick 1.5.2 → 2.0.0
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 +7 -0
- data/README.md +45 -13
- data/app/assets/javascripts/chartkick.js +104 -32
- data/lib/chartkick/version.rb +1 -1
- data/vendor/assets/javascripts/Chart.bundle.js +10122 -9143
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31531f1eb7383e7a1d3a2a38a310bc278f8217f6
|
4
|
+
data.tar.gz: d8428bfeb19b0075d09abc12402e9df9bec763ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f38b97716209f4e3f8b412d40325a86a644669852e86e5f6ebe0b589d51806dd608b47110d3b53f86102894ede129cd8594e32476cfd17386ae2d9104dd7915
|
7
|
+
data.tar.gz: 1bd3ab66e1615588a03308bd537e2216baf8c78229e07b39080ec6d57f11493941f266ba006d388e0ff0ac028de864f8a79f6d288c0f84d7785d45db1765b6b0
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,7 @@ Create beautiful JavaScript charts with one line of Ruby. No more fighting with
|
|
4
4
|
|
5
5
|
[See it in action](http://ankane.github.io/chartkick/)
|
6
6
|
|
7
|
-
|
7
|
+
**Chartkick 2.0 was just released!** See [instructions for upgrading](#20)
|
8
8
|
|
9
9
|
:two_hearts: A perfect companion to [groupdate](https://github.com/ankane/groupdate), [hightop](https://github.com/ankane/hightop), and [active_median](https://github.com/ankane/active_median)
|
10
10
|
|
@@ -42,19 +42,19 @@ Area chart
|
|
42
42
|
<%= area_chart Visit.group_by_minute(:created_at).maximum(:load_time) %>
|
43
43
|
```
|
44
44
|
|
45
|
-
Scatter chart
|
45
|
+
Scatter chart - *Google Charts and Highcharts*
|
46
46
|
|
47
47
|
```erb
|
48
48
|
<%= scatter_chart City.pluck(:size, :population) %>
|
49
49
|
```
|
50
50
|
|
51
|
-
Geo chart
|
51
|
+
Geo chart - *Google Charts*
|
52
52
|
|
53
53
|
```erb
|
54
54
|
<%= geo_chart Medal.group(:country).count %>
|
55
55
|
```
|
56
56
|
|
57
|
-
Timeline
|
57
|
+
Timeline - *Google Charts*
|
58
58
|
|
59
59
|
```erb
|
60
60
|
<%= timeline [
|
@@ -226,6 +226,15 @@ Next, choose your charting library.
|
|
226
226
|
|
227
227
|
**Note:** In the instructions below, `application.js` must be included **before** the helper methods in your views, unless using the `:content_for` option.
|
228
228
|
|
229
|
+
#### Chart.js
|
230
|
+
|
231
|
+
In `application.js`, add:
|
232
|
+
|
233
|
+
```js
|
234
|
+
//= require Chart.bundle
|
235
|
+
//= require chartkick
|
236
|
+
```
|
237
|
+
|
229
238
|
#### Google Charts
|
230
239
|
|
231
240
|
In `application.js`, add:
|
@@ -253,15 +262,6 @@ In `application.js`, add:
|
|
253
262
|
|
254
263
|
Works with Highcharts 2.1+
|
255
264
|
|
256
|
-
#### Chart.js (in beta)
|
257
|
-
|
258
|
-
In `application.js`, add:
|
259
|
-
|
260
|
-
```js
|
261
|
-
//= require Chart.bundle
|
262
|
-
//= require chartkick
|
263
|
-
```
|
264
|
-
|
265
265
|
### For Rails 2.3 and 3.0
|
266
266
|
|
267
267
|
You must include `chartkick.js` manually. [Download it here](https://raw.github.com/ankane/chartkick/master/app/assets/javascripts/chartkick.js)
|
@@ -301,10 +301,42 @@ To specify a language for Google Charts, add:
|
|
301
301
|
|
302
302
|
**before** the JavaScript files.
|
303
303
|
|
304
|
+
## JavaScript API
|
305
|
+
|
306
|
+
Access a chart with:
|
307
|
+
|
308
|
+
```javascript
|
309
|
+
var chart = Chartkick.charts["chart-id"];
|
310
|
+
```
|
311
|
+
|
312
|
+
Get the underlying chart object with:
|
313
|
+
|
314
|
+
```javascript
|
315
|
+
chart.getChartObject();
|
316
|
+
```
|
317
|
+
|
318
|
+
You can also use:
|
319
|
+
|
320
|
+
```javascript
|
321
|
+
chart.getElement();
|
322
|
+
chart.getData();
|
323
|
+
chart.getOptions();
|
324
|
+
```
|
325
|
+
|
304
326
|
## No Ruby? No Problem
|
305
327
|
|
306
328
|
Check out [chartkick.js](https://github.com/ankane/chartkick.js)
|
307
329
|
|
330
|
+
## Upgrading
|
331
|
+
|
332
|
+
### 2.0
|
333
|
+
|
334
|
+
Breaking changes
|
335
|
+
|
336
|
+
- Chart.js is now the default adapter if multiple are loaded - yay open source!
|
337
|
+
- Axis types are automatically detected - no need for `discrete: true`
|
338
|
+
- Better date support - dates are no longer treated as UTC
|
339
|
+
|
308
340
|
## Credits
|
309
341
|
|
310
342
|
Chartkick uses [iso8601.js](https://github.com/Do/iso8601.js) to parse dates and times.
|
@@ -2,7 +2,7 @@
|
|
2
2
|
* Chartkick.js
|
3
3
|
* Create beautiful JavaScript charts with minimal code
|
4
4
|
* https://github.com/ankane/chartkick.js
|
5
|
-
*
|
5
|
+
* v2.0.0
|
6
6
|
* MIT License
|
7
7
|
*/
|
8
8
|
|
@@ -14,7 +14,7 @@
|
|
14
14
|
var config = window.Chartkick || {};
|
15
15
|
var Chartkick, ISO8601_PATTERN, DECIMAL_SEPARATOR, adapters = [];
|
16
16
|
var DATE_PATTERN = /^(\d\d\d\d)(\-)?(\d\d)(\-)?(\d\d)$/i;
|
17
|
-
var
|
17
|
+
var GoogleChartsAdapter, HighchartsAdapter, ChartjsAdapter;
|
18
18
|
|
19
19
|
// helpers
|
20
20
|
|
@@ -68,7 +68,8 @@
|
|
68
68
|
if (type !== '[object String]') {
|
69
69
|
return;
|
70
70
|
}
|
71
|
-
|
71
|
+
matches = input.match(ISO8601_PATTERN);
|
72
|
+
if (matches) {
|
72
73
|
year = parseInt(matches[1], 10);
|
73
74
|
month = parseInt(matches[3], 10) - 1;
|
74
75
|
day = parseInt(matches[5], 10);
|
@@ -211,7 +212,7 @@
|
|
211
212
|
if (typeof n !== "object") {
|
212
213
|
if (typeof n === "number") {
|
213
214
|
n = new Date(n * 1000); // ms
|
214
|
-
} else if (
|
215
|
+
} else if ((matches = n.match(DATE_PATTERN))) {
|
215
216
|
year = parseInt(matches[1], 10);
|
216
217
|
month = parseInt(matches[3], 10) - 1;
|
217
218
|
day = parseInt(matches[5], 10);
|
@@ -249,7 +250,7 @@
|
|
249
250
|
|
250
251
|
function loadAdapters() {
|
251
252
|
if (!HighchartsAdapter && "Highcharts" in window) {
|
252
|
-
|
253
|
+
HighchartsAdapter = new function () {
|
253
254
|
var Highcharts = window.Highcharts;
|
254
255
|
|
255
256
|
this.name = "highcharts";
|
@@ -385,7 +386,7 @@
|
|
385
386
|
};
|
386
387
|
|
387
388
|
this.renderColumnChart = function (chart, chartType) {
|
388
|
-
|
389
|
+
chartType = chartType || "column";
|
389
390
|
var series = chart.data;
|
390
391
|
var options = jsOptions(series, chart.options), i, j, s, d, rows = [];
|
391
392
|
options.chart.type = chartType;
|
@@ -441,7 +442,7 @@
|
|
441
442
|
adapters.push(HighchartsAdapter);
|
442
443
|
}
|
443
444
|
if (!GoogleChartsAdapter && window.google && window.google.setOnLoadCallback) {
|
444
|
-
|
445
|
+
GoogleChartsAdapter = new function () {
|
445
446
|
var google = window.google;
|
446
447
|
|
447
448
|
this.name = "google";
|
@@ -453,7 +454,7 @@
|
|
453
454
|
var cb, call;
|
454
455
|
for (var i = 0; i < callbacks.length; i++) {
|
455
456
|
cb = callbacks[i];
|
456
|
-
call = google.visualization && ((cb.pack === "corechart" && google.visualization.LineChart) || (cb.pack === "timeline" && google.visualization.Timeline))
|
457
|
+
call = google.visualization && ((cb.pack === "corechart" && google.visualization.LineChart) || (cb.pack === "timeline" && google.visualization.Timeline));
|
457
458
|
if (call) {
|
458
459
|
cb.callback();
|
459
460
|
callbacks.splice(i, 1);
|
@@ -557,7 +558,7 @@
|
|
557
558
|
var setXtitle = function (options, title) {
|
558
559
|
options.hAxis.title = title;
|
559
560
|
options.hAxis.titleTextStyle.italic = false;
|
560
|
-
}
|
561
|
+
};
|
561
562
|
|
562
563
|
var setYtitle = function (options, title) {
|
563
564
|
options.vAxis.title = title;
|
@@ -769,7 +770,7 @@
|
|
769
770
|
adapters.push(GoogleChartsAdapter);
|
770
771
|
}
|
771
772
|
if (!ChartjsAdapter && "Chart" in window) {
|
772
|
-
|
773
|
+
ChartjsAdapter = new function () {
|
773
774
|
var Chart = window.Chart;
|
774
775
|
|
775
776
|
this.name = "chartjs";
|
@@ -832,6 +833,16 @@
|
|
832
833
|
options.scales.yAxes[0].ticks.max = max;
|
833
834
|
};
|
834
835
|
|
836
|
+
var setBarMin = function (options, min) {
|
837
|
+
if (min !== null) {
|
838
|
+
options.scales.xAxes[0].ticks.min = min;
|
839
|
+
}
|
840
|
+
};
|
841
|
+
|
842
|
+
var setBarMax = function (options, max) {
|
843
|
+
options.scales.xAxes[0].ticks.max = max;
|
844
|
+
};
|
845
|
+
|
835
846
|
var setStacked = function (options, stacked) {
|
836
847
|
options.scales.xAxes[0].stacked = !!stacked;
|
837
848
|
options.scales.yAxes[0].stacked = !!stacked;
|
@@ -889,6 +900,8 @@
|
|
889
900
|
var dayOfWeek;
|
890
901
|
var month = true;
|
891
902
|
var year = true;
|
903
|
+
var hour = true;
|
904
|
+
var minute = true;
|
892
905
|
var detectType = (chartType === "line" || chartType === "area") && !chart.options.discrete;
|
893
906
|
|
894
907
|
var series = chart.data;
|
@@ -917,11 +930,10 @@
|
|
917
930
|
}
|
918
931
|
|
919
932
|
var rows2 = [];
|
920
|
-
for (
|
933
|
+
for (j = 0; j < series.length; j++) {
|
921
934
|
rows2.push([]);
|
922
935
|
}
|
923
936
|
|
924
|
-
var day = true;
|
925
937
|
var value;
|
926
938
|
var k;
|
927
939
|
for (k = 0; k < sortedLabels.length; k++) {
|
@@ -936,17 +948,19 @@
|
|
936
948
|
week = week && isWeek(value, dayOfWeek);
|
937
949
|
month = month && isMonth(value);
|
938
950
|
year = year && isYear(value);
|
951
|
+
hour = hour && isHour(value);
|
952
|
+
minute = minute && isMinute(value);
|
939
953
|
} else {
|
940
954
|
value = i;
|
941
955
|
}
|
942
956
|
labels.push(value);
|
943
|
-
for (
|
944
|
-
rows2[j].push(rows[i][j])
|
957
|
+
for (j = 0; j < series.length; j++) {
|
958
|
+
rows2[j].push(rows[i][j]);
|
945
959
|
}
|
946
960
|
}
|
947
961
|
|
948
|
-
for (
|
949
|
-
|
962
|
+
for (i = 0; i < series.length; i++) {
|
963
|
+
s = series[i];
|
950
964
|
|
951
965
|
var backgroundColor = chartType !== "line" ? addOpacity(colors[i], 0.5) : colors[i];
|
952
966
|
|
@@ -989,6 +1003,13 @@
|
|
989
1003
|
} else if (day || timeDiff > 10) {
|
990
1004
|
options.scales.xAxes[0].time.unit = "day";
|
991
1005
|
step = 1;
|
1006
|
+
} else if (hour) {
|
1007
|
+
options.scales.xAxes[0].time.unit = "hour";
|
1008
|
+
step = 1 / 24.0;
|
1009
|
+
} else if (minute) {
|
1010
|
+
options.scales.xAxes[0].time.displayFormats = {minute: "h:mm a"};
|
1011
|
+
options.scales.xAxes[0].time.unit = "minute";
|
1012
|
+
step = 1 / 24.0 / 60.0;
|
992
1013
|
}
|
993
1014
|
|
994
1015
|
if (step && timeDiff > 0) {
|
@@ -1000,8 +1021,14 @@
|
|
1000
1021
|
}
|
1001
1022
|
}
|
1002
1023
|
|
1003
|
-
if (!options.scales.xAxes[0].time.tooltipFormat
|
1004
|
-
|
1024
|
+
if (!options.scales.xAxes[0].time.tooltipFormat) {
|
1025
|
+
if (day) {
|
1026
|
+
options.scales.xAxes[0].time.tooltipFormat = "ll";
|
1027
|
+
} else if (hour) {
|
1028
|
+
options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
|
1029
|
+
} else if (minute) {
|
1030
|
+
options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
|
1031
|
+
}
|
1005
1032
|
}
|
1006
1033
|
}
|
1007
1034
|
|
@@ -1019,6 +1046,11 @@
|
|
1019
1046
|
// TODO fix area stacked
|
1020
1047
|
// areaOptions.stacked = true;
|
1021
1048
|
}
|
1049
|
+
// fix for https://github.com/chartjs/Chart.js/issues/2441
|
1050
|
+
if (!chart.options.max && allZeros(chart.data)) {
|
1051
|
+
chart.options.max = 1;
|
1052
|
+
}
|
1053
|
+
|
1022
1054
|
var options = jsOptions(chart.data, merge(areaOptions, chart.options));
|
1023
1055
|
|
1024
1056
|
var data = createDataTable(chart, options, chartType || "line");
|
@@ -1026,7 +1058,7 @@
|
|
1026
1058
|
options.scales.xAxes[0].type = chart.options.discrete ? "category" : "time";
|
1027
1059
|
|
1028
1060
|
drawChart(chart, "line", data, options);
|
1029
|
-
}
|
1061
|
+
};
|
1030
1062
|
|
1031
1063
|
this.renderPieChart = function (chart) {
|
1032
1064
|
var options = merge(baseOptions, chart.options.library || {});
|
@@ -1050,14 +1082,19 @@
|
|
1050
1082
|
};
|
1051
1083
|
|
1052
1084
|
drawChart(chart, "pie", data, options);
|
1053
|
-
}
|
1085
|
+
};
|
1054
1086
|
|
1055
1087
|
this.renderColumnChart = function (chart, chartType) {
|
1056
|
-
var options
|
1088
|
+
var options;
|
1089
|
+
if (chartType === "bar") {
|
1090
|
+
options = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setBarMin, setBarMax, setStacked)(chart.data, chart.options);
|
1091
|
+
} else {
|
1092
|
+
options = jsOptions(chart.data, chart.options);
|
1093
|
+
}
|
1057
1094
|
var data = createDataTable(chart, options, "column");
|
1058
1095
|
setLabelSize(chart, data, options);
|
1059
1096
|
drawChart(chart, (chartType === "bar" ? "horizontalBar" : "bar"), data, options);
|
1060
|
-
}
|
1097
|
+
};
|
1061
1098
|
|
1062
1099
|
var self = this;
|
1063
1100
|
|
@@ -1066,11 +1103,11 @@
|
|
1066
1103
|
};
|
1067
1104
|
|
1068
1105
|
this.renderBarChart = function (chart) {
|
1069
|
-
self.renderColumnChart(chart, "bar")
|
1070
|
-
}
|
1071
|
-
}
|
1106
|
+
self.renderColumnChart(chart, "bar");
|
1107
|
+
};
|
1108
|
+
};
|
1072
1109
|
|
1073
|
-
adapters.
|
1110
|
+
adapters.unshift(ChartjsAdapter);
|
1074
1111
|
}
|
1075
1112
|
}
|
1076
1113
|
|
@@ -1081,9 +1118,7 @@
|
|
1081
1118
|
fnName = "render" + chartType;
|
1082
1119
|
adapterName = chart.options.adapter;
|
1083
1120
|
|
1084
|
-
|
1085
|
-
loadAdapters();
|
1086
|
-
}
|
1121
|
+
loadAdapters();
|
1087
1122
|
|
1088
1123
|
for (i = 0; i < adapters.length; i++) {
|
1089
1124
|
adapter = adapters[i];
|
@@ -1119,8 +1154,16 @@
|
|
1119
1154
|
return r;
|
1120
1155
|
};
|
1121
1156
|
|
1157
|
+
function isMinute(d) {
|
1158
|
+
return d.getMilliseconds() === 0 && d.getSeconds() === 0;
|
1159
|
+
}
|
1160
|
+
|
1161
|
+
function isHour(d) {
|
1162
|
+
return isMinute(d) && d.getMinutes() === 0;
|
1163
|
+
}
|
1164
|
+
|
1122
1165
|
function isDay(d) {
|
1123
|
-
return
|
1166
|
+
return isHour(d) && d.getHours() === 0;
|
1124
1167
|
}
|
1125
1168
|
|
1126
1169
|
function isWeek(d, dayOfWeek) {
|
@@ -1139,6 +1182,19 @@
|
|
1139
1182
|
return !isNaN(toDate(obj)) && toStr(obj).length >= 6;
|
1140
1183
|
}
|
1141
1184
|
|
1185
|
+
function allZeros(data) {
|
1186
|
+
var i, j, d;
|
1187
|
+
for (i = 0; i < data.length; i++) {
|
1188
|
+
d = data[i].data;
|
1189
|
+
for (j = 0; j < d.length; j++) {
|
1190
|
+
if (d[j][1] != 0) {
|
1191
|
+
return false;
|
1192
|
+
}
|
1193
|
+
}
|
1194
|
+
}
|
1195
|
+
return true;
|
1196
|
+
}
|
1197
|
+
|
1142
1198
|
function detectDiscrete(series) {
|
1143
1199
|
var i, j, data;
|
1144
1200
|
for (i = 0; i < series.length; i++) {
|
@@ -1162,7 +1218,7 @@
|
|
1162
1218
|
} else {
|
1163
1219
|
opts.hideLegend = false;
|
1164
1220
|
}
|
1165
|
-
if (
|
1221
|
+
if ((opts.discrete === null || opts.discrete === undefined)) {
|
1166
1222
|
opts.discrete = detectDiscrete(series);
|
1167
1223
|
}
|
1168
1224
|
if (opts.discrete) {
|
@@ -1242,6 +1298,18 @@
|
|
1242
1298
|
chart.element = element;
|
1243
1299
|
chart.options = opts || {};
|
1244
1300
|
chart.dataSource = dataSource;
|
1301
|
+
chart.getElement = function () {
|
1302
|
+
return element;
|
1303
|
+
};
|
1304
|
+
chart.getData = function () {
|
1305
|
+
return chart.data;
|
1306
|
+
};
|
1307
|
+
chart.getOptions = function () {
|
1308
|
+
return opts || {};
|
1309
|
+
};
|
1310
|
+
chart.getChartObject = function () {
|
1311
|
+
return chart.chart;
|
1312
|
+
};
|
1245
1313
|
Chartkick.charts[element.id] = chart;
|
1246
1314
|
fetchDataSource(chart, callback);
|
1247
1315
|
}
|
@@ -1276,5 +1344,9 @@
|
|
1276
1344
|
charts: {}
|
1277
1345
|
};
|
1278
1346
|
|
1279
|
-
|
1347
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
1348
|
+
module.exports = Chartkick;
|
1349
|
+
} else {
|
1350
|
+
window.Chartkick = Chartkick;
|
1351
|
+
}
|
1280
1352
|
}(window));
|
data/lib/chartkick/version.rb
CHANGED