thm 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
data/js/chartkick.js ADDED
@@ -0,0 +1,829 @@
1
+ /*
2
+ * Chartkick.js
3
+ * Create beautiful Javascript charts with minimal code
4
+ * https://github.com/ankane/chartkick.js
5
+ * v1.2.2
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
+
17
+ // helpers
18
+
19
+ function isArray(variable) {
20
+ return Object.prototype.toString.call(variable) === "[object Array]";
21
+ }
22
+
23
+ function isFunction(variable) {
24
+ return variable instanceof Function;
25
+ }
26
+
27
+ function isPlainObject(variable) {
28
+ return !isFunction(variable) && variable instanceof Object;
29
+ }
30
+
31
+ // https://github.com/madrobby/zepto/blob/master/src/zepto.js
32
+ function extend(target, source) {
33
+ var key;
34
+ for (key in source) {
35
+ if (isPlainObject(source[key]) || isArray(source[key])) {
36
+ if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
37
+ target[key] = {};
38
+ }
39
+ if (isArray(source[key]) && !isArray(target[key])) {
40
+ target[key] = [];
41
+ }
42
+ extend(target[key], source[key]);
43
+ } else if (source[key] !== undefined) {
44
+ target[key] = source[key];
45
+ }
46
+ }
47
+ }
48
+
49
+ function merge(obj1, obj2) {
50
+ var target = {};
51
+ extend(target, obj1);
52
+ extend(target, obj2);
53
+ return target;
54
+ }
55
+
56
+ // https://github.com/Do/iso8601.js
57
+ ISO8601_PATTERN = /(\d\d\d\d)(\-)?(\d\d)(\-)?(\d\d)(T)?(\d\d)(:)?(\d\d)?(:)?(\d\d)?([\.,]\d+)?($|Z|([\+\-])(\d\d)(:)?(\d\d)?)/i;
58
+ DECIMAL_SEPARATOR = String(1.5).charAt(1);
59
+
60
+ function parseISO8601(input) {
61
+ var day, hour, matches, milliseconds, minutes, month, offset, result, seconds, type, year;
62
+ type = Object.prototype.toString.call(input);
63
+ if (type === '[object Date]') {
64
+ return input;
65
+ }
66
+ if (type !== '[object String]') {
67
+ return;
68
+ }
69
+ if (matches = input.match(ISO8601_PATTERN)) {
70
+ year = parseInt(matches[1], 10);
71
+ month = parseInt(matches[3], 10) - 1;
72
+ day = parseInt(matches[5], 10);
73
+ hour = parseInt(matches[7], 10);
74
+ minutes = matches[9] ? parseInt(matches[9], 10) : 0;
75
+ seconds = matches[11] ? parseInt(matches[11], 10) : 0;
76
+ milliseconds = matches[12] ? parseFloat(DECIMAL_SEPARATOR + matches[12].slice(1)) * 1000 : 0;
77
+ result = Date.UTC(year, month, day, hour, minutes, seconds, milliseconds);
78
+ if (matches[13] && matches[14]) {
79
+ offset = matches[15] * 60;
80
+ if (matches[17]) {
81
+ offset += parseInt(matches[17], 10);
82
+ }
83
+ offset *= matches[14] === '-' ? -1 : 1;
84
+ result -= offset * 60 * 1000;
85
+ }
86
+ return new Date(result);
87
+ }
88
+ }
89
+ // end iso8601.js
90
+
91
+ function negativeValues(series) {
92
+ var i, j, data;
93
+ for (i = 0; i < series.length; i++) {
94
+ data = series[i].data;
95
+ for (j = 0; j < data.length; j++) {
96
+ if (data[j][1] < 0) {
97
+ return true;
98
+ }
99
+ }
100
+ }
101
+ return false;
102
+ }
103
+
104
+ function jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked) {
105
+ return function (series, opts, chartOptions) {
106
+ var options = merge({}, defaultOptions);
107
+ options = merge(options, chartOptions || {});
108
+
109
+ // hide legend
110
+ // this is *not* an external option!
111
+ if (opts.hideLegend) {
112
+ hideLegend(options);
113
+ }
114
+
115
+ // min
116
+ if ("min" in opts) {
117
+ setMin(options, opts.min);
118
+ } else if (!negativeValues(series)) {
119
+ setMin(options, 0);
120
+ }
121
+
122
+ // max
123
+ if ("max" in opts) {
124
+ setMax(options, opts.max);
125
+ }
126
+
127
+ if (opts.stacked) {
128
+ setStacked(options);
129
+ }
130
+
131
+ if (opts.colors) {
132
+ options.colors = opts.colors;
133
+ }
134
+
135
+ // merge library last
136
+ options = merge(options, opts.library || {});
137
+
138
+ return options;
139
+ };
140
+ }
141
+
142
+ function setText(element, text) {
143
+ if (document.body.innerText) {
144
+ element.innerText = text;
145
+ } else {
146
+ element.textContent = text;
147
+ }
148
+ }
149
+
150
+ function chartError(element, message) {
151
+ setText(element, "Error Loading Chart: " + message);
152
+ element.style.color = "#ff0000";
153
+ }
154
+
155
+ function getJSON(element, url, success) {
156
+ var $ = window.jQuery || window.Zepto || window.$;
157
+ $.ajax({
158
+ dataType: "json",
159
+ url: url,
160
+ success: success,
161
+ error: function (jqXHR, textStatus, errorThrown) {
162
+ var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
163
+ chartError(element, message);
164
+ }
165
+ });
166
+ }
167
+
168
+ function errorCatcher(chart, callback) {
169
+ try {
170
+ callback(chart);
171
+ } catch (err) {
172
+ chartError(chart.element, err.message);
173
+ throw err;
174
+ }
175
+ }
176
+
177
+ function fetchDataSource(chart, callback) {
178
+ if (typeof chart.dataSource === "string") {
179
+ getJSON(chart.element, chart.dataSource, function (data, textStatus, jqXHR) {
180
+ chart.data = data;
181
+ errorCatcher(chart, callback);
182
+ });
183
+ } else {
184
+ chart.data = chart.dataSource;
185
+ errorCatcher(chart, callback);
186
+ }
187
+ }
188
+
189
+ // type conversions
190
+
191
+ function toStr(n) {
192
+ return "" + n;
193
+ }
194
+
195
+ function toFloat(n) {
196
+ return parseFloat(n);
197
+ }
198
+
199
+ function toDate(n) {
200
+ if (typeof n !== "object") {
201
+ if (typeof n === "number") {
202
+ n = new Date(n * 1000); // ms
203
+ } else { // str
204
+ // try our best to get the str into iso8601
205
+ // TODO be smarter about this
206
+ var str = n.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
207
+ n = parseISO8601(str) || new Date(n);
208
+ }
209
+ }
210
+ return n;
211
+ }
212
+
213
+ function toArr(n) {
214
+ if (!isArray(n)) {
215
+ var arr = [], i;
216
+ for (i in n) {
217
+ if (n.hasOwnProperty(i)) {
218
+ arr.push([i, n[i]]);
219
+ }
220
+ }
221
+ n = arr;
222
+ }
223
+ return n;
224
+ }
225
+
226
+ function sortByTime(a, b) {
227
+ return a[0].getTime() - b[0].getTime();
228
+ }
229
+
230
+ if ("Highcharts" in window) {
231
+ var HighchartsAdapter = new function () {
232
+ var Highcharts = window.Highcharts;
233
+
234
+ var defaultOptions = {
235
+ chart: {},
236
+ xAxis: {
237
+ labels: {
238
+ style: {
239
+ fontSize: "12px"
240
+ }
241
+ }
242
+ },
243
+ yAxis: {
244
+ title: {
245
+ text: null
246
+ },
247
+ labels: {
248
+ style: {
249
+ fontSize: "12px"
250
+ }
251
+ }
252
+ },
253
+ title: {
254
+ text: null
255
+ },
256
+ credits: {
257
+ enabled: false
258
+ },
259
+ legend: {
260
+ borderWidth: 0
261
+ },
262
+ tooltip: {
263
+ style: {
264
+ fontSize: "12px"
265
+ }
266
+ },
267
+ plotOptions: {
268
+ areaspline: {},
269
+ series: {
270
+ marker: {}
271
+ }
272
+ }
273
+ };
274
+
275
+ var hideLegend = function (options) {
276
+ options.legend.enabled = false;
277
+ };
278
+
279
+ var setMin = function (options, min) {
280
+ options.yAxis.min = min;
281
+ };
282
+
283
+ var setMax = function (options, max) {
284
+ options.yAxis.max = max;
285
+ };
286
+
287
+ var setStacked = function (options) {
288
+ options.plotOptions.series.stacking = "normal";
289
+ };
290
+
291
+ var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked);
292
+
293
+ this.renderLineChart = function (chart, chartType) {
294
+ chartType = chartType || "spline";
295
+ var chartOptions = {};
296
+ if (chartType === "areaspline") {
297
+ chartOptions = {
298
+ plotOptions: {
299
+ areaspline: {
300
+ stacking: "normal"
301
+ },
302
+ series: {
303
+ marker: {
304
+ enabled: false
305
+ }
306
+ }
307
+ }
308
+ };
309
+ }
310
+ var options = jsOptions(chart.data, chart.options, chartOptions), data, i, j;
311
+ options.xAxis.type = chart.options.discrete ? "category" : "datetime";
312
+ options.chart.type = chartType;
313
+ options.chart.renderTo = chart.element.id;
314
+
315
+ var series = chart.data;
316
+ for (i = 0; i < series.length; i++) {
317
+ data = series[i].data;
318
+ if (!chart.options.discrete) {
319
+ for (j = 0; j < data.length; j++) {
320
+ data[j][0] = data[j][0].getTime();
321
+ }
322
+ }
323
+ series[i].marker = {symbol: "circle"};
324
+ }
325
+ options.series = series;
326
+ new Highcharts.Chart(options);
327
+ };
328
+
329
+ this.renderPieChart = function (chart) {
330
+ var chartOptions = {};
331
+ if (chart.options.colors) {
332
+ chartOptions.colors = chart.options.colors;
333
+ }
334
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
335
+ options.chart.renderTo = chart.element.id;
336
+ options.series = [{
337
+ type: "pie",
338
+ name: "Value",
339
+ data: chart.data
340
+ }];
341
+ new Highcharts.Chart(options);
342
+ };
343
+
344
+ this.renderColumnChart = function (chart, chartType) {
345
+ var chartType = chartType || "column";
346
+ var series = chart.data;
347
+ var options = jsOptions(series, chart.options), i, j, s, d, rows = [];
348
+ options.chart.type = chartType;
349
+ options.chart.renderTo = chart.element.id;
350
+
351
+ for (i = 0; i < series.length; i++) {
352
+ s = series[i];
353
+
354
+ for (j = 0; j < s.data.length; j++) {
355
+ d = s.data[j];
356
+ if (!rows[d[0]]) {
357
+ rows[d[0]] = new Array(series.length);
358
+ }
359
+ rows[d[0]][i] = d[1];
360
+ }
361
+ }
362
+
363
+ var categories = [];
364
+ for (i in rows) {
365
+ if (rows.hasOwnProperty(i)) {
366
+ categories.push(i);
367
+ }
368
+ }
369
+ options.xAxis.categories = categories;
370
+
371
+ var newSeries = [];
372
+ for (i = 0; i < series.length; i++) {
373
+ d = [];
374
+ for (j = 0; j < categories.length; j++) {
375
+ d.push(rows[categories[j]][i] || 0);
376
+ }
377
+
378
+ newSeries.push({
379
+ name: series[i].name,
380
+ data: d
381
+ });
382
+ }
383
+ options.series = newSeries;
384
+
385
+ new Highcharts.Chart(options);
386
+ };
387
+
388
+ var self = this;
389
+
390
+ this.renderBarChart = function (chart) {
391
+ self.renderColumnChart(chart, "bar");
392
+ };
393
+
394
+ this.renderAreaChart = function (chart) {
395
+ self.renderLineChart(chart, "areaspline");
396
+ };
397
+ };
398
+ adapters.push(HighchartsAdapter);
399
+ }
400
+ if (window.google && window.google.setOnLoadCallback) {
401
+ var GoogleChartsAdapter = new function () {
402
+ var google = window.google;
403
+
404
+ var loaded = {};
405
+ var callbacks = [];
406
+
407
+ var runCallbacks = function () {
408
+ var cb, call;
409
+ for (var i = 0; i < callbacks.length; i++) {
410
+ cb = callbacks[i];
411
+ call = google.visualization && ((cb.pack == "corechart" && google.visualization.LineChart) || (cb.pack == "timeline" && google.visualization.Timeline))
412
+ if (call) {
413
+ cb.callback();
414
+ callbacks.splice(i, 1);
415
+ i--;
416
+ }
417
+ }
418
+ };
419
+
420
+ var waitForLoaded = function (pack, callback) {
421
+ if (!callback) {
422
+ callback = pack;
423
+ pack = "corechart";
424
+ }
425
+
426
+ callbacks.push({pack: pack, callback: callback});
427
+
428
+ if (loaded[pack]) {
429
+ runCallbacks();
430
+ } else {
431
+ loaded[pack] = true;
432
+
433
+ // https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
434
+ var loadOptions = {
435
+ packages: [pack],
436
+ callback: runCallbacks
437
+ };
438
+ if (config.language) {
439
+ loadOptions.language = config.language;
440
+ }
441
+ google.load("visualization", "1", loadOptions);
442
+ }
443
+ };
444
+
445
+ // Set chart options
446
+ var defaultOptions = {
447
+ chartArea: {},
448
+ fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
449
+ pointSize: 6,
450
+ legend: {
451
+ textStyle: {
452
+ fontSize: 12,
453
+ color: "#444"
454
+ },
455
+ alignment: "center",
456
+ position: "right"
457
+ },
458
+ curveType: "function",
459
+ hAxis: {
460
+ textStyle: {
461
+ color: "#666",
462
+ fontSize: 12
463
+ },
464
+ gridlines: {
465
+ color: "transparent"
466
+ },
467
+ baselineColor: "#ccc",
468
+ viewWindow: {}
469
+ },
470
+ vAxis: {
471
+ textStyle: {
472
+ color: "#666",
473
+ fontSize: 12
474
+ },
475
+ baselineColor: "#ccc",
476
+ viewWindow: {}
477
+ },
478
+ tooltip: {
479
+ textStyle: {
480
+ color: "#666",
481
+ fontSize: 12
482
+ }
483
+ }
484
+ };
485
+
486
+ var hideLegend = function (options) {
487
+ options.legend.position = "none";
488
+ };
489
+
490
+ var setMin = function (options, min) {
491
+ options.vAxis.viewWindow.min = min;
492
+ };
493
+
494
+ var setMax = function (options, max) {
495
+ options.vAxis.viewWindow.max = max;
496
+ };
497
+
498
+ var setBarMin = function (options, min) {
499
+ options.hAxis.viewWindow.min = min;
500
+ };
501
+
502
+ var setBarMax = function (options, max) {
503
+ options.hAxis.viewWindow.max = max;
504
+ };
505
+
506
+ var setStacked = function (options) {
507
+ options.isStacked = true;
508
+ };
509
+
510
+ var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setStacked);
511
+
512
+ // cant use object as key
513
+ var createDataTable = function (series, columnType) {
514
+ var data = new google.visualization.DataTable();
515
+ data.addColumn(columnType, "");
516
+
517
+ var i, j, s, d, key, rows = [];
518
+ for (i = 0; i < series.length; i++) {
519
+ s = series[i];
520
+ data.addColumn("number", s.name);
521
+
522
+ for (j = 0; j < s.data.length; j++) {
523
+ d = s.data[j];
524
+ key = (columnType === "datetime") ? d[0].getTime() : d[0];
525
+ if (!rows[key]) {
526
+ rows[key] = new Array(series.length);
527
+ }
528
+ rows[key][i] = toFloat(d[1]);
529
+ }
530
+ }
531
+
532
+ var rows2 = [];
533
+ for (i in rows) {
534
+ if (rows.hasOwnProperty(i)) {
535
+ rows2.push([(columnType === "datetime") ? new Date(toFloat(i)) : i].concat(rows[i]));
536
+ }
537
+ }
538
+ if (columnType === "datetime") {
539
+ rows2.sort(sortByTime);
540
+ }
541
+ data.addRows(rows2);
542
+
543
+ return data;
544
+ };
545
+
546
+ var resize = function (callback) {
547
+ if (window.attachEvent) {
548
+ window.attachEvent("onresize", callback);
549
+ } else if (window.addEventListener) {
550
+ window.addEventListener("resize", callback, true);
551
+ }
552
+ callback();
553
+ };
554
+
555
+ this.renderLineChart = function (chart) {
556
+ waitForLoaded(function () {
557
+ var options = jsOptions(chart.data, chart.options);
558
+ var data = createDataTable(chart.data, chart.options.discrete ? "string" : "datetime");
559
+ chart.chart = new google.visualization.LineChart(chart.element);
560
+ resize(function () {
561
+ chart.chart.draw(data, options);
562
+ });
563
+ });
564
+ };
565
+
566
+ this.renderPieChart = function (chart) {
567
+ waitForLoaded(function () {
568
+ var chartOptions = {
569
+ chartArea: {
570
+ top: "10%",
571
+ height: "80%"
572
+ }
573
+ };
574
+ if (chart.options.colors) {
575
+ chartOptions.colors = chart.options.colors;
576
+ }
577
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
578
+
579
+ var data = new google.visualization.DataTable();
580
+ data.addColumn("string", "");
581
+ data.addColumn("number", "Value");
582
+ data.addRows(chart.data);
583
+
584
+ chart.chart = new google.visualization.PieChart(chart.element);
585
+ resize(function () {
586
+ chart.chart.draw(data, options);
587
+ });
588
+ });
589
+ };
590
+
591
+ this.renderColumnChart = function (chart) {
592
+ waitForLoaded(function () {
593
+ var options = jsOptions(chart.data, chart.options);
594
+ var data = createDataTable(chart.data, "string");
595
+ chart.chart = new google.visualization.ColumnChart(chart.element);
596
+ resize(function () {
597
+ chart.chart.draw(data, options);
598
+ });
599
+ });
600
+ };
601
+
602
+ this.renderBarChart = function (chart) {
603
+ waitForLoaded(function () {
604
+ var chartOptions = {
605
+ hAxis: {
606
+ gridlines: {
607
+ color: "#ccc"
608
+ }
609
+ }
610
+ };
611
+ var options = jsOptionsFunc(defaultOptions, hideLegend, setBarMin, setBarMax, setStacked)(chart.data, chart.options, chartOptions);
612
+ var data = createDataTable(chart.data, "string");
613
+ chart.chart = new google.visualization.BarChart(chart.element);
614
+ resize(function () {
615
+ chart.chart.draw(data, options);
616
+ });
617
+ });
618
+ };
619
+
620
+ this.renderAreaChart = function (chart) {
621
+ waitForLoaded(function () {
622
+ var chartOptions = {
623
+ isStacked: true,
624
+ pointSize: 0,
625
+ areaOpacity: 0.5
626
+ };
627
+ var options = jsOptions(chart.data, chart.options, chartOptions);
628
+ var data = createDataTable(chart.data, chart.options.discrete ? "string" : "datetime");
629
+ chart.chart = new google.visualization.AreaChart(chart.element);
630
+ resize(function () {
631
+ chart.chart.draw(data, options);
632
+ });
633
+ });
634
+ };
635
+
636
+ this.renderGeoChart = function (chart) {
637
+ waitForLoaded(function () {
638
+ var chartOptions = {
639
+ legend: "none",
640
+ colorAxis: {
641
+ colors: chart.options.colors || ["#f6c7b6", "#ce502d"]
642
+ }
643
+ };
644
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
645
+
646
+ var data = new google.visualization.DataTable();
647
+ data.addColumn("string", "");
648
+ data.addColumn("number", "Value");
649
+ data.addRows(chart.data);
650
+
651
+ chart.chart = new google.visualization.GeoChart(chart.element);
652
+ resize(function () {
653
+ chart.chart.draw(data, options);
654
+ });
655
+ });
656
+ };
657
+
658
+ this.renderTimeline = function (chart) {
659
+ waitForLoaded("timeline", function () {
660
+ var chartOptions = {
661
+ legend: "none"
662
+ };
663
+
664
+ if (chart.options.colors) {
665
+ chartOptions.colorAxis.colors = chart.options.colors;
666
+ }
667
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
668
+
669
+ var data = new google.visualization.DataTable();
670
+ data.addColumn({type: "string", id: "Name"});
671
+ data.addColumn({type: "date", id: "Start"});
672
+ data.addColumn({type: "date", id: "End"});
673
+ data.addRows(chart.data);
674
+
675
+ chart.chart = new google.visualization.Timeline(chart.element);
676
+
677
+ resize(function () {
678
+ chart.chart.draw(data, options);
679
+ });
680
+ });
681
+ };
682
+ };
683
+
684
+ adapters.push(GoogleChartsAdapter);
685
+ }
686
+
687
+ // TODO add adapter option
688
+ // TODO remove chartType if cross-browser way
689
+ // to get the name of the chart class
690
+ function renderChart(chartType, chart) {
691
+ var i, adapter, fnName;
692
+ fnName = "render" + chartType;
693
+
694
+ for (i = 0; i < adapters.length; i++) {
695
+ adapter = adapters[i];
696
+ if (isFunction(adapter[fnName])) {
697
+ return adapter[fnName](chart);
698
+ }
699
+ }
700
+ throw new Error("No adapter found");
701
+ }
702
+
703
+ // process data
704
+
705
+ function processSeries(series, opts, time) {
706
+ var i, j, data, r, key;
707
+
708
+ // see if one series or multiple
709
+ if (!isArray(series) || typeof series[0] !== "object" || isArray(series[0])) {
710
+ series = [{name: "Value", data: series}];
711
+ opts.hideLegend = true;
712
+ } else {
713
+ opts.hideLegend = false;
714
+ }
715
+ if (opts.discrete) {
716
+ time = false;
717
+ }
718
+
719
+ // right format
720
+ for (i = 0; i < series.length; i++) {
721
+ data = toArr(series[i].data);
722
+ r = [];
723
+ for (j = 0; j < data.length; j++) {
724
+ key = data[j][0];
725
+ key = time ? toDate(key) : toStr(key);
726
+ r.push([key, toFloat(data[j][1])]);
727
+ }
728
+ if (time) {
729
+ r.sort(sortByTime);
730
+ }
731
+ series[i].data = r;
732
+ }
733
+
734
+ return series;
735
+ }
736
+
737
+ function processSimple(data) {
738
+ var perfectData = toArr(data), i;
739
+ for (i = 0; i < perfectData.length; i++) {
740
+ perfectData[i] = [toStr(perfectData[i][0]), toFloat(perfectData[i][1])];
741
+ }
742
+ return perfectData;
743
+ }
744
+
745
+ function processTime(data)
746
+ {
747
+ var i;
748
+ for (i = 0; i < data.length; i++) {
749
+ data[i][1] = toDate(data[i][1]);
750
+ data[i][2] = toDate(data[i][2]);
751
+ }
752
+ return data;
753
+ }
754
+
755
+ function processLineData(chart) {
756
+ chart.data = processSeries(chart.data, chart.options, true);
757
+ renderChart("LineChart", chart);
758
+ }
759
+
760
+ function processColumnData(chart) {
761
+ chart.data = processSeries(chart.data, chart.options, false);
762
+ renderChart("ColumnChart", chart);
763
+ }
764
+
765
+ function processPieData(chart) {
766
+ chart.data = processSimple(chart.data);
767
+ renderChart("PieChart", chart);
768
+ }
769
+
770
+ function processBarData(chart) {
771
+ chart.data = processSeries(chart.data, chart.options, false);
772
+ renderChart("BarChart", chart);
773
+ }
774
+
775
+ function processAreaData(chart) {
776
+ chart.data = processSeries(chart.data, chart.options, true);
777
+ renderChart("AreaChart", chart);
778
+ }
779
+
780
+ function processGeoData(chart) {
781
+ chart.data = processSimple(chart.data);
782
+ renderChart("GeoChart", chart);
783
+ }
784
+
785
+ function processTimelineData(chart) {
786
+ chart.data = processTime(chart.data);
787
+ renderChart("Timeline", chart);
788
+ }
789
+
790
+ function setElement(chart, element, dataSource, opts, callback) {
791
+ if (typeof element === "string") {
792
+ element = document.getElementById(element);
793
+ }
794
+ chart.element = element;
795
+ chart.options = opts || {};
796
+ chart.dataSource = dataSource;
797
+ Chartkick.charts[element.id] = chart;
798
+ fetchDataSource(chart, callback);
799
+ }
800
+
801
+ // define classes
802
+
803
+ Chartkick = {
804
+ LineChart: function (element, dataSource, opts) {
805
+ setElement(this, element, dataSource, opts, processLineData);
806
+ },
807
+ PieChart: function (element, dataSource, opts) {
808
+ setElement(this, element, dataSource, opts, processPieData);
809
+ },
810
+ ColumnChart: function (element, dataSource, opts) {
811
+ setElement(this, element, dataSource, opts, processColumnData);
812
+ },
813
+ BarChart: function (element, dataSource, opts) {
814
+ setElement(this, element, dataSource, opts, processBarData);
815
+ },
816
+ AreaChart: function (element, dataSource, opts) {
817
+ setElement(this, element, dataSource, opts, processAreaData);
818
+ },
819
+ GeoChart: function (element, dataSource, opts) {
820
+ setElement(this, element, dataSource, opts, processGeoData);
821
+ },
822
+ Timeline: function (element, dataSource, opts) {
823
+ setElement(this, element, dataSource, opts, processTimelineData);
824
+ },
825
+ charts: {}
826
+ };
827
+
828
+ window.Chartkick = Chartkick;
829
+ }(window));