chartkick 1.2.2 → 1.2.3

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: ca7e47f1dbaaa98f3c7e1ca1e4dc52ab6cb4262b
4
- data.tar.gz: de76a0f1276d12212b37f2a8366649ff22f187e8
3
+ metadata.gz: c3d82466b6703318eaead4b787e2029ed81b6419
4
+ data.tar.gz: 6a94782f3c4fbfd27171e03e89e1288e97221287
5
5
  SHA512:
6
- metadata.gz: 7d4f116d8ac99364ef648f5ee4f9416327c8ea77e647d5606028fe549c2c771c9245676b09b8032ac2df9b9b41e3bc47209911a7daecc562c73742077af8be96
7
- data.tar.gz: c67bdceab693294cb60867edaf7d467a0ea2c46f05791bc1f294b1b35ace97aa9290851117e90eeda336ac0ebe08a8e7cec0af4bd09e525effc496ca19053385
6
+ metadata.gz: b14d7a3cd54eb4d67af1efa3776c7f9c5bf6c07c8d8d22aff8294312236095b1ab5de4850c330d938aae2f0b21108c31aacad0da73a0248b190da79fbf637884
7
+ data.tar.gz: ce3df7336aa518bc1c3859c7e113607bd851779c5efc23b483f1154fdc2913d207ab0fffc6ed86b82f9743a1d656f4034bba4e67520769c2bff06d851c006684
@@ -1,3 +1,8 @@
1
+ ## 1.2.3
2
+
3
+ - Added geo chart
4
+ - Added `discrete` option
5
+
1
6
  ## 1.2.2
2
7
 
3
8
  - Added global `content_for` option
data/README.md CHANGED
@@ -19,19 +19,19 @@ Line chart
19
19
  Pie chart
20
20
 
21
21
  ```erb
22
- <%= pie_chart Goal.group("name").count %>
22
+ <%= pie_chart Goal.group(:name).count %>
23
23
  ```
24
24
 
25
25
  Column chart
26
26
 
27
27
  ```erb
28
- <%= column_chart Task.group_by_hour_of_day(:created_at).count %>
28
+ <%= column_chart Task.group_by_hour_of_day(:created_at, format: "%l %P").count %>
29
29
  ```
30
30
 
31
31
  Bar chart
32
32
 
33
33
  ```erb
34
- <%= bar_chart Shirt.group("size").sum(:price) %>
34
+ <%= bar_chart Shirt.group(:size).sum(:price) %>
35
35
  ```
36
36
 
37
37
  Area chart
@@ -40,11 +40,17 @@ Area chart
40
40
  <%= area_chart Visit.group_by_minute(:created_at).maximum(:load_time) %>
41
41
  ```
42
42
 
43
+ Geo chart
44
+
45
+ ```erb
46
+ <%= geo_chart Medal.group(:country).count %>
47
+ ```
48
+
43
49
  Multiple series (except pie chart)
44
50
 
45
51
  ```erb
46
52
  <%= line_chart @goals.map{|goal|
47
- {:name => goal.name, :data => goal.feats.group_by_week(:created_at).count }
53
+ {name: goal.name, data: goal.feats.group_by_week(:created_at).count}
48
54
  } %>
49
55
  ```
50
56
 
@@ -61,43 +67,49 @@ And in your controller, pass the data as JSON.
61
67
  ```ruby
62
68
  class ChartsController < ApplicationController
63
69
  def completed_tasks
64
- render :json => Task.group_by_day(:completed_at).count
70
+ render json: Task.group_by_day(:completed_at).count
65
71
  end
66
72
  end
67
73
  ```
68
74
 
69
- **Note:** This feature requires jQuery at the moment.
75
+ **Note:** This feature requires [jQuery](http://jquery.com/) or [Zepto](http://zeptojs.com/) at the moment.
70
76
 
71
77
  ### Options
72
78
 
73
79
  Id and height
74
80
 
75
81
  ```erb
76
- <%= line_chart data, :id => "users-chart", :height => "500px" %>
82
+ <%= line_chart data, id: "users-chart", height: "500px" %>
77
83
  ```
78
84
 
79
85
  Min and max values (except pie chart)
80
86
 
81
87
  ```erb
82
- <%= line_chart data, :min => 1000, :max => 5000 %>
88
+ <%= line_chart data, min: 1000, max: 5000 %>
83
89
  ```
84
90
 
85
91
  Stacked columns or bars
86
92
 
87
93
  ```erb
88
- <%= column_chart data, :stacked => true %>
94
+ <%= column_chart data, stacked: true %>
95
+ ```
96
+
97
+ Discrete axis
98
+
99
+ ```erb
100
+ <%= line_chart data, discrete: true %>
89
101
  ```
90
102
 
91
103
  You can pass options directly to the charting library with:
92
104
 
93
105
  ```erb
94
- <%= line_chart data, :library => {:backgroundColor => "#eee"} %>
106
+ <%= line_chart data, library: {backgroundColor: "#eee"} %>
95
107
  ```
96
108
 
97
109
  You can also pass a content_for option, which will put the javascript in a content block. This is great for including all of your javascript at the bottom of the page.
98
110
 
99
111
  ```erb
100
- <%= line_chart data, :content_for => :charts_js %>
112
+ <%= line_chart data, content_for: :charts_js %>
101
113
  ```
102
114
  Then, in your layout:
103
115
 
@@ -125,8 +137,8 @@ For multiple series, use the format
125
137
 
126
138
  ```erb
127
139
  <%= line_chart [
128
- {:name => "Series A", :data => series_a},
129
- {:name => "Series B", :data => series_b}
140
+ {name: "Series A", data: series_a},
141
+ {name: "Series B", data: series_b}
130
142
  ] %>
131
143
  ```
132
144
 
@@ -2,21 +2,18 @@
2
2
  * Chartkick.js
3
3
  * Create beautiful Javascript charts with minimal code
4
4
  * https://github.com/ankane/chartkick.js
5
- * v1.1.1
5
+ * v1.2.1
6
6
  * MIT License
7
7
  */
8
8
 
9
9
  /*jslint browser: true, indent: 2, plusplus: true, vars: true */
10
- /*global google, Highcharts, $*/
11
10
 
12
- (function () {
11
+ (function (window) {
13
12
  'use strict';
14
13
 
15
- var Chartkick, ISO8601_PATTERN, DECIMAL_SEPARATOR, defaultOptions, hideLegend,
16
- setMin, setMax, setStacked, jsOptions, loaded, waitForLoaded, setBarMin, setBarMax, createDataTable, resize;
14
+ var Chartkick, ISO8601_PATTERN, DECIMAL_SEPARATOR, adapters = [];
17
15
 
18
- // only functions that need defined specific to charting library
19
- var renderLineChart, renderPieChart, renderColumnChart, renderBarChart, renderAreaChart;
16
+ var $ = window.jQuery || window.Zepto || window.$;
20
17
 
21
18
  // helpers
22
19
 
@@ -153,7 +150,7 @@
153
150
  }
154
151
 
155
152
  function getJSON(element, url, success) {
156
- jQuery.ajax({
153
+ $.ajax({
157
154
  dataType: "json",
158
155
  url: url,
159
156
  success: success,
@@ -164,22 +161,24 @@
164
161
  });
165
162
  }
166
163
 
167
- function errorCatcher(element, data, opts, callback) {
164
+ function errorCatcher(chart, callback) {
168
165
  try {
169
- callback(element, data, opts);
166
+ callback(chart);
170
167
  } catch (err) {
171
- chartError(element, err.message);
168
+ chartError(chart.element, err.message);
172
169
  throw err;
173
170
  }
174
171
  }
175
172
 
176
- function fetchDataSource(element, dataSource, opts, callback) {
177
- if (typeof dataSource === "string") {
178
- getJSON(element, dataSource, function (data, textStatus, jqXHR) {
179
- errorCatcher(element, data, opts, callback);
173
+ function fetchDataSource(chart, callback) {
174
+ if (typeof chart.dataSource === "string") {
175
+ getJSON(chart.element, chart.dataSource, function (data, textStatus, jqXHR) {
176
+ chart.data = data;
177
+ errorCatcher(chart, callback);
180
178
  });
181
179
  } else {
182
- errorCatcher(element, dataSource, opts, callback);
180
+ chart.data = chart.dataSource;
181
+ errorCatcher(chart, callback);
183
182
  }
184
183
  }
185
184
 
@@ -225,371 +224,416 @@
225
224
  }
226
225
 
227
226
  if ("Highcharts" in window) {
228
-
229
- defaultOptions = {
230
- chart: {},
231
- xAxis: {
232
- labels: {
233
- style: {
234
- fontSize: "12px"
227
+ var HighchartsAdapter = new function () {
228
+ var Highcharts = window.Highcharts;
229
+
230
+ var defaultOptions = {
231
+ chart: {},
232
+ xAxis: {
233
+ labels: {
234
+ style: {
235
+ fontSize: "12px"
236
+ }
235
237
  }
236
- }
237
- },
238
- yAxis: {
238
+ },
239
+ yAxis: {
240
+ title: {
241
+ text: null
242
+ },
243
+ labels: {
244
+ style: {
245
+ fontSize: "12px"
246
+ }
247
+ }
248
+ },
239
249
  title: {
240
250
  text: null
241
251
  },
242
- labels: {
252
+ credits: {
253
+ enabled: false
254
+ },
255
+ legend: {
256
+ borderWidth: 0
257
+ },
258
+ tooltip: {
243
259
  style: {
244
260
  fontSize: "12px"
245
261
  }
262
+ },
263
+ plotOptions: {
264
+ areaspline: {},
265
+ series: {
266
+ marker: {}
267
+ }
246
268
  }
247
- },
248
- title: {
249
- text: null
250
- },
251
- credits: {
252
- enabled: false
253
- },
254
- legend: {
255
- borderWidth: 0
256
- },
257
- tooltip: {
258
- style: {
259
- fontSize: "12px"
269
+ };
270
+
271
+ var hideLegend = function (options) {
272
+ options.legend.enabled = false;
273
+ };
274
+
275
+ var setMin = function (options, min) {
276
+ options.yAxis.min = min;
277
+ };
278
+
279
+ var setMax = function (options, max) {
280
+ options.yAxis.max = max;
281
+ };
282
+
283
+ var setStacked = function (options) {
284
+ options.plotOptions.series.stacking = "normal";
285
+ };
286
+
287
+ var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked);
288
+
289
+ this.renderLineChart = function (chart, chartType) {
290
+ chartType = chartType || "spline";
291
+ var chartOptions = {};
292
+ if (chartType === "areaspline") {
293
+ chartOptions = {
294
+ plotOptions: {
295
+ areaspline: {
296
+ stacking: "normal"
297
+ },
298
+ series: {
299
+ marker: {
300
+ enabled: false
301
+ }
302
+ }
303
+ }
304
+ };
260
305
  }
261
- },
262
- plotOptions: {
263
- areaspline: {},
264
- series: {
265
- marker: {}
306
+ var options = jsOptions(chart.data, chart.options, chartOptions), data, i, j;
307
+ options.xAxis.type = chart.options.discrete ? "category" : "datetime";
308
+ options.chart.type = chartType;
309
+ options.chart.renderTo = chart.element.id;
310
+
311
+ var series = chart.data;
312
+ for (i = 0; i < series.length; i++) {
313
+ data = series[i].data;
314
+ if (!chart.options.discrete) {
315
+ for (j = 0; j < data.length; j++) {
316
+ data[j][0] = data[j][0].getTime();
317
+ }
318
+ }
319
+ series[i].marker = {symbol: "circle"};
266
320
  }
267
- }
268
- };
269
-
270
- hideLegend = function (options) {
271
- options.legend.enabled = false;
272
- };
273
-
274
- setMin = function (options, min) {
275
- options.yAxis.min = min;
276
- };
277
-
278
- setMax = function (options, max) {
279
- options.yAxis.max = max;
280
- };
281
-
282
- setStacked = function (options) {
283
- options.plotOptions.series.stacking = "normal";
284
- };
285
-
286
- jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked);
287
-
288
- renderLineChart = function (element, series, opts, chartType) {
289
- chartType = chartType || "spline";
290
- var chartOptions = {};
291
- if (chartType === "areaspline") {
292
- chartOptions = {
293
- plotOptions: {
294
- areaspline: {
295
- stacking: "normal"
296
- },
297
- series: {
298
- marker: {
299
- enabled: false
300
- }
321
+ options.series = series;
322
+ new Highcharts.Chart(options);
323
+ };
324
+
325
+ this.renderPieChart = function (chart) {
326
+ var options = merge(defaultOptions, chart.options.library || {});
327
+ options.chart.renderTo = chart.element.id;
328
+ options.series = [{
329
+ type: "pie",
330
+ name: "Value",
331
+ data: chart.data
332
+ }];
333
+ new Highcharts.Chart(options);
334
+ };
335
+
336
+ this.renderColumnChart = function (chart, chartType) {
337
+ var chartType = chartType || "column";
338
+ var series = chart.data;
339
+ var options = jsOptions(series, chart.options), i, j, s, d, rows = [];
340
+ options.chart.type = chartType;
341
+ options.chart.renderTo = chart.element.id;
342
+
343
+ for (i = 0; i < series.length; i++) {
344
+ s = series[i];
345
+
346
+ for (j = 0; j < s.data.length; j++) {
347
+ d = s.data[j];
348
+ if (!rows[d[0]]) {
349
+ rows[d[0]] = new Array(series.length);
301
350
  }
351
+ rows[d[0]][i] = d[1];
302
352
  }
303
- };
304
- }
305
- var options = jsOptions(series, opts, chartOptions), data, i, j;
306
- options.xAxis.type = "datetime";
307
- options.chart.type = chartType;
308
- options.chart.renderTo = element.id;
309
-
310
- for (i = 0; i < series.length; i++) {
311
- data = series[i].data;
312
- for (j = 0; j < data.length; j++) {
313
- data[j][0] = data[j][0].getTime();
314
353
  }
315
- series[i].marker = {symbol: "circle"};
316
- }
317
- options.series = series;
318
- new Highcharts.Chart(options);
319
- };
320
-
321
- renderPieChart = function (element, series, opts) {
322
- var options = merge(defaultOptions, opts.library || {});
323
- options.chart.renderTo = element.id;
324
- options.series = [{
325
- type: "pie",
326
- name: "Value",
327
- data: series
328
- }];
329
- new Highcharts.Chart(options);
330
- };
331
-
332
- renderColumnChart = function (element, series, opts, chartType) {
333
- chartType = chartType || "column";
334
- var options = jsOptions(series, opts), i, j, s, d, rows = [];
335
- options.chart.type = chartType;
336
- options.chart.renderTo = element.id;
337
354
 
338
- for (i = 0; i < series.length; i++) {
339
- s = series[i];
340
-
341
- for (j = 0; j < s.data.length; j++) {
342
- d = s.data[j];
343
- if (!rows[d[0]]) {
344
- rows[d[0]] = new Array(series.length);
355
+ var categories = [];
356
+ for (i in rows) {
357
+ if (rows.hasOwnProperty(i)) {
358
+ categories.push(i);
345
359
  }
346
- rows[d[0]][i] = d[1];
347
360
  }
348
- }
361
+ options.xAxis.categories = categories;
349
362
 
350
- var categories = [];
351
- for (i in rows) {
352
- if (rows.hasOwnProperty(i)) {
353
- categories.push(i);
354
- }
355
- }
356
- options.xAxis.categories = categories;
363
+ var newSeries = [];
364
+ for (i = 0; i < series.length; i++) {
365
+ d = [];
366
+ for (j = 0; j < categories.length; j++) {
367
+ d.push(rows[categories[j]][i] || 0);
368
+ }
357
369
 
358
- var newSeries = [];
359
- for (i = 0; i < series.length; i++) {
360
- d = [];
361
- for (j = 0; j < categories.length; j++) {
362
- d.push(rows[categories[j]][i] || 0);
370
+ newSeries.push({
371
+ name: series[i].name,
372
+ data: d
373
+ });
363
374
  }
375
+ options.series = newSeries;
364
376
 
365
- newSeries.push({
366
- name: series[i].name,
367
- data: d
368
- });
369
- }
370
- options.series = newSeries;
377
+ new Highcharts.Chart(options);
378
+ };
371
379
 
372
- new Highcharts.Chart(options);
373
- };
380
+ var self = this;
374
381
 
375
- renderBarChart = function (element, series, opts) {
376
- renderColumnChart(element, series, opts, "bar");
377
- };
378
-
379
- renderAreaChart = function (element, series, opts) {
380
- renderLineChart(element, series, opts, "areaspline");
381
- };
382
- } else if ("google" in window) { // Google charts
383
- // load from google
384
- loaded = false;
385
- google.setOnLoadCallback(function () {
386
- loaded = true;
387
- });
388
- var loadOptions = {"packages": ["corechart"]};
389
- var config = window.Chartkick || {};
390
- if (config.language) {
391
- loadOptions.language = config.language;
392
- }
393
- google.load("visualization", "1.0", loadOptions);
382
+ this.renderBarChart = function (chart) {
383
+ self.renderColumnChart(chart, "bar");
384
+ };
394
385
 
395
- waitForLoaded = function (callback) {
396
- google.setOnLoadCallback(callback); // always do this to prevent race conditions (watch out for other issues due to this)
397
- if (loaded) {
398
- callback();
399
- }
386
+ this.renderAreaChart = function (chart) {
387
+ self.renderLineChart(chart, "areaspline");
388
+ };
400
389
  };
390
+ adapters.push(HighchartsAdapter);
391
+ }
392
+ if ("google" in window) {
393
+ var GoogleChartsAdapter = new function () {
394
+ var google = window.google;
395
+
396
+ // load from google
397
+ var loaded = false;
398
+ google.setOnLoadCallback(function () {
399
+ loaded = true;
400
+ });
401
+ google.load("visualization", "1.0", {"packages": ["corechart"]});
401
402
 
402
- // Set chart options
403
- defaultOptions = {
404
- chartArea: {},
405
- fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
406
- pointSize: 6,
407
- legend: {
408
- textStyle: {
409
- fontSize: 12,
410
- color: "#444"
411
- },
412
- alignment: "center",
413
- position: "right"
414
- },
415
- curveType: "function",
416
- hAxis: {
417
- textStyle: {
418
- color: "#666",
419
- fontSize: 12
403
+ var waitForLoaded = function (callback) {
404
+ google.setOnLoadCallback(callback); // always do this to prevent race conditions (watch out for other issues due to this)
405
+ if (loaded) {
406
+ callback();
407
+ }
408
+ };
409
+
410
+ // Set chart options
411
+ var defaultOptions = {
412
+ chartArea: {},
413
+ fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
414
+ pointSize: 6,
415
+ legend: {
416
+ textStyle: {
417
+ fontSize: 12,
418
+ color: "#444"
419
+ },
420
+ alignment: "center",
421
+ position: "right"
420
422
  },
421
- gridlines: {
422
- color: "transparent"
423
+ curveType: "function",
424
+ hAxis: {
425
+ textStyle: {
426
+ color: "#666",
427
+ fontSize: 12
428
+ },
429
+ gridlines: {
430
+ color: "transparent"
431
+ },
432
+ baselineColor: "#ccc",
433
+ viewWindow: {}
423
434
  },
424
- baselineColor: "#ccc",
425
- viewWindow: {}
426
- },
427
- vAxis: {
428
- textStyle: {
429
- color: "#666",
430
- fontSize: 12
435
+ vAxis: {
436
+ textStyle: {
437
+ color: "#666",
438
+ fontSize: 12
439
+ },
440
+ baselineColor: "#ccc",
441
+ viewWindow: {}
431
442
  },
432
- baselineColor: "#ccc",
433
- viewWindow: {}
434
- },
435
- tooltip: {
436
- textStyle: {
437
- color: "#666",
438
- fontSize: 12
443
+ tooltip: {
444
+ textStyle: {
445
+ color: "#666",
446
+ fontSize: 12
447
+ }
439
448
  }
440
- }
441
- };
449
+ };
442
450
 
443
- hideLegend = function (options) {
444
- options.legend.position = "none";
445
- };
451
+ var hideLegend = function (options) {
452
+ options.legend.position = "none";
453
+ };
446
454
 
447
- setMin = function (options, min) {
448
- options.vAxis.viewWindow.min = min;
449
- };
455
+ var setMin = function (options, min) {
456
+ options.vAxis.viewWindow.min = min;
457
+ };
450
458
 
451
- setMax = function (options, max) {
452
- options.vAxis.viewWindow.max = max;
453
- };
459
+ var setMax = function (options, max) {
460
+ options.vAxis.viewWindow.max = max;
461
+ };
454
462
 
455
- setBarMin = function (options, min) {
456
- options.hAxis.viewWindow.min = min;
457
- };
463
+ var setBarMin = function (options, min) {
464
+ options.hAxis.viewWindow.min = min;
465
+ };
458
466
 
459
- setBarMax = function (options, max) {
460
- options.hAxis.viewWindow.max = max;
461
- };
462
-
463
- setStacked = function (options) {
464
- options.isStacked = true;
465
- };
466
-
467
- jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked);
467
+ var setBarMax = function (options, max) {
468
+ options.hAxis.viewWindow.max = max;
469
+ };
468
470
 
469
- // cant use object as key
470
- createDataTable = function (series, columnType) {
471
- var data = new google.visualization.DataTable();
472
- data.addColumn(columnType, "");
471
+ var setStacked = function (options) {
472
+ options.isStacked = true;
473
+ };
473
474
 
474
- var i, j, s, d, key, rows = [];
475
- for (i = 0; i < series.length; i++) {
476
- s = series[i];
477
- data.addColumn("number", s.name);
475
+ var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked);
478
476
 
479
- for (j = 0; j < s.data.length; j++) {
480
- d = s.data[j];
481
- key = (columnType === "datetime") ? d[0].getTime() : d[0];
482
- if (!rows[key]) {
483
- rows[key] = new Array(series.length);
477
+ // cant use object as key
478
+ var createDataTable = function (series, columnType) {
479
+ var data = new google.visualization.DataTable();
480
+ data.addColumn(columnType, "");
481
+
482
+ var i, j, s, d, key, rows = [];
483
+ for (i = 0; i < series.length; i++) {
484
+ s = series[i];
485
+ data.addColumn("number", s.name);
486
+
487
+ for (j = 0; j < s.data.length; j++) {
488
+ d = s.data[j];
489
+ key = (columnType === "datetime") ? d[0].getTime() : d[0];
490
+ if (!rows[key]) {
491
+ rows[key] = new Array(series.length);
492
+ }
493
+ rows[key][i] = toFloat(d[1]);
484
494
  }
485
- rows[key][i] = toFloat(d[1]);
486
495
  }
487
- }
488
496
 
489
- var rows2 = [];
490
- for (i in rows) {
491
- if (rows.hasOwnProperty(i)) {
492
- rows2.push([(columnType === "datetime") ? new Date(toFloat(i)) : i].concat(rows[i]));
497
+ var rows2 = [];
498
+ for (i in rows) {
499
+ if (rows.hasOwnProperty(i)) {
500
+ rows2.push([(columnType === "datetime") ? new Date(toFloat(i)) : i].concat(rows[i]));
501
+ }
493
502
  }
494
- }
495
- if (columnType === "datetime") {
496
- rows2.sort(sortByTime);
497
- }
498
- data.addRows(rows2);
499
-
500
- return data;
501
- };
503
+ if (columnType === "datetime") {
504
+ rows2.sort(sortByTime);
505
+ }
506
+ data.addRows(rows2);
502
507
 
503
- resize = function (callback) {
504
- if (window.attachEvent) {
505
- window.attachEvent("onresize", callback);
506
- } else if (window.addEventListener) {
507
- window.addEventListener("resize", callback, true);
508
- }
509
- callback();
510
- };
508
+ return data;
509
+ };
511
510
 
512
- renderLineChart = function (element, series, opts) {
513
- waitForLoaded(function () {
514
- var options = jsOptions(series, opts);
515
- var data = createDataTable(series, "datetime");
516
- var chart = new google.visualization.LineChart(element);
517
- resize(function () {
518
- chart.draw(data, options);
511
+ var resize = function (callback) {
512
+ if (window.attachEvent) {
513
+ window.attachEvent("onresize", callback);
514
+ } else if (window.addEventListener) {
515
+ window.addEventListener("resize", callback, true);
516
+ }
517
+ callback();
518
+ };
519
+
520
+ this.renderLineChart = function (chart) {
521
+ waitForLoaded(function () {
522
+ var options = jsOptions(chart.data, chart.options);
523
+ var data = createDataTable(chart.data, chart.options.discrete ? "string" : "datetime");
524
+ chart.chart = new google.visualization.LineChart(chart.element);
525
+ resize(function () {
526
+ chart.chart.draw(data, options);
527
+ });
519
528
  });
520
- });
521
- };
522
-
523
- renderPieChart = function (element, series, opts) {
524
- waitForLoaded(function () {
525
- var chartOptions = {
526
- chartArea: {
527
- top: "10%",
528
- height: "80%"
529
- }
530
- };
531
- var options = merge(merge(defaultOptions, chartOptions), opts.library || {});
532
-
533
- var data = new google.visualization.DataTable();
534
- data.addColumn("string", "");
535
- data.addColumn("number", "Value");
536
- data.addRows(series);
537
-
538
- var chart = new google.visualization.PieChart(element);
539
- resize(function () {
540
- chart.draw(data, options);
529
+ };
530
+
531
+ this.renderPieChart = function (chart) {
532
+ waitForLoaded(function () {
533
+ var chartOptions = {
534
+ chartArea: {
535
+ top: "10%",
536
+ height: "80%"
537
+ }
538
+ };
539
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
540
+
541
+ var data = new google.visualization.DataTable();
542
+ data.addColumn("string", "");
543
+ data.addColumn("number", "Value");
544
+ data.addRows(chart.data);
545
+
546
+ chart.chart = new google.visualization.PieChart(chart.element);
547
+ resize(function () {
548
+ chart.chart.draw(data, options);
549
+ });
541
550
  });
542
- });
543
- };
544
-
545
- renderColumnChart = function (element, series, opts) {
546
- waitForLoaded(function () {
547
- var options = jsOptions(series, opts);
548
- var data = createDataTable(series, "string");
549
- var chart = new google.visualization.ColumnChart(element);
550
- resize(function () {
551
- chart.draw(data, options);
551
+ };
552
+
553
+ this.renderColumnChart = function (chart) {
554
+ waitForLoaded(function () {
555
+ var options = jsOptions(chart.data, chart.options);
556
+ var data = createDataTable(chart.data, "string");
557
+ chart.chart = new google.visualization.ColumnChart(chart.element);
558
+ resize(function () {
559
+ chart.chart.draw(data, options);
560
+ });
552
561
  });
553
- });
554
- };
555
-
556
- renderBarChart = function (element, series, opts) {
557
- waitForLoaded(function () {
558
- var chartOptions = {
559
- hAxis: {
560
- gridlines: {
561
- color: "#ccc"
562
+ };
563
+
564
+ this.renderBarChart = function (chart) {
565
+ waitForLoaded(function () {
566
+ var chartOptions = {
567
+ hAxis: {
568
+ gridlines: {
569
+ color: "#ccc"
570
+ }
562
571
  }
563
- }
564
- };
565
- var options = jsOptionsFunc(defaultOptions, hideLegend, setBarMin, setBarMax, setStacked)(series, opts, chartOptions);
566
- var data = createDataTable(series, "string");
567
- var chart = new google.visualization.BarChart(element);
568
- resize(function () {
569
- chart.draw(data, options);
572
+ };
573
+ var options = jsOptionsFunc(defaultOptions, hideLegend, setBarMin, setBarMax, setStacked)(chart.data, chart.options, chartOptions);
574
+ var data = createDataTable(chart.data, "string");
575
+ chart.chart = new google.visualization.BarChart(chart.element);
576
+ resize(function () {
577
+ chart.chart.draw(data, options);
578
+ });
570
579
  });
571
- });
572
- };
573
-
574
- renderAreaChart = function (element, series, opts) {
575
- waitForLoaded(function () {
576
- var chartOptions = {
577
- isStacked: true,
578
- pointSize: 0,
579
- areaOpacity: 0.5
580
- };
581
- var options = jsOptions(series, opts, chartOptions);
582
- var data = createDataTable(series, "datetime");
583
- var chart = new google.visualization.AreaChart(element);
584
- resize(function () {
585
- chart.draw(data, options);
580
+ };
581
+
582
+ this.renderAreaChart = function (chart) {
583
+ waitForLoaded(function () {
584
+ var chartOptions = {
585
+ isStacked: true,
586
+ pointSize: 0,
587
+ areaOpacity: 0.5
588
+ };
589
+ var options = jsOptions(chart.data, chart.options, chartOptions);
590
+ var data = createDataTable(chart.data, chart.options.discrete ? "string" : "datetime");
591
+ chart.chart = new google.visualization.AreaChart(chart.element);
592
+ resize(function () {
593
+ chart.chart.draw(data, options);
594
+ });
586
595
  });
587
- });
588
- };
589
- } else { // no chart library installed
590
- renderLineChart = renderPieChart = renderColumnChart = renderBarChart = renderAreaChart = function () {
591
- throw new Error("Please install Google Charts or Highcharts");
596
+ };
597
+
598
+ this.renderGeoChart = function (chart) {
599
+ waitForLoaded(function () {
600
+ var chartOptions = {
601
+ legend: "none",
602
+ colorAxis: {
603
+ colors: ["#f6c7b6", "#ce502d"]
604
+ }
605
+ };
606
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
607
+
608
+ var data = new google.visualization.DataTable();
609
+ data.addColumn("string", "");
610
+ data.addColumn("number", "Value");
611
+ data.addRows(chart.data);
612
+
613
+ chart.chart = new google.visualization.GeoChart(chart.element);
614
+ resize(function () {
615
+ chart.chart.draw(data, options);
616
+ });
617
+ });
618
+ };
592
619
  };
620
+ adapters.push(GoogleChartsAdapter);
621
+ }
622
+
623
+ // TODO add adapter option
624
+ // TODO remove chartType if cross-browser way
625
+ // to get the name of the chart class
626
+ function renderChart(chartType, chart) {
627
+ var i, adapter, fnName;
628
+ fnName = "render" + chartType + "Chart";
629
+
630
+ for (i = 0; i < adapters.length; i++) {
631
+ adapter = adapters[i];
632
+ if (isFunction(adapter[fnName])) {
633
+ return adapter[fnName](chart);
634
+ }
635
+ }
636
+ throw new Error("No adapter found");
593
637
  }
594
638
 
595
639
  // process data
@@ -604,6 +648,9 @@
604
648
  } else {
605
649
  opts.hideLegend = false;
606
650
  }
651
+ if (opts.discrete) {
652
+ time = false;
653
+ }
607
654
 
608
655
  // right format
609
656
  for (i = 0; i < series.length; i++) {
@@ -623,56 +670,78 @@
623
670
  return series;
624
671
  }
625
672
 
626
- function processLineData(element, data, opts) {
627
- renderLineChart(element, processSeries(data, opts, true), opts);
628
- }
629
-
630
- function processColumnData(element, data, opts) {
631
- renderColumnChart(element, processSeries(data, opts, false), opts);
632
- }
633
-
634
- function processPieData(element, data, opts) {
673
+ function processSimple(data) {
635
674
  var perfectData = toArr(data), i;
636
675
  for (i = 0; i < perfectData.length; i++) {
637
676
  perfectData[i] = [toStr(perfectData[i][0]), toFloat(perfectData[i][1])];
638
677
  }
639
- renderPieChart(element, perfectData, opts);
678
+ return perfectData;
679
+ }
680
+
681
+ function processLineData(chart) {
682
+ chart.data = processSeries(chart.data, chart.options, true);
683
+ renderChart("Line", chart);
684
+ }
685
+
686
+ function processColumnData(chart) {
687
+ chart.data = processSeries(chart.data, chart.options, false);
688
+ renderChart("Column", chart);
640
689
  }
641
690
 
642
- function processBarData(element, data, opts) {
643
- renderBarChart(element, processSeries(data, opts, false), opts);
691
+ function processPieData(chart) {
692
+ chart.data = processSimple(chart.data);
693
+ renderChart("Pie", chart);
644
694
  }
645
695
 
646
- function processAreaData(element, data, opts) {
647
- renderAreaChart(element, processSeries(data, opts, true), opts);
696
+ function processBarData(chart) {
697
+ chart.data = processSeries(chart.data, chart.options, false);
698
+ renderChart("Bar", chart);
648
699
  }
649
700
 
650
- function setElement(element, data, opts, callback) {
701
+ function processAreaData(chart) {
702
+ chart.data = processSeries(chart.data, chart.options, true);
703
+ renderChart("Area", chart);
704
+ }
705
+
706
+ function processGeoData(chart) {
707
+ chart.data = processSimple(chart.data);
708
+ renderChart("Geo", chart);
709
+ }
710
+
711
+ function setElement(chart, element, dataSource, opts, callback) {
651
712
  if (typeof element === "string") {
652
713
  element = document.getElementById(element);
653
714
  }
654
- fetchDataSource(element, data, opts || {}, callback);
715
+ chart.element = element;
716
+ chart.options = opts || {};
717
+ chart.dataSource = dataSource;
718
+ Chartkick.charts[element.id] = chart;
719
+ fetchDataSource(chart, callback);
655
720
  }
656
721
 
657
722
  // define classes
658
723
 
659
724
  Chartkick = {
660
725
  LineChart: function (element, dataSource, opts) {
661
- setElement(element, dataSource, opts, processLineData);
726
+ setElement(this, element, dataSource, opts, processLineData);
662
727
  },
663
728
  PieChart: function (element, dataSource, opts) {
664
- setElement(element, dataSource, opts, processPieData);
729
+ setElement(this, element, dataSource, opts, processPieData);
665
730
  },
666
731
  ColumnChart: function (element, dataSource, opts) {
667
- setElement(element, dataSource, opts, processColumnData);
732
+ setElement(this, element, dataSource, opts, processColumnData);
668
733
  },
669
734
  BarChart: function (element, dataSource, opts) {
670
- setElement(element, dataSource, opts, processBarData);
735
+ setElement(this, element, dataSource, opts, processBarData);
671
736
  },
672
737
  AreaChart: function (element, dataSource, opts) {
673
- setElement(element, dataSource, opts, processAreaData);
674
- }
738
+ setElement(this, element, dataSource, opts, processAreaData);
739
+ },
740
+ GeoChart: function (element, dataSource, opts) {
741
+ setElement(this, element, dataSource, opts, processGeoData);
742
+ },
743
+ charts: {}
675
744
  };
676
745
 
677
746
  window.Chartkick = Chartkick;
678
- }());
747
+ }(window));
@@ -24,6 +24,10 @@ module Chartkick
24
24
  chartkick_chart "AreaChart", data_source, options
25
25
  end
26
26
 
27
+ def geo_chart(data_source, options = {})
28
+ chartkick_chart "GeoChart", data_source, options
29
+ end
30
+
27
31
  private
28
32
 
29
33
  def chartkick_chart(klass, data_source, options, &block)
@@ -1,3 +1,3 @@
1
1
  module Chartkick
2
- VERSION = "1.2.2"
2
+ VERSION = "1.2.3"
3
3
  end
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: 1.2.2
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-23 00:00:00.000000000 Z
11
+ date: 2014-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -95,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
95
  version: '0'
96
96
  requirements: []
97
97
  rubyforge_project:
98
- rubygems_version: 2.2.0
98
+ rubygems_version: 2.2.2
99
99
  signing_key:
100
100
  specification_version: 4
101
101
  summary: Create beautiful Javascript charts with one line of Ruby