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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 82cdbb6b87fdf0a3c87795d5c28eb6eea52c2119
4
- data.tar.gz: 3ffaddfafdd92df4ca5d71ebfc077fa4951301dd
3
+ metadata.gz: 31531f1eb7383e7a1d3a2a38a310bc278f8217f6
4
+ data.tar.gz: d8428bfeb19b0075d09abc12402e9df9bec763ea
5
5
  SHA512:
6
- metadata.gz: 72048eaf74b2d83f1dfb46626eae9a351c1dfdd2f71ac42df9a84c7c66e9c6a4944689698eeff74c87b7f0e1e13eea4ef42270c185ff02c147c5efeed9003c9a
7
- data.tar.gz: 176fe037e0ec8e0f149e73e267cc8cb0656709576ba33addca4494d1b64346e67316fac2f69a0d9631a69f5873d9dc360410ecdbf07cf240dccfd2423d226253
6
+ metadata.gz: 5f38b97716209f4e3f8b412d40325a86a644669852e86e5f6ebe0b589d51806dd608b47110d3b53f86102894ede129cd8594e32476cfd17386ae2d9104dd7915
7
+ data.tar.gz: 1bd3ab66e1615588a03308bd537e2216baf8c78229e07b39080ec6d57f11493941f266ba006d388e0ff0ac028de864f8a79f6d288c0f84d7785d45db1765b6b0
@@ -1,3 +1,10 @@
1
+ ## 2.0.0
2
+
3
+ - Chart.js is now the default adapter - yay open source!
4
+ - Axis types are automatically detected - no need for `discrete: true`
5
+ - Better date support
6
+ - New JavaScript API
7
+
1
8
  ## 1.5.2
2
9
 
3
10
  - Fixed Sprockets error
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
- Works with Rails, Sinatra and most browsers (including IE 6)
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
- * v1.5.1
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 adapters = [];
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
- if (matches = input.match(ISO8601_PATTERN)) {
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 (config.smarterDates && (matches = n.match(DATE_PATTERN))) {
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
- var HighchartsAdapter = new function () {
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
- var chartType = chartType || "column";
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
- var GoogleChartsAdapter = new function () {
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
- var ChartjsAdapter = new function () {
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 (var j = 0; j < series.length; j++) {
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 (var j = 0; j < series.length; j++) {
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 (var i = 0; i < series.length; i++) {
949
- var s = series[i];
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 && day) {
1004
- options.scales.xAxes[0].time.tooltipFormat = "ll";
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 = jsOptions(chart.data, chart.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.push(ChartjsAdapter);
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
- if (adapters.length == 0) {
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 d.getMilliseconds() + d.getSeconds() + d.getMinutes() + d.getHours() === 0;
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 (config.smarterDiscrete && (opts.discrete === null || opts.discrete === undefined)) {
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
- window.Chartkick = Chartkick;
1347
+ if (typeof module === "object" && typeof module.exports === "object") {
1348
+ module.exports = Chartkick;
1349
+ } else {
1350
+ window.Chartkick = Chartkick;
1351
+ }
1280
1352
  }(window));
@@ -1,3 +1,3 @@
1
1
  module Chartkick
2
- VERSION = "1.5.2"
2
+ VERSION = "2.0.0"
3
3
  end