weight-recorder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/CODE_OF_CONDUCT.md +49 -0
  6. data/Gemfile +8 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +49 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/config.ru +3 -0
  13. data/exe/recorder +5 -0
  14. data/exe/weight-recorder +5 -0
  15. data/lib/application.rb +98 -0
  16. data/lib/public/chartkick.js +1396 -0
  17. data/lib/public/css/bootstrap-theme.css +587 -0
  18. data/lib/public/css/bootstrap-theme.css.map +1 -0
  19. data/lib/public/css/bootstrap-theme.min.css +6 -0
  20. data/lib/public/css/bootstrap-theme.min.css.map +1 -0
  21. data/lib/public/css/bootstrap.css +6757 -0
  22. data/lib/public/css/bootstrap.css.map +1 -0
  23. data/lib/public/css/bootstrap.min.css +6 -0
  24. data/lib/public/css/bootstrap.min.css.map +1 -0
  25. data/lib/public/fonts/glyphicons-halflings-regular.eot +0 -0
  26. data/lib/public/fonts/glyphicons-halflings-regular.svg +288 -0
  27. data/lib/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  28. data/lib/public/fonts/glyphicons-halflings-regular.woff +0 -0
  29. data/lib/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
  30. data/lib/public/js/bootstrap.js +2377 -0
  31. data/lib/public/js/bootstrap.min.js +7 -0
  32. data/lib/public/js/npm.js +13 -0
  33. data/lib/recorder/command/options.rb +95 -0
  34. data/lib/recorder/command.rb +80 -0
  35. data/lib/recorder/data.rb +8 -0
  36. data/lib/recorder/db.rb +51 -0
  37. data/lib/recorder/version.rb +3 -0
  38. data/lib/recorder.rb +7 -0
  39. data/lib/views/_errors.haml +6 -0
  40. data/lib/views/_form.haml +13 -0
  41. data/lib/views/chart.haml +8 -0
  42. data/lib/views/edit.haml +8 -0
  43. data/lib/views/index.haml +36 -0
  44. data/lib/views/layout.haml +16 -0
  45. data/lib/views/new.haml +18 -0
  46. data/weight-recorder.gemspec +40 -0
  47. metadata +231 -0
@@ -0,0 +1,1396 @@
1
+ /*
2
+ * Chartkick.js
3
+ * Create beautiful JavaScript charts with minimal code
4
+ * https://github.com/ankane/chartkick.js
5
+ * v2.0.1
6
+ * MIT License
7
+ */
8
+
9
+ /*jslint browser: true, indent: 2, plusplus: true, vars: true */
10
+
11
+ (function (window) {
12
+ 'use strict';
13
+
14
+ var config = window.Chartkick || {};
15
+ var Chartkick, ISO8601_PATTERN, DECIMAL_SEPARATOR, adapters = [];
16
+ var DATE_PATTERN = /^(\d\d\d\d)(\-)?(\d\d)(\-)?(\d\d)$/i;
17
+ var GoogleChartsAdapter, HighchartsAdapter, ChartjsAdapter;
18
+
19
+ // helpers
20
+
21
+ function isArray(variable) {
22
+ return Object.prototype.toString.call(variable) === "[object Array]";
23
+ }
24
+
25
+ function isFunction(variable) {
26
+ return variable instanceof Function;
27
+ }
28
+
29
+ function isPlainObject(variable) {
30
+ return !isFunction(variable) && variable instanceof Object;
31
+ }
32
+
33
+ // https://github.com/madrobby/zepto/blob/master/src/zepto.js
34
+ function extend(target, source) {
35
+ var key;
36
+ for (key in source) {
37
+ if (isPlainObject(source[key]) || isArray(source[key])) {
38
+ if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
39
+ target[key] = {};
40
+ }
41
+ if (isArray(source[key]) && !isArray(target[key])) {
42
+ target[key] = [];
43
+ }
44
+ extend(target[key], source[key]);
45
+ } else if (source[key] !== undefined) {
46
+ target[key] = source[key];
47
+ }
48
+ }
49
+ }
50
+
51
+ function merge(obj1, obj2) {
52
+ var target = {};
53
+ extend(target, obj1);
54
+ extend(target, obj2);
55
+ return target;
56
+ }
57
+
58
+ // https://github.com/Do/iso8601.js
59
+ ISO8601_PATTERN = /(\d\d\d\d)(\-)?(\d\d)(\-)?(\d\d)(T)?(\d\d)(:)?(\d\d)?(:)?(\d\d)?([\.,]\d+)?($|Z|([\+\-])(\d\d)(:)?(\d\d)?)/i;
60
+ DECIMAL_SEPARATOR = String(1.5).charAt(1);
61
+
62
+ function parseISO8601(input) {
63
+ var day, hour, matches, milliseconds, minutes, month, offset, result, seconds, type, year;
64
+ type = Object.prototype.toString.call(input);
65
+ if (type === '[object Date]') {
66
+ return input;
67
+ }
68
+ if (type !== '[object String]') {
69
+ return;
70
+ }
71
+ matches = input.match(ISO8601_PATTERN);
72
+ if (matches) {
73
+ year = parseInt(matches[1], 10);
74
+ month = parseInt(matches[3], 10) - 1;
75
+ day = parseInt(matches[5], 10);
76
+ hour = parseInt(matches[7], 10);
77
+ minutes = matches[9] ? parseInt(matches[9], 10) : 0;
78
+ seconds = matches[11] ? parseInt(matches[11], 10) : 0;
79
+ milliseconds = matches[12] ? parseFloat(DECIMAL_SEPARATOR + matches[12].slice(1)) * 1000 : 0;
80
+ result = Date.UTC(year, month, day, hour, minutes, seconds, milliseconds);
81
+ if (matches[13] && matches[14]) {
82
+ offset = matches[15] * 60;
83
+ if (matches[17]) {
84
+ offset += parseInt(matches[17], 10);
85
+ }
86
+ offset *= matches[14] === '-' ? -1 : 1;
87
+ result -= offset * 60 * 1000;
88
+ }
89
+ return new Date(result);
90
+ }
91
+ }
92
+ // end iso8601.js
93
+
94
+ function negativeValues(series) {
95
+ var i, j, data;
96
+ for (i = 0; i < series.length; i++) {
97
+ data = series[i].data;
98
+ for (j = 0; j < data.length; j++) {
99
+ if (data[j][1] < 0) {
100
+ return true;
101
+ }
102
+ }
103
+ }
104
+ return false;
105
+ }
106
+
107
+ function jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked, setXtitle, setYtitle) {
108
+ return function (series, opts, chartOptions) {
109
+ var options = merge({}, defaultOptions);
110
+ options = merge(options, chartOptions || {});
111
+
112
+ // hide legend
113
+ // this is *not* an external option!
114
+ if (opts.hideLegend) {
115
+ hideLegend(options);
116
+ }
117
+
118
+ // min
119
+ if ("min" in opts) {
120
+ setMin(options, opts.min);
121
+ } else if (!negativeValues(series)) {
122
+ setMin(options, 0);
123
+ }
124
+
125
+ // max
126
+ if (opts.max) {
127
+ setMax(options, opts.max);
128
+ }
129
+
130
+ if ("stacked" in opts) {
131
+ setStacked(options, opts.stacked);
132
+ }
133
+
134
+ if (opts.colors) {
135
+ options.colors = opts.colors;
136
+ }
137
+
138
+ if (opts.xtitle) {
139
+ setXtitle(options, opts.xtitle);
140
+ }
141
+
142
+ if (opts.ytitle) {
143
+ setYtitle(options, opts.ytitle);
144
+ }
145
+
146
+ // merge library last
147
+ options = merge(options, opts.library || {});
148
+
149
+ return options;
150
+ };
151
+ }
152
+
153
+ function setText(element, text) {
154
+ if (document.body.innerText) {
155
+ element.innerText = text;
156
+ } else {
157
+ element.textContent = text;
158
+ }
159
+ }
160
+
161
+ function chartError(element, message) {
162
+ setText(element, "Error Loading Chart: " + message);
163
+ element.style.color = "#ff0000";
164
+ }
165
+
166
+ function getJSON(element, url, success) {
167
+ var $ = window.jQuery || window.Zepto || window.$;
168
+ $.ajax({
169
+ dataType: "json",
170
+ url: url,
171
+ success: success,
172
+ error: function (jqXHR, textStatus, errorThrown) {
173
+ var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
174
+ chartError(element, message);
175
+ }
176
+ });
177
+ }
178
+
179
+ function errorCatcher(chart, callback) {
180
+ try {
181
+ callback(chart);
182
+ } catch (err) {
183
+ chartError(chart.element, err.message);
184
+ throw err;
185
+ }
186
+ }
187
+
188
+ function fetchDataSource(chart, callback) {
189
+ if (typeof chart.dataSource === "string") {
190
+ getJSON(chart.element, chart.dataSource, function (data, textStatus, jqXHR) {
191
+ chart.data = data;
192
+ errorCatcher(chart, callback);
193
+ });
194
+ } else {
195
+ chart.data = chart.dataSource;
196
+ errorCatcher(chart, callback);
197
+ }
198
+ }
199
+
200
+ // type conversions
201
+
202
+ function toStr(n) {
203
+ return "" + n;
204
+ }
205
+
206
+ function toFloat(n) {
207
+ return parseFloat(n);
208
+ }
209
+
210
+ function toDate(n) {
211
+ var matches, year, month, day;
212
+ if (typeof n !== "object") {
213
+ if (typeof n === "number") {
214
+ n = new Date(n * 1000); // ms
215
+ } else if ((matches = n.match(DATE_PATTERN))) {
216
+ year = parseInt(matches[1], 10);
217
+ month = parseInt(matches[3], 10) - 1;
218
+ day = parseInt(matches[5], 10);
219
+ return new Date(year, month, day);
220
+ } else { // str
221
+ // try our best to get the str into iso8601
222
+ // TODO be smarter about this
223
+ var str = n.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
224
+ n = parseISO8601(str) || new Date(n);
225
+ }
226
+ }
227
+ return n;
228
+ }
229
+
230
+ function toArr(n) {
231
+ if (!isArray(n)) {
232
+ var arr = [], i;
233
+ for (i in n) {
234
+ if (n.hasOwnProperty(i)) {
235
+ arr.push([i, n[i]]);
236
+ }
237
+ }
238
+ n = arr;
239
+ }
240
+ return n;
241
+ }
242
+
243
+ function sortByTime(a, b) {
244
+ return a[0].getTime() - b[0].getTime();
245
+ }
246
+
247
+ function sortByNumber(a, b) {
248
+ return a - b;
249
+ }
250
+
251
+ function loadAdapters() {
252
+ if (!HighchartsAdapter && "Highcharts" in window) {
253
+ HighchartsAdapter = new function () {
254
+ var Highcharts = window.Highcharts;
255
+
256
+ this.name = "highcharts";
257
+
258
+ var defaultOptions = {
259
+ chart: {},
260
+ xAxis: {
261
+ title: {
262
+ text: null
263
+ },
264
+ labels: {
265
+ style: {
266
+ fontSize: "12px"
267
+ }
268
+ }
269
+ },
270
+ yAxis: {
271
+ title: {
272
+ text: null
273
+ },
274
+ labels: {
275
+ style: {
276
+ fontSize: "12px"
277
+ }
278
+ }
279
+ },
280
+ title: {
281
+ text: null
282
+ },
283
+ credits: {
284
+ enabled: false
285
+ },
286
+ legend: {
287
+ borderWidth: 0
288
+ },
289
+ tooltip: {
290
+ style: {
291
+ fontSize: "12px"
292
+ }
293
+ },
294
+ plotOptions: {
295
+ areaspline: {},
296
+ series: {
297
+ marker: {}
298
+ }
299
+ }
300
+ };
301
+
302
+ var hideLegend = function (options) {
303
+ options.legend.enabled = false;
304
+ };
305
+
306
+ var setMin = function (options, min) {
307
+ options.yAxis.min = min;
308
+ };
309
+
310
+ var setMax = function (options, max) {
311
+ options.yAxis.max = max;
312
+ };
313
+
314
+ var setStacked = function (options, stacked) {
315
+ options.plotOptions.series.stacking = stacked ? "normal" : null;
316
+ };
317
+
318
+ var setXtitle = function (options, title) {
319
+ options.xAxis.title.text = title;
320
+ };
321
+
322
+ var setYtitle = function (options, title) {
323
+ options.yAxis.title.text = title;
324
+ };
325
+
326
+ var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked, setXtitle, setYtitle);
327
+
328
+ this.renderLineChart = function (chart, chartType) {
329
+ chartType = chartType || "spline";
330
+ var chartOptions = {};
331
+ if (chartType === "areaspline") {
332
+ chartOptions = {
333
+ plotOptions: {
334
+ areaspline: {
335
+ stacking: "normal"
336
+ },
337
+ series: {
338
+ marker: {
339
+ enabled: false
340
+ }
341
+ }
342
+ }
343
+ };
344
+ }
345
+ var options = jsOptions(chart.data, chart.options, chartOptions), data, i, j;
346
+ options.xAxis.type = chart.options.discrete ? "category" : "datetime";
347
+ options.chart.type = chartType;
348
+ options.chart.renderTo = chart.element.id;
349
+
350
+ var series = chart.data;
351
+ for (i = 0; i < series.length; i++) {
352
+ data = series[i].data;
353
+ if (!chart.options.discrete) {
354
+ for (j = 0; j < data.length; j++) {
355
+ data[j][0] = data[j][0].getTime();
356
+ }
357
+ }
358
+ series[i].marker = {symbol: "circle"};
359
+ }
360
+ options.series = series;
361
+ new Highcharts.Chart(options);
362
+ };
363
+
364
+ this.renderScatterChart = function (chart) {
365
+ var chartOptions = {};
366
+ var options = jsOptions(chart.data, chart.options, chartOptions);
367
+ options.chart.type = 'scatter';
368
+ options.chart.renderTo = chart.element.id;
369
+ options.series = chart.data;
370
+ new Highcharts.Chart(options);
371
+ };
372
+
373
+ this.renderPieChart = function (chart) {
374
+ var chartOptions = {};
375
+ if (chart.options.colors) {
376
+ chartOptions.colors = chart.options.colors;
377
+ }
378
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
379
+ options.chart.renderTo = chart.element.id;
380
+ options.series = [{
381
+ type: "pie",
382
+ name: chart.options.label || "Value",
383
+ data: chart.data
384
+ }];
385
+ new Highcharts.Chart(options);
386
+ };
387
+
388
+ this.renderColumnChart = function (chart, chartType) {
389
+ chartType = chartType || "column";
390
+ var series = chart.data;
391
+ var options = jsOptions(series, chart.options), i, j, s, d, rows = [];
392
+ options.chart.type = chartType;
393
+ options.chart.renderTo = chart.element.id;
394
+
395
+ for (i = 0; i < series.length; i++) {
396
+ s = series[i];
397
+
398
+ for (j = 0; j < s.data.length; j++) {
399
+ d = s.data[j];
400
+ if (!rows[d[0]]) {
401
+ rows[d[0]] = new Array(series.length);
402
+ }
403
+ rows[d[0]][i] = d[1];
404
+ }
405
+ }
406
+
407
+ var categories = [];
408
+ for (i in rows) {
409
+ if (rows.hasOwnProperty(i)) {
410
+ categories.push(i);
411
+ }
412
+ }
413
+ options.xAxis.categories = categories;
414
+
415
+ var newSeries = [];
416
+ for (i = 0; i < series.length; i++) {
417
+ d = [];
418
+ for (j = 0; j < categories.length; j++) {
419
+ d.push(rows[categories[j]][i] || 0);
420
+ }
421
+
422
+ newSeries.push({
423
+ name: series[i].name,
424
+ data: d
425
+ });
426
+ }
427
+ options.series = newSeries;
428
+
429
+ new Highcharts.Chart(options);
430
+ };
431
+
432
+ var self = this;
433
+
434
+ this.renderBarChart = function (chart) {
435
+ self.renderColumnChart(chart, "bar");
436
+ };
437
+
438
+ this.renderAreaChart = function (chart) {
439
+ self.renderLineChart(chart, "areaspline");
440
+ };
441
+ };
442
+ adapters.push(HighchartsAdapter);
443
+ }
444
+ if (!GoogleChartsAdapter && window.google && window.google.setOnLoadCallback) {
445
+ GoogleChartsAdapter = new function () {
446
+ var google = window.google;
447
+
448
+ this.name = "google";
449
+
450
+ var loaded = {};
451
+ var callbacks = [];
452
+
453
+ var runCallbacks = function () {
454
+ var cb, call;
455
+ for (var i = 0; i < callbacks.length; i++) {
456
+ cb = callbacks[i];
457
+ call = google.visualization && ((cb.pack === "corechart" && google.visualization.LineChart) || (cb.pack === "timeline" && google.visualization.Timeline));
458
+ if (call) {
459
+ cb.callback();
460
+ callbacks.splice(i, 1);
461
+ i--;
462
+ }
463
+ }
464
+ };
465
+
466
+ var waitForLoaded = function (pack, callback) {
467
+ if (!callback) {
468
+ callback = pack;
469
+ pack = "corechart";
470
+ }
471
+
472
+ callbacks.push({pack: pack, callback: callback});
473
+
474
+ if (loaded[pack]) {
475
+ runCallbacks();
476
+ } else {
477
+ loaded[pack] = true;
478
+
479
+ // https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
480
+ var loadOptions = {
481
+ packages: [pack],
482
+ callback: runCallbacks
483
+ };
484
+ if (config.language) {
485
+ loadOptions.language = config.language;
486
+ }
487
+ google.load("visualization", "1", loadOptions);
488
+ }
489
+ };
490
+
491
+ // Set chart options
492
+ var defaultOptions = {
493
+ chartArea: {},
494
+ fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
495
+ pointSize: 6,
496
+ legend: {
497
+ textStyle: {
498
+ fontSize: 12,
499
+ color: "#444"
500
+ },
501
+ alignment: "center",
502
+ position: "right"
503
+ },
504
+ curveType: "function",
505
+ hAxis: {
506
+ textStyle: {
507
+ color: "#666",
508
+ fontSize: 12
509
+ },
510
+ titleTextStyle: {},
511
+ gridlines: {
512
+ color: "transparent"
513
+ },
514
+ baselineColor: "#ccc",
515
+ viewWindow: {}
516
+ },
517
+ vAxis: {
518
+ textStyle: {
519
+ color: "#666",
520
+ fontSize: 12
521
+ },
522
+ titleTextStyle: {},
523
+ baselineColor: "#ccc",
524
+ viewWindow: {}
525
+ },
526
+ tooltip: {
527
+ textStyle: {
528
+ color: "#666",
529
+ fontSize: 12
530
+ }
531
+ }
532
+ };
533
+
534
+ var hideLegend = function (options) {
535
+ options.legend.position = "none";
536
+ };
537
+
538
+ var setMin = function (options, min) {
539
+ options.vAxis.viewWindow.min = min;
540
+ };
541
+
542
+ var setMax = function (options, max) {
543
+ options.vAxis.viewWindow.max = max;
544
+ };
545
+
546
+ var setBarMin = function (options, min) {
547
+ options.hAxis.viewWindow.min = min;
548
+ };
549
+
550
+ var setBarMax = function (options, max) {
551
+ options.hAxis.viewWindow.max = max;
552
+ };
553
+
554
+ var setStacked = function (options, stacked) {
555
+ options.isStacked = !!stacked;
556
+ };
557
+
558
+ var setXtitle = function (options, title) {
559
+ options.hAxis.title = title;
560
+ options.hAxis.titleTextStyle.italic = false;
561
+ };
562
+
563
+ var setYtitle = function (options, title) {
564
+ options.vAxis.title = title;
565
+ options.vAxis.titleTextStyle.italic = false;
566
+ };
567
+
568
+ var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked, setXtitle, setYtitle);
569
+
570
+ // cant use object as key
571
+ var createDataTable = function (series, columnType) {
572
+ var i, j, s, d, key, rows = [];
573
+ for (i = 0; i < series.length; i++) {
574
+ s = series[i];
575
+
576
+ for (j = 0; j < s.data.length; j++) {
577
+ d = s.data[j];
578
+ key = (columnType === "datetime") ? d[0].getTime() : d[0];
579
+ if (!rows[key]) {
580
+ rows[key] = new Array(series.length);
581
+ }
582
+ rows[key][i] = toFloat(d[1]);
583
+ }
584
+ }
585
+
586
+ var rows2 = [];
587
+ var day = true;
588
+ var value;
589
+ for (i in rows) {
590
+ if (rows.hasOwnProperty(i)) {
591
+ if (columnType === "datetime") {
592
+ value = new Date(toFloat(i));
593
+ day = day && isDay(value);
594
+ } else if (columnType === "number") {
595
+ value = toFloat(i);
596
+ } else {
597
+ value = i;
598
+ }
599
+ rows2.push([value].concat(rows[i]));
600
+ }
601
+ }
602
+ if (columnType === "datetime") {
603
+ rows2.sort(sortByTime);
604
+ }
605
+
606
+ // create datatable
607
+ var data = new google.visualization.DataTable();
608
+ columnType = columnType === "datetime" && day ? "date" : columnType;
609
+ data.addColumn(columnType, "");
610
+ for (i = 0; i < series.length; i++) {
611
+ data.addColumn("number", series[i].name);
612
+ }
613
+ data.addRows(rows2);
614
+
615
+ return data;
616
+ };
617
+
618
+ var resize = function (callback) {
619
+ if (window.attachEvent) {
620
+ window.attachEvent("onresize", callback);
621
+ } else if (window.addEventListener) {
622
+ window.addEventListener("resize", callback, true);
623
+ }
624
+ callback();
625
+ };
626
+
627
+ this.renderLineChart = function (chart) {
628
+ waitForLoaded(function () {
629
+ var options = jsOptions(chart.data, chart.options);
630
+ var data = createDataTable(chart.data, chart.options.discrete ? "string" : "datetime");
631
+ chart.chart = new google.visualization.LineChart(chart.element);
632
+ resize(function () {
633
+ chart.chart.draw(data, options);
634
+ });
635
+ });
636
+ };
637
+
638
+ this.renderPieChart = function (chart) {
639
+ waitForLoaded(function () {
640
+ var chartOptions = {
641
+ chartArea: {
642
+ top: "10%",
643
+ height: "80%"
644
+ }
645
+ };
646
+ if (chart.options.colors) {
647
+ chartOptions.colors = chart.options.colors;
648
+ }
649
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
650
+
651
+ var data = new google.visualization.DataTable();
652
+ data.addColumn("string", "");
653
+ data.addColumn("number", "Value");
654
+ data.addRows(chart.data);
655
+
656
+ chart.chart = new google.visualization.PieChart(chart.element);
657
+ resize(function () {
658
+ chart.chart.draw(data, options);
659
+ });
660
+ });
661
+ };
662
+
663
+ this.renderColumnChart = function (chart) {
664
+ waitForLoaded(function () {
665
+ var options = jsOptions(chart.data, chart.options);
666
+ var data = createDataTable(chart.data, "string");
667
+ chart.chart = new google.visualization.ColumnChart(chart.element);
668
+ resize(function () {
669
+ chart.chart.draw(data, options);
670
+ });
671
+ });
672
+ };
673
+
674
+ this.renderBarChart = function (chart) {
675
+ waitForLoaded(function () {
676
+ var chartOptions = {
677
+ hAxis: {
678
+ gridlines: {
679
+ color: "#ccc"
680
+ }
681
+ }
682
+ };
683
+ var options = jsOptionsFunc(defaultOptions, hideLegend, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart.data, chart.options, chartOptions);
684
+ var data = createDataTable(chart.data, "string");
685
+ chart.chart = new google.visualization.BarChart(chart.element);
686
+ resize(function () {
687
+ chart.chart.draw(data, options);
688
+ });
689
+ });
690
+ };
691
+
692
+ this.renderAreaChart = function (chart) {
693
+ waitForLoaded(function () {
694
+ var chartOptions = {
695
+ isStacked: true,
696
+ pointSize: 0,
697
+ areaOpacity: 0.5
698
+ };
699
+ var options = jsOptions(chart.data, chart.options, chartOptions);
700
+ var data = createDataTable(chart.data, chart.options.discrete ? "string" : "datetime");
701
+ chart.chart = new google.visualization.AreaChart(chart.element);
702
+ resize(function () {
703
+ chart.chart.draw(data, options);
704
+ });
705
+ });
706
+ };
707
+
708
+ this.renderGeoChart = function (chart) {
709
+ waitForLoaded(function () {
710
+ var chartOptions = {
711
+ legend: "none",
712
+ colorAxis: {
713
+ colors: chart.options.colors || ["#f6c7b6", "#ce502d"]
714
+ }
715
+ };
716
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
717
+
718
+ var data = new google.visualization.DataTable();
719
+ data.addColumn("string", "");
720
+ data.addColumn("number", chart.options.label || "Value");
721
+ data.addRows(chart.data);
722
+
723
+ chart.chart = new google.visualization.GeoChart(chart.element);
724
+ resize(function () {
725
+ chart.chart.draw(data, options);
726
+ });
727
+ });
728
+ };
729
+
730
+ this.renderScatterChart = function (chart) {
731
+ waitForLoaded(function () {
732
+ var chartOptions = {};
733
+ var options = jsOptions(chart.data, chart.options, chartOptions);
734
+ var data = createDataTable(chart.data, "number");
735
+
736
+ chart.chart = new google.visualization.ScatterChart(chart.element);
737
+ resize(function () {
738
+ chart.chart.draw(data, options);
739
+ });
740
+ });
741
+ };
742
+
743
+ this.renderTimeline = function (chart) {
744
+ waitForLoaded("timeline", function () {
745
+ var chartOptions = {
746
+ legend: "none"
747
+ };
748
+
749
+ if (chart.options.colors) {
750
+ chartOptions.colors = chart.options.colors;
751
+ }
752
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
753
+
754
+ var data = new google.visualization.DataTable();
755
+ data.addColumn({type: "string", id: "Name"});
756
+ data.addColumn({type: "date", id: "Start"});
757
+ data.addColumn({type: "date", id: "End"});
758
+ data.addRows(chart.data);
759
+
760
+ chart.element.style.lineHeight = "normal";
761
+ chart.chart = new google.visualization.Timeline(chart.element);
762
+
763
+ resize(function () {
764
+ chart.chart.draw(data, options);
765
+ });
766
+ });
767
+ };
768
+ };
769
+
770
+ adapters.push(GoogleChartsAdapter);
771
+ }
772
+ if (!ChartjsAdapter && "Chart" in window) {
773
+ ChartjsAdapter = new function () {
774
+ var Chart = window.Chart;
775
+
776
+ this.name = "chartjs";
777
+
778
+ var baseOptions = {
779
+ maintainAspectRatio: false,
780
+ animation: false
781
+ };
782
+
783
+ var defaultOptions = {
784
+ scales: {
785
+ yAxes: [
786
+ {
787
+ ticks: {
788
+ maxTicksLimit: 4
789
+ },
790
+ scaleLabel: {
791
+ fontSize: 16,
792
+ // fontStyle: "bold",
793
+ fontColor: "#333"
794
+ }
795
+ }
796
+ ],
797
+ xAxes: [
798
+ {
799
+ gridLines: {
800
+ drawOnChartArea: false
801
+ },
802
+ scaleLabel: {
803
+ fontSize: 16,
804
+ // fontStyle: "bold",
805
+ fontColor: "#333"
806
+ },
807
+ time: {},
808
+ ticks: {}
809
+ }
810
+ ]
811
+ },
812
+ legend: {}
813
+ };
814
+
815
+ // http://there4.io/2012/05/02/google-chart-color-list/
816
+ var defaultColors = [
817
+ "#3366CC", "#DC3912", "#FF9900", "#109618", "#990099", "#3B3EAC", "#0099C6",
818
+ "#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11",
819
+ "#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#3B3EAC"
820
+ ];
821
+
822
+ var hideLegend = function (options) {
823
+ options.legend.display = false;
824
+ };
825
+
826
+ var setMin = function (options, min) {
827
+ if (min !== null) {
828
+ options.scales.yAxes[0].ticks.min = min;
829
+ }
830
+ };
831
+
832
+ var setMax = function (options, max) {
833
+ options.scales.yAxes[0].ticks.max = max;
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
+
846
+ var setStacked = function (options, stacked) {
847
+ options.scales.xAxes[0].stacked = !!stacked;
848
+ options.scales.yAxes[0].stacked = !!stacked;
849
+ };
850
+
851
+ var setXtitle = function (options, title) {
852
+ options.scales.xAxes[0].scaleLabel.display = true;
853
+ options.scales.xAxes[0].scaleLabel.labelString = title;
854
+ };
855
+
856
+ var setYtitle = function (options, title) {
857
+ options.scales.yAxes[0].scaleLabel.display = true;
858
+ options.scales.yAxes[0].scaleLabel.labelString = title;
859
+ };
860
+
861
+ var drawChart = function(chart, type, data, options) {
862
+ chart.element.innerHTML = "<canvas></canvas>";
863
+ var ctx = chart.element.getElementsByTagName("CANVAS")[0];
864
+
865
+ chart.chart = new Chart(ctx, {
866
+ type: type,
867
+ data: data,
868
+ options: options
869
+ });
870
+ };
871
+
872
+ // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
873
+ var addOpacity = function(hex, opacity) {
874
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
875
+ return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
876
+ };
877
+
878
+ var setLabelSize = function (chart, data, options) {
879
+ var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
880
+ if (maxLabelSize > 25) {
881
+ maxLabelSize = 25;
882
+ }
883
+ options.scales.xAxes[0].ticks.callback = function (value) {
884
+ value = toStr(value);
885
+ if (value.length > maxLabelSize) {
886
+ return value.substring(0, maxLabelSize - 2) + "...";
887
+ } else {
888
+ return value;
889
+ }
890
+ };
891
+ };
892
+
893
+ var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setMin, setMax, setStacked, setXtitle, setYtitle);
894
+
895
+ var createDataTable = function (chart, options, chartType) {
896
+ var datasets = [];
897
+ var labels = [];
898
+
899
+ var colors = chart.options.colors || defaultColors;
900
+
901
+ var day = true;
902
+ var week = true;
903
+ var dayOfWeek;
904
+ var month = true;
905
+ var year = true;
906
+ var hour = true;
907
+ var minute = true;
908
+ var detectType = (chartType === "line" || chartType === "area") && !chart.options.discrete;
909
+
910
+ var series = chart.data;
911
+
912
+ var sortedLabels = [];
913
+
914
+ var i, j, s, d, key, rows = [];
915
+ for (i = 0; i < series.length; i++) {
916
+ s = series[i];
917
+
918
+ for (j = 0; j < s.data.length; j++) {
919
+ d = s.data[j];
920
+ key = detectType ? d[0].getTime() : d[0];
921
+ if (!rows[key]) {
922
+ rows[key] = new Array(series.length);
923
+ }
924
+ rows[key][i] = toFloat(d[1]);
925
+ if (sortedLabels.indexOf(key) === -1) {
926
+ sortedLabels.push(key);
927
+ }
928
+ }
929
+ }
930
+
931
+ if (detectType) {
932
+ sortedLabels.sort(sortByNumber);
933
+ }
934
+
935
+ var rows2 = [];
936
+ for (j = 0; j < series.length; j++) {
937
+ rows2.push([]);
938
+ }
939
+
940
+ var value;
941
+ var k;
942
+ for (k = 0; k < sortedLabels.length; k++) {
943
+ i = sortedLabels[k];
944
+ if (detectType) {
945
+ value = new Date(toFloat(i));
946
+ // TODO make this efficient
947
+ day = day && isDay(value);
948
+ if (!dayOfWeek) {
949
+ dayOfWeek = value.getDay();
950
+ }
951
+ week = week && isWeek(value, dayOfWeek);
952
+ month = month && isMonth(value);
953
+ year = year && isYear(value);
954
+ hour = hour && isHour(value);
955
+ minute = minute && isMinute(value);
956
+ } else {
957
+ value = i;
958
+ }
959
+ labels.push(value);
960
+ for (j = 0; j < series.length; j++) {
961
+ rows2[j].push(rows[i][j]);
962
+ }
963
+ }
964
+
965
+ for (i = 0; i < series.length; i++) {
966
+ s = series[i];
967
+
968
+ var backgroundColor = chartType !== "line" ? addOpacity(colors[i], 0.5) : colors[i];
969
+
970
+ var dataset = {
971
+ label: s.name,
972
+ data: rows2[i],
973
+ fill: chartType === "area",
974
+ borderColor: colors[i],
975
+ backgroundColor: backgroundColor,
976
+ pointBackgroundColor: colors[i],
977
+ borderWidth: 2
978
+ };
979
+
980
+ datasets.push(merge(dataset, s.library || {}));
981
+ }
982
+
983
+ if (detectType && labels.length > 0) {
984
+ var minTime = labels[0].getTime();
985
+ var maxTime = labels[0].getTime();
986
+ for (i = 1; i < labels.length; i++) {
987
+ value = labels[i].getTime();
988
+ if (value < minTime) {
989
+ minTime = value;
990
+ }
991
+ if (value > maxTime) {
992
+ maxTime = value;
993
+ }
994
+ }
995
+
996
+ var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
997
+
998
+ if (!options.scales.xAxes[0].time.unit) {
999
+ var step;
1000
+ if (year || timeDiff > 365 * 10) {
1001
+ options.scales.xAxes[0].time.unit = "year";
1002
+ step = 365;
1003
+ } else if (month || timeDiff > 30 * 10) {
1004
+ options.scales.xAxes[0].time.unit = "month";
1005
+ step = 30;
1006
+ } else if (day || timeDiff > 10) {
1007
+ options.scales.xAxes[0].time.unit = "day";
1008
+ step = 1;
1009
+ } else if (hour) {
1010
+ options.scales.xAxes[0].time.unit = "hour";
1011
+ step = 1 / 24.0;
1012
+ } else if (minute) {
1013
+ options.scales.xAxes[0].time.displayFormats = {minute: "h:mm a"};
1014
+ options.scales.xAxes[0].time.unit = "minute";
1015
+ step = 1 / 24.0 / 60.0;
1016
+ }
1017
+
1018
+
1019
+ if (step && timeDiff > 0) {
1020
+ var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
1021
+ if (week && step === 1) {
1022
+ unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
1023
+ }
1024
+ options.scales.xAxes[0].time.unitStepSize = unitStepSize;
1025
+ }
1026
+ }
1027
+
1028
+ if (!options.scales.xAxes[0].time.tooltipFormat) {
1029
+ if (day) {
1030
+ options.scales.xAxes[0].time.tooltipFormat = "ll";
1031
+ } else if (hour) {
1032
+ options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
1033
+ } else if (minute) {
1034
+ options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
1035
+ }
1036
+ }
1037
+ }
1038
+
1039
+ var data = {
1040
+ labels: labels,
1041
+ datasets: datasets
1042
+ };
1043
+
1044
+ return data;
1045
+ };
1046
+
1047
+ this.renderLineChart = function (chart, chartType) {
1048
+ var areaOptions = {};
1049
+ if (chartType === "area") {
1050
+ // TODO fix area stacked
1051
+ // areaOptions.stacked = true;
1052
+ }
1053
+ // fix for https://github.com/chartjs/Chart.js/issues/2441
1054
+ if (!chart.options.max && allZeros(chart.data)) {
1055
+ chart.options.max = 1;
1056
+ }
1057
+
1058
+ var options = jsOptions(chart.data, merge(areaOptions, chart.options));
1059
+
1060
+ var data = createDataTable(chart, options, chartType || "line");
1061
+
1062
+ options.scales.xAxes[0].type = chart.options.discrete ? "category" : "time";
1063
+
1064
+ drawChart(chart, "line", data, options);
1065
+ };
1066
+
1067
+ this.renderPieChart = function (chart) {
1068
+ var options = merge(baseOptions, chart.options.library || {});
1069
+
1070
+ var labels = [];
1071
+ var values = [];
1072
+ for (var i = 0; i < chart.data.length; i++) {
1073
+ var point = chart.data[i];
1074
+ labels.push(point[0]);
1075
+ values.push(point[1]);
1076
+ }
1077
+
1078
+ var data = {
1079
+ labels: labels,
1080
+ datasets: [
1081
+ {
1082
+ data: values,
1083
+ backgroundColor: chart.options.colors || defaultColors
1084
+ }
1085
+ ]
1086
+ };
1087
+
1088
+ drawChart(chart, "pie", data, options);
1089
+ };
1090
+
1091
+ this.renderColumnChart = function (chart, chartType) {
1092
+ var options;
1093
+ if (chartType === "bar") {
1094
+ options = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart.data, chart.options);
1095
+ } else {
1096
+ options = jsOptions(chart.data, chart.options);
1097
+ }
1098
+ var data = createDataTable(chart, options, "column");
1099
+ setLabelSize(chart, data, options);
1100
+ drawChart(chart, (chartType === "bar" ? "horizontalBar" : "bar"), data, options);
1101
+ };
1102
+
1103
+ var self = this;
1104
+
1105
+ this.renderAreaChart = function (chart) {
1106
+ self.renderLineChart(chart, "area");
1107
+ };
1108
+
1109
+ this.renderBarChart = function (chart) {
1110
+ self.renderColumnChart(chart, "bar");
1111
+ };
1112
+
1113
+ this.renderScatterChart = function (chart) {
1114
+ var options = jsOptions(chart.data, chart.options);
1115
+
1116
+ var colors = chart.options.colors || defaultColors;
1117
+
1118
+ var datasets = [];
1119
+ var series = chart.data;
1120
+ for (var i = 0; i < series.length; i++) {
1121
+ var s = series[i];
1122
+ var d = [];
1123
+ for (var j = 0; j < s.data.length; j++) {
1124
+ d.push({
1125
+ x: toFloat(s.data[j][0]),
1126
+ y: toFloat(s.data[j][1])
1127
+ });
1128
+ }
1129
+
1130
+ datasets.push({
1131
+ label: s.name,
1132
+ showLine: false,
1133
+ data: d,
1134
+ borderColor: colors[i],
1135
+ backgroundColor: colors[i],
1136
+ pointBackgroundColor: colors[i]
1137
+ })
1138
+ }
1139
+
1140
+ var data = {datasets: datasets};
1141
+
1142
+ options.scales.xAxes[0].type = "linear";
1143
+ options.scales.xAxes[0].position = "bottom";
1144
+
1145
+ drawChart(chart, "line", data, options);
1146
+ };
1147
+ };
1148
+
1149
+ adapters.unshift(ChartjsAdapter);
1150
+ }
1151
+ }
1152
+
1153
+ // TODO remove chartType if cross-browser way
1154
+ // to get the name of the chart class
1155
+ function renderChart(chartType, chart) {
1156
+ var i, adapter, fnName, adapterName;
1157
+ fnName = "render" + chartType;
1158
+ adapterName = chart.options.adapter;
1159
+
1160
+ loadAdapters();
1161
+
1162
+ for (i = 0; i < adapters.length; i++) {
1163
+ adapter = adapters[i];
1164
+ if ((!adapterName || adapterName === adapter.name) && isFunction(adapter[fnName])) {
1165
+ return adapter[fnName](chart);
1166
+ }
1167
+ }
1168
+ throw new Error("No adapter found");
1169
+ }
1170
+
1171
+ // process data
1172
+
1173
+ var toFormattedKey = function (key, keyType) {
1174
+ if (keyType === "number") {
1175
+ key = toFloat(key);
1176
+ } else if (keyType === "datetime") {
1177
+ key = toDate(key);
1178
+ } else {
1179
+ key = toStr(key);
1180
+ }
1181
+ return key;
1182
+ };
1183
+
1184
+ var formatSeriesData = function (data, keyType) {
1185
+ var r = [], key, j;
1186
+ for (j = 0; j < data.length; j++) {
1187
+ key = toFormattedKey(data[j][0], keyType);
1188
+ r.push([key, toFloat(data[j][1])]);
1189
+ }
1190
+ if (keyType === "datetime") {
1191
+ r.sort(sortByTime);
1192
+ }
1193
+ return r;
1194
+ };
1195
+
1196
+ function isMinute(d) {
1197
+ return d.getMilliseconds() === 0 && d.getSeconds() === 0;
1198
+ }
1199
+
1200
+ function isHour(d) {
1201
+ return isMinute(d) && d.getMinutes() === 0;
1202
+ }
1203
+
1204
+ function isDay(d) {
1205
+ return isHour(d) && d.getHours() === 0;
1206
+ }
1207
+
1208
+ function isWeek(d, dayOfWeek) {
1209
+ return isDay(d) && d.getDay() === dayOfWeek;
1210
+ }
1211
+
1212
+ function isMonth(d) {
1213
+ return isDay(d) && d.getDate() === 1;
1214
+ }
1215
+
1216
+ function isYear(d) {
1217
+ return isMonth(d) && d.getMonth() === 0;
1218
+ }
1219
+
1220
+ function isDate(obj) {
1221
+ return !isNaN(toDate(obj)) && toStr(obj).length >= 6;
1222
+ }
1223
+
1224
+ function allZeros(data) {
1225
+ var i, j, d;
1226
+ for (i = 0; i < data.length; i++) {
1227
+ d = data[i].data;
1228
+ for (j = 0; j < d.length; j++) {
1229
+ if (d[j][1] != 0) {
1230
+ return false;
1231
+ }
1232
+ }
1233
+ }
1234
+ return true;
1235
+ }
1236
+
1237
+ function detectDiscrete(series) {
1238
+ var i, j, data;
1239
+ for (i = 0; i < series.length; i++) {
1240
+ data = toArr(series[i].data);
1241
+ for (j = 0; j < data.length; j++) {
1242
+ if (!isDate(data[j][0])) {
1243
+ return true;
1244
+ }
1245
+ }
1246
+ }
1247
+ return false;
1248
+ }
1249
+
1250
+ function processSeries(series, opts, keyType) {
1251
+ var i;
1252
+
1253
+ // see if one series or multiple
1254
+ if (!isArray(series) || typeof series[0] !== "object" || isArray(series[0])) {
1255
+ series = [{name: opts.label || "Value", data: series}];
1256
+ opts.hideLegend = true;
1257
+ } else {
1258
+ opts.hideLegend = false;
1259
+ }
1260
+ if ((opts.discrete === null || opts.discrete === undefined)) {
1261
+ opts.discrete = detectDiscrete(series);
1262
+ }
1263
+ if (opts.discrete) {
1264
+ keyType = "string";
1265
+ }
1266
+
1267
+ // right format
1268
+ for (i = 0; i < series.length; i++) {
1269
+ series[i].data = formatSeriesData(toArr(series[i].data), keyType);
1270
+ }
1271
+
1272
+ return series;
1273
+ }
1274
+
1275
+ function processSimple(data) {
1276
+ var perfectData = toArr(data), i;
1277
+ for (i = 0; i < perfectData.length; i++) {
1278
+ perfectData[i] = [toStr(perfectData[i][0]), toFloat(perfectData[i][1])];
1279
+ }
1280
+ return perfectData;
1281
+ }
1282
+
1283
+ function processTime(data)
1284
+ {
1285
+ var i;
1286
+ for (i = 0; i < data.length; i++) {
1287
+ data[i][1] = toDate(data[i][1]);
1288
+ data[i][2] = toDate(data[i][2]);
1289
+ }
1290
+ return data;
1291
+ }
1292
+
1293
+ function processLineData(chart) {
1294
+ chart.data = processSeries(chart.data, chart.options, "datetime");
1295
+ renderChart("LineChart", chart);
1296
+ }
1297
+
1298
+ function processColumnData(chart) {
1299
+ chart.data = processSeries(chart.data, chart.options, "string");
1300
+ renderChart("ColumnChart", chart);
1301
+ }
1302
+
1303
+ function processPieData(chart) {
1304
+ chart.data = processSimple(chart.data);
1305
+ renderChart("PieChart", chart);
1306
+ }
1307
+
1308
+ function processBarData(chart) {
1309
+ chart.data = processSeries(chart.data, chart.options, "string");
1310
+ renderChart("BarChart", chart);
1311
+ }
1312
+
1313
+ function processAreaData(chart) {
1314
+ chart.data = processSeries(chart.data, chart.options, "datetime");
1315
+ renderChart("AreaChart", chart);
1316
+ }
1317
+
1318
+ function processGeoData(chart) {
1319
+ chart.data = processSimple(chart.data);
1320
+ renderChart("GeoChart", chart);
1321
+ }
1322
+
1323
+ function processScatterData(chart) {
1324
+ chart.data = processSeries(chart.data, chart.options, "number");
1325
+ renderChart("ScatterChart", chart);
1326
+ }
1327
+
1328
+ function processTimelineData(chart) {
1329
+ chart.data = processTime(chart.data);
1330
+ renderChart("Timeline", chart);
1331
+ }
1332
+
1333
+ function setElement(chart, element, dataSource, opts, callback) {
1334
+ var elementId;
1335
+ if (typeof element === "string") {
1336
+ elementId = element;
1337
+ element = document.getElementById(element);
1338
+ if (!element) {
1339
+ throw new Error("No element with id " + elementId);
1340
+ }
1341
+ }
1342
+ chart.element = element;
1343
+ chart.options = opts || {};
1344
+ chart.dataSource = dataSource;
1345
+ chart.getElement = function () {
1346
+ return element;
1347
+ };
1348
+ chart.getData = function () {
1349
+ return chart.data;
1350
+ };
1351
+ chart.getOptions = function () {
1352
+ return opts || {};
1353
+ };
1354
+ chart.getChartObject = function () {
1355
+ return chart.chart;
1356
+ };
1357
+ Chartkick.charts[element.id] = chart;
1358
+ fetchDataSource(chart, callback);
1359
+ }
1360
+
1361
+ // define classes
1362
+
1363
+ Chartkick = {
1364
+ LineChart: function (element, dataSource, opts) {
1365
+ setElement(this, element, dataSource, opts, processLineData);
1366
+ },
1367
+ PieChart: function (element, dataSource, opts) {
1368
+ setElement(this, element, dataSource, opts, processPieData);
1369
+ },
1370
+ ColumnChart: function (element, dataSource, opts) {
1371
+ setElement(this, element, dataSource, opts, processColumnData);
1372
+ },
1373
+ BarChart: function (element, dataSource, opts) {
1374
+ setElement(this, element, dataSource, opts, processBarData);
1375
+ },
1376
+ AreaChart: function (element, dataSource, opts) {
1377
+ setElement(this, element, dataSource, opts, processAreaData);
1378
+ },
1379
+ GeoChart: function (element, dataSource, opts) {
1380
+ setElement(this, element, dataSource, opts, processGeoData);
1381
+ },
1382
+ ScatterChart: function (element, dataSource, opts) {
1383
+ setElement(this, element, dataSource, opts, processScatterData);
1384
+ },
1385
+ Timeline: function (element, dataSource, opts) {
1386
+ setElement(this, element, dataSource, opts, processTimelineData);
1387
+ },
1388
+ charts: {}
1389
+ };
1390
+
1391
+ if (typeof module === "object" && typeof module.exports === "object") {
1392
+ module.exports = Chartkick;
1393
+ } else {
1394
+ window.Chartkick = Chartkick;
1395
+ }
1396
+ }(window));