SimpleOutput 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2a7e643350511dcfb0e3351745572e51a562323b
4
+ data.tar.gz: be3428569ff46dd937087c0b51f786a3831be680
5
+ SHA512:
6
+ metadata.gz: cceff15a470c80cfea512a515dcdcdc452b063ccc27d1d5817aec35c2e3985ae1b9d5888cd60784c923c0f62209478a9bf276de12420e3150023b17fa256cd88
7
+ data.tar.gz: 1b4711124db0ae46bffbdcb3dd944c28464ec012626c6552b2d3f4b679c29c9414701b9927f4fb348430f4863d8e096a9e3e7ac9f2d27d74ebb62d49ce1e973f
data/LICENSE ADDED
@@ -0,0 +1,191 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ All works
179
+ Copyright 2014 Austen Higgins-Cassidy
180
+
181
+ Licensed under the Apache License, Version 2.0 (the "License");
182
+ you may not use this file except in compliance with the License.
183
+ You may obtain a copy of the License at
184
+
185
+ http://www.apache.org/licenses/LICENSE-2.0
186
+
187
+ Unless required by applicable law or agreed to in writing, software
188
+ distributed under the License is distributed on an "AS IS" BASIS,
189
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190
+ See the License for the specific language governing permissions and
191
+ limitations under the License.
@@ -0,0 +1,759 @@
1
+ /*
2
+ * Chartkick.js
3
+ * Create beautiful Javascript charts with minimal code
4
+ * https://github.com/ankane/chartkick.js
5
+ * v1.2.0
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 Chartkick, ISO8601_PATTERN, DECIMAL_SEPARATOR, adapters = [];
15
+
16
+ var $ = window.jQuery || window.Zepto || window.$;
17
+
18
+ // helpers
19
+
20
+ function isArray(variable) {
21
+ return Object.prototype.toString.call(variable) === "[object Array]";
22
+ }
23
+
24
+ function isFunction(variable) {
25
+ return variable instanceof Function;
26
+ }
27
+
28
+ function isPlainObject(variable) {
29
+ return !isFunction(variable) && variable instanceof Object;
30
+ }
31
+
32
+ // https://github.com/madrobby/zepto/blob/master/src/zepto.js
33
+ function extend(target, source) {
34
+ var key;
35
+ for (key in source) {
36
+ if (isPlainObject(source[key]) || isArray(source[key])) {
37
+ if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
38
+ target[key] = {};
39
+ }
40
+ if (isArray(source[key]) && !isArray(target[key])) {
41
+ target[key] = [];
42
+ }
43
+ extend(target[key], source[key]);
44
+ } else if (source[key] !== undefined) {
45
+ target[key] = source[key];
46
+ }
47
+ }
48
+ }
49
+
50
+ function merge(obj1, obj2) {
51
+ var target = {};
52
+ extend(target, obj1);
53
+ extend(target, obj2);
54
+ return target;
55
+ }
56
+
57
+ // https://github.com/Do/iso8601.js
58
+ ISO8601_PATTERN = /(\d\d\d\d)(\-)?(\d\d)(\-)?(\d\d)(T)?(\d\d)(:)?(\d\d)?(:)?(\d\d)?([\.,]\d+)?($|Z|([\+\-])(\d\d)(:)?(\d\d)?)/i;
59
+ DECIMAL_SEPARATOR = String(1.5).charAt(1);
60
+
61
+ function parseISO8601(input) {
62
+ var day, hour, matches, milliseconds, minutes, month, offset, result, seconds, type, year;
63
+ type = Object.prototype.toString.call(input);
64
+ if (type === '[object Date]') {
65
+ return input;
66
+ }
67
+ if (type !== '[object String]') {
68
+ return;
69
+ }
70
+ if (matches = input.match(ISO8601_PATTERN)) {
71
+ year = parseInt(matches[1], 10);
72
+ month = parseInt(matches[3], 10) - 1;
73
+ day = parseInt(matches[5], 10);
74
+ hour = parseInt(matches[7], 10);
75
+ minutes = matches[9] ? parseInt(matches[9], 10) : 0;
76
+ seconds = matches[11] ? parseInt(matches[11], 10) : 0;
77
+ milliseconds = matches[12] ? parseFloat(DECIMAL_SEPARATOR + matches[12].slice(1)) * 1000 : 0;
78
+ result = Date.UTC(year, month, day, hour, minutes, seconds, milliseconds);
79
+ if (matches[13] && matches[14]) {
80
+ offset = matches[15] * 60;
81
+ if (matches[17]) {
82
+ offset += parseInt(matches[17], 10);
83
+ }
84
+ offset *= matches[14] === '-' ? -1 : 1;
85
+ result -= offset * 60 * 1000;
86
+ }
87
+ return new Date(result);
88
+ }
89
+ }
90
+ // end iso8601.js
91
+
92
+ function negativeValues(series) {
93
+ var i, j, data;
94
+ for (i = 0; i < series.length; i++) {
95
+ data = series[i].data;
96
+ for (j = 0; j < data.length; j++) {
97
+ if (data[j][1] < 0) {
98
+ return true;
99
+ }
100
+ }
101
+ }
102
+ return false;
103
+ }
104
+
105
+ function jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setFormat, setStacked) {
106
+ return function (series, opts, chartOptions) {
107
+ var options = merge({}, defaultOptions);
108
+ options = merge(options, chartOptions || {});
109
+
110
+ // hide legend
111
+ // this is *not* an external option!
112
+ if (opts.hideLegend) {
113
+ hideLegend(options);
114
+ }
115
+
116
+ // min
117
+ if ("min" in opts) {
118
+ setMin(options, opts.min);
119
+ } else if (!negativeValues(series)) {
120
+ setMin(options, 0);
121
+ }
122
+
123
+ // max
124
+ if ("max" in opts) {
125
+ setMax(options, opts.max);
126
+ }
127
+
128
+ if ("format" in opts)
129
+ {
130
+ setFormat(options, opts.format)
131
+ }
132
+
133
+ if (opts.stacked) {
134
+ setStacked(options);
135
+ }
136
+
137
+ // merge library last
138
+ options = merge(options, opts.library || {});
139
+
140
+ return options;
141
+ };
142
+ }
143
+
144
+ function setText(element, text) {
145
+ if (document.body.innerText) {
146
+ element.innerText = text;
147
+ } else {
148
+ element.textContent = text;
149
+ }
150
+ }
151
+
152
+ function chartError(element, message) {
153
+ setText(element, "Error Loading Chart: " + message);
154
+ element.style.color = "#ff0000";
155
+ }
156
+
157
+ function getJSON(element, url, success) {
158
+ $.ajax({
159
+ dataType: "json",
160
+ url: url,
161
+ success: success,
162
+ error: function (jqXHR, textStatus, errorThrown) {
163
+ var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
164
+ chartError(element, message);
165
+ }
166
+ });
167
+ }
168
+
169
+ function errorCatcher(chart, callback) {
170
+ try {
171
+ callback(chart);
172
+ } catch (err) {
173
+ chartError(chart.element, err.message);
174
+ throw err;
175
+ }
176
+ }
177
+
178
+ function fetchDataSource(chart, callback) {
179
+ if (typeof chart.dataSource === "string") {
180
+ getJSON(chart.element, chart.dataSource, function (data, textStatus, jqXHR) {
181
+ chart.data = data;
182
+ errorCatcher(chart, callback);
183
+ });
184
+ } else {
185
+ chart.data = chart.dataSource;
186
+ errorCatcher(chart, callback);
187
+ }
188
+ }
189
+
190
+ // type conversions
191
+
192
+ function toStr(n) {
193
+ return "" + n;
194
+ }
195
+
196
+ function toFloat(n) {
197
+ return parseFloat(n);
198
+ }
199
+
200
+ function toDate(n) {
201
+ if (typeof n !== "object") {
202
+ if (typeof n === "number") {
203
+ n = new Date(n * 1000); // ms
204
+ } else { // str
205
+ // try our best to get the str into iso8601
206
+ // TODO be smarter about this
207
+ var str = n.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
208
+ n = parseISO8601(str) || new Date(n);
209
+ }
210
+ }
211
+ return n;
212
+ }
213
+
214
+ function toArr(n) {
215
+ if (!isArray(n)) {
216
+ var arr = [], i;
217
+ for (i in n) {
218
+ if (n.hasOwnProperty(i)) {
219
+ arr.push([i, n[i]]);
220
+ }
221
+ }
222
+ n = arr;
223
+ }
224
+ return n;
225
+ }
226
+
227
+ function sortByTime(a, b) {
228
+ return a[0].getTime() - b[0].getTime();
229
+ }
230
+
231
+ if ("Highcharts" in window) {
232
+ var HighchartsAdapter = new function () {
233
+ var Highcharts = window.Highcharts;
234
+
235
+ var defaultOptions = {
236
+ chart: {},
237
+ xAxis: {
238
+ labels: {
239
+ style: {
240
+ fontSize: "12px"
241
+ }
242
+ },
243
+ },
244
+ xformat: "datetime",
245
+ yAxis: {
246
+ title: {
247
+ text: null
248
+ },
249
+ labels: {
250
+ style: {
251
+ fontSize: "12px"
252
+ }
253
+ }
254
+ },
255
+ title: {
256
+ text: null
257
+ },
258
+ credits: {
259
+ enabled: false
260
+ },
261
+ legend: {
262
+ borderWidth: 0
263
+ },
264
+ tooltip: {
265
+ style: {
266
+ fontSize: "12px"
267
+ }
268
+ },
269
+ plotOptions: {
270
+ areaspline: {},
271
+ series: {
272
+ marker: {}
273
+ }
274
+ }
275
+ };
276
+
277
+ var hideLegend = function (options) {
278
+ options.legend.enabled = false;
279
+ };
280
+
281
+ var setMin = function (options, min) {
282
+ options.yAxis.min = min;
283
+ };
284
+
285
+ var setMax = function (options, max) {
286
+ options.yAxis.max = max;
287
+ };
288
+
289
+ var setFormat = function(options, format){
290
+ options.xformat = format;
291
+ };
292
+
293
+ var setStacked = function (options) {
294
+ options.plotOptions.series.stacking = "normal";
295
+ };
296
+
297
+ var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax, setFormat, setStacked);
298
+
299
+ this.renderLineChart = function (chart, chartType) {
300
+ chartType = chartType || "spline";
301
+ var chartOptions = {};
302
+ if (chartType === "areaspline") {
303
+ chartOptions = {
304
+ plotOptions: {
305
+ areaspline: {
306
+ stacking: "normal"
307
+ },
308
+ series: {
309
+ marker: {
310
+ enabled: false
311
+ }
312
+ }
313
+ }
314
+ };
315
+ }
316
+ var options = jsOptions(chart.data, chart.options, chartOptions), data, i, j;
317
+ options.xAxis.type = options.xformat;
318
+ options.chart.type = chartType;
319
+ options.chart.renderTo = chart.element.id;
320
+
321
+ var series = chart.data;
322
+ for (i = 0; i < series.length; i++) {
323
+ data = series[i].data;
324
+ for (j = 0; j < data.length; j++) {
325
+ data[j][0] = data[j][0].getTime();
326
+ }
327
+ series[i].marker = {symbol: "circle"};
328
+ }
329
+ options.series = series;
330
+ new Highcharts.Chart(options);
331
+ };
332
+
333
+ this.renderPieChart = function (chart) {
334
+ var options = merge(defaultOptions, 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 ("google" in window) {
401
+ var GoogleChartsAdapter = new function () {
402
+ var google = window.google;
403
+
404
+ // load from google
405
+ var loaded = false;
406
+ google.setOnLoadCallback(function () {
407
+ loaded = true;
408
+ });
409
+ google.load("visualization", "1.0", {"packages": ["corechart"]});
410
+
411
+ var waitForLoaded = function (callback) {
412
+ google.setOnLoadCallback(callback); // always do this to prevent race conditions (watch out for other issues due to this)
413
+ if (loaded) {
414
+ callback();
415
+ }
416
+ };
417
+
418
+ // Set chart options
419
+ var defaultOptions = {
420
+ chartArea: {},
421
+ fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
422
+ pointSize: 6,
423
+ legend: {
424
+ textStyle: {
425
+ fontSize: 12,
426
+ color: "#444"
427
+ },
428
+ alignment: "center",
429
+ position: "right"
430
+ },
431
+ curveType: "function",
432
+ xformat: "datetime",
433
+ hAxis: {
434
+ textStyle: {
435
+ color: "#666",
436
+ fontSize: 12
437
+ },
438
+ gridlines: {
439
+ color: "transparent"
440
+ },
441
+ baselineColor: "#ccc",
442
+ viewWindow: {}
443
+ },
444
+ vAxis: {
445
+ textStyle: {
446
+ color: "#666",
447
+ fontSize: 12
448
+ },
449
+ baselineColor: "#ccc",
450
+ viewWindow: {}
451
+ },
452
+ tooltip: {
453
+ textStyle: {
454
+ color: "#666",
455
+ fontSize: 12
456
+ }
457
+ }
458
+ };
459
+
460
+ var hideLegend = function (options) {
461
+ options.legend.position = "none";
462
+ };
463
+
464
+ var setMin = function (options, min) {
465
+ options.vAxis.viewWindow.min = min;
466
+ };
467
+
468
+ var setMax = function (options, max) {
469
+ options.vAxis.viewWindow.max = max;
470
+ };
471
+
472
+ var setFormat = function (options, format)
473
+ {
474
+ options.xformat = format;
475
+ };
476
+
477
+ var setBarMin = function (options, min) {
478
+ options.hAxis.viewWindow.min = min;
479
+ };
480
+
481
+ var setBarMax = function (options, max) {
482
+ options.hAxis.viewWindow.max = max;
483
+ };
484
+
485
+ var setBarFormat = function (options, max) {
486
+ //Stub
487
+ };
488
+
489
+ var setStacked = function (options) {
490
+ options.isStacked = true;
491
+ };
492
+
493
+ var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setMin, setMax,setFormat, setStacked);
494
+
495
+ // cant use object as key
496
+ var createDataTable = function (series, columnType) {
497
+ var data = new google.visualization.DataTable();
498
+ data.addColumn(columnType, "");
499
+
500
+ var i, j, s, d, key, rows = [];
501
+ for (i = 0; i < series.length; i++) {
502
+ s = series[i];
503
+ data.addColumn("number", s.name);
504
+
505
+ for (j = 0; j < s.data.length; j++) {
506
+ d = s.data[j];
507
+ key = (columnType === "datetime") ? d[0].getTime() : d[0];
508
+ if (!rows[key]) {
509
+ rows[key] = new Array(series.length);
510
+ }
511
+ rows[key][i] = toFloat(d[1]);
512
+ }
513
+ }
514
+
515
+ var rows2 = [];
516
+ for (i in rows) {
517
+ if (rows.hasOwnProperty(i)) {
518
+ rows2.push([(columnType === "datetime") ? new Date(toFloat(i)) : i].concat(rows[i]));
519
+ }
520
+ }
521
+ if (columnType === "datetime") {
522
+ rows2.sort(sortByTime);
523
+ }
524
+ data.addRows(rows2);
525
+
526
+ return data;
527
+ };
528
+
529
+ var resize = function (callback) {
530
+ if (window.attachEvent) {
531
+ window.attachEvent("onresize", callback);
532
+ } else if (window.addEventListener) {
533
+ window.addEventListener("resize", callback, true);
534
+ }
535
+ callback();
536
+ };
537
+
538
+ this.renderLineChart = function (chart) {
539
+ waitForLoaded(function () {
540
+ var options = jsOptions(chart.data, chart.options);
541
+ var data = createDataTable(chart.data, options.xformat);
542
+ chart.chart = new google.visualization.LineChart(chart.element);
543
+ resize(function () {
544
+ chart.chart.draw(data, options);
545
+ });
546
+ });
547
+ };
548
+
549
+ this.renderPieChart = function (chart) {
550
+ waitForLoaded(function () {
551
+ var chartOptions = {
552
+ chartArea: {
553
+ top: "10%",
554
+ height: "80%"
555
+ }
556
+ };
557
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
558
+
559
+ var data = new google.visualization.DataTable();
560
+ data.addColumn("string", "");
561
+ data.addColumn("number", "Value");
562
+ data.addRows(chart.data);
563
+
564
+ chart.chart = new google.visualization.PieChart(chart.element);
565
+ resize(function () {
566
+ chart.chart.draw(data, options);
567
+ });
568
+ });
569
+ };
570
+
571
+ this.renderColumnChart = function (chart) {
572
+ waitForLoaded(function () {
573
+ var options = jsOptions(chart.data, chart.options);
574
+ var data = createDataTable(chart.data, "string");
575
+ chart.chart = new google.visualization.ColumnChart(chart.element);
576
+ resize(function () {
577
+ chart.chart.draw(data, options);
578
+ });
579
+ });
580
+ };
581
+
582
+ this.renderBarChart = function (chart) {
583
+ waitForLoaded(function () {
584
+ var chartOptions = {
585
+ hAxis: {
586
+ gridlines: {
587
+ color: "#ccc"
588
+ }
589
+ }
590
+ };
591
+ var options = jsOptionsFunc(defaultOptions, hideLegend, setBarMin, setBarMax, setBarFormat, setStacked)(chart.data, chart.options, chartOptions);
592
+ var data = createDataTable(chart.data, "string");
593
+ chart.chart = new google.visualization.BarChart(chart.element);
594
+ resize(function () {
595
+ chart.chart.draw(data, options);
596
+ });
597
+ });
598
+ };
599
+
600
+ this.renderAreaChart = function (chart) {
601
+ waitForLoaded(function () {
602
+ var chartOptions = {
603
+ isStacked: true,
604
+ pointSize: 0,
605
+ areaOpacity: 0.5
606
+ };
607
+ var options = jsOptions(chart.data, chart.options, chartOptions);
608
+ var data = createDataTable(chart.data, options.xformat);
609
+ chart.chart = new google.visualization.AreaChart(chart.element);
610
+ resize(function () {
611
+ chart.chart.draw(data, options);
612
+ });
613
+ });
614
+ };
615
+
616
+ this.renderGeoChart = function (chart) {
617
+ waitForLoaded(function () {
618
+ var chartOptions = {
619
+ legend: "none"
620
+ };
621
+ var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
622
+
623
+ var data = new google.visualization.DataTable();
624
+ data.addColumn("string", "");
625
+ data.addColumn("number", "Value");
626
+ data.addRows(chart.data);
627
+
628
+ chart.chart = new google.visualization.GeoChart(chart.element);
629
+ resize(function () {
630
+ chart.chart.draw(data, options);
631
+ });
632
+ });
633
+ };
634
+ };
635
+ adapters.push(GoogleChartsAdapter);
636
+ }
637
+
638
+ // TODO add adapter option
639
+ // TODO remove chartType if cross-browser way
640
+ // to get the name of the chart class
641
+ function renderChart(chartType, chart) {
642
+ var i, adapter, fnName;
643
+ fnName = "render" + chartType + "Chart";
644
+
645
+ for (i = 0; i < adapters.length; i++) {
646
+ adapter = adapters[i];
647
+ if (isFunction(adapter[fnName])) {
648
+ return adapter[fnName](chart);
649
+ }
650
+ }
651
+ throw new Error("No adapter found");
652
+ }
653
+
654
+ // process data
655
+
656
+ function processSeries(series, opts, time) {
657
+ var i, j, data, r, key;
658
+
659
+ // see if one series or multiple
660
+ if (!isArray(series) || typeof series[0] !== "object" || isArray(series[0])) {
661
+ series = [{name: "Value", data: series}];
662
+ opts.hideLegend = true;
663
+ } else {
664
+ opts.hideLegend = false;
665
+ }
666
+
667
+ // right format
668
+ for (i = 0; i < series.length; i++) {
669
+ data = toArr(series[i].data);
670
+ r = [];
671
+ for (j = 0; j < data.length; j++) {
672
+ key = data[j][0];
673
+ key = time ? toDate(key) : toStr(key);
674
+ r.push([key, toFloat(data[j][1])]);
675
+ }
676
+ if (time) {
677
+ r.sort(sortByTime);
678
+ }
679
+ series[i].data = r;
680
+ }
681
+
682
+ return series;
683
+ }
684
+
685
+ function processSimple(data) {
686
+ var perfectData = toArr(data), i;
687
+ for (i = 0; i < perfectData.length; i++) {
688
+ perfectData[i] = [toStr(perfectData[i][0]), toFloat(perfectData[i][1])];
689
+ }
690
+ return perfectData;
691
+ }
692
+
693
+ function processLineData(chart) {
694
+ chart.data = processSeries(chart.data, chart.options, false);
695
+ renderChart("Line", chart);
696
+ }
697
+
698
+ function processColumnData(chart) {
699
+ chart.data = processSeries(chart.data, chart.options, false);
700
+ renderChart("Column", chart);
701
+ }
702
+
703
+ function processPieData(chart) {
704
+ chart.data = processSimple(chart.data);
705
+ renderChart("Pie", chart);
706
+ }
707
+
708
+ function processBarData(chart) {
709
+ chart.data = processSeries(chart.data, chart.options, false);
710
+ renderChart("Bar", chart);
711
+ }
712
+
713
+ function processAreaData(chart) {
714
+ chart.data = processSeries(chart.data, chart.options, false);
715
+ renderChart("Area", chart);
716
+ }
717
+
718
+ function processGeoData(chart) {
719
+ chart.data = processSimple(chart.data);
720
+ renderChart("Geo", chart);
721
+ }
722
+
723
+ function setElement(chart, element, dataSource, opts, callback) {
724
+ if (typeof element === "string") {
725
+ element = document.getElementById(element);
726
+ }
727
+ chart.element = element;
728
+ chart.options = opts || {};
729
+ chart.dataSource = dataSource;
730
+ Chartkick.charts[element.id] = chart;
731
+ fetchDataSource(chart, callback);
732
+ }
733
+
734
+ // define classes
735
+
736
+ Chartkick = {
737
+ LineChart: function (element, dataSource, opts) {
738
+ setElement(this, element, dataSource, opts, processLineData);
739
+ },
740
+ PieChart: function (element, dataSource, opts) {
741
+ setElement(this, element, dataSource, opts, processPieData);
742
+ },
743
+ ColumnChart: function (element, dataSource, opts) {
744
+ setElement(this, element, dataSource, opts, processColumnData);
745
+ },
746
+ BarChart: function (element, dataSource, opts) {
747
+ setElement(this, element, dataSource, opts, processBarData);
748
+ },
749
+ AreaChart: function (element, dataSource, opts) {
750
+ setElement(this, element, dataSource, opts, processAreaData);
751
+ },
752
+ GeoChart: function (element, dataSource, opts) {
753
+ setElement(this, element, dataSource, opts, processGeoData);
754
+ },
755
+ charts: {}
756
+ };
757
+
758
+ window.Chartkick = Chartkick;
759
+ }(window));