pghero_fork 2.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +391 -0
  3. data/CONTRIBUTING.md +42 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +3 -0
  6. data/app/assets/images/pghero/favicon.png +0 -0
  7. data/app/assets/javascripts/pghero/Chart.bundle.js +20755 -0
  8. data/app/assets/javascripts/pghero/application.js +158 -0
  9. data/app/assets/javascripts/pghero/chartkick.js +2436 -0
  10. data/app/assets/javascripts/pghero/highlight.pack.js +2 -0
  11. data/app/assets/javascripts/pghero/jquery.js +10872 -0
  12. data/app/assets/javascripts/pghero/nouislider.js +2672 -0
  13. data/app/assets/stylesheets/pghero/application.css +514 -0
  14. data/app/assets/stylesheets/pghero/arduino-light.css +86 -0
  15. data/app/assets/stylesheets/pghero/nouislider.css +310 -0
  16. data/app/controllers/pg_hero/home_controller.rb +449 -0
  17. data/app/helpers/pg_hero/home_helper.rb +30 -0
  18. data/app/views/layouts/pg_hero/application.html.erb +68 -0
  19. data/app/views/pg_hero/home/_connections_table.html.erb +16 -0
  20. data/app/views/pg_hero/home/_live_queries_table.html.erb +51 -0
  21. data/app/views/pg_hero/home/_queries_table.html.erb +72 -0
  22. data/app/views/pg_hero/home/_query_stats_slider.html.erb +16 -0
  23. data/app/views/pg_hero/home/_suggested_index.html.erb +18 -0
  24. data/app/views/pg_hero/home/connections.html.erb +32 -0
  25. data/app/views/pg_hero/home/explain.html.erb +27 -0
  26. data/app/views/pg_hero/home/index.html.erb +518 -0
  27. data/app/views/pg_hero/home/index_bloat.html.erb +72 -0
  28. data/app/views/pg_hero/home/live_queries.html.erb +11 -0
  29. data/app/views/pg_hero/home/maintenance.html.erb +55 -0
  30. data/app/views/pg_hero/home/queries.html.erb +33 -0
  31. data/app/views/pg_hero/home/relation_space.html.erb +14 -0
  32. data/app/views/pg_hero/home/show_query.html.erb +106 -0
  33. data/app/views/pg_hero/home/space.html.erb +83 -0
  34. data/app/views/pg_hero/home/system.html.erb +34 -0
  35. data/app/views/pg_hero/home/tune.html.erb +53 -0
  36. data/config/routes.rb +32 -0
  37. data/lib/generators/pghero/config_generator.rb +13 -0
  38. data/lib/generators/pghero/query_stats_generator.rb +18 -0
  39. data/lib/generators/pghero/space_stats_generator.rb +18 -0
  40. data/lib/generators/pghero/templates/config.yml.tt +46 -0
  41. data/lib/generators/pghero/templates/query_stats.rb.tt +15 -0
  42. data/lib/generators/pghero/templates/space_stats.rb.tt +13 -0
  43. data/lib/pghero.rb +246 -0
  44. data/lib/pghero/connection.rb +5 -0
  45. data/lib/pghero/database.rb +175 -0
  46. data/lib/pghero/engine.rb +16 -0
  47. data/lib/pghero/methods/basic.rb +160 -0
  48. data/lib/pghero/methods/connections.rb +77 -0
  49. data/lib/pghero/methods/constraints.rb +30 -0
  50. data/lib/pghero/methods/explain.rb +29 -0
  51. data/lib/pghero/methods/indexes.rb +332 -0
  52. data/lib/pghero/methods/kill.rb +28 -0
  53. data/lib/pghero/methods/maintenance.rb +93 -0
  54. data/lib/pghero/methods/queries.rb +75 -0
  55. data/lib/pghero/methods/query_stats.rb +349 -0
  56. data/lib/pghero/methods/replication.rb +74 -0
  57. data/lib/pghero/methods/sequences.rb +124 -0
  58. data/lib/pghero/methods/settings.rb +37 -0
  59. data/lib/pghero/methods/space.rb +141 -0
  60. data/lib/pghero/methods/suggested_indexes.rb +329 -0
  61. data/lib/pghero/methods/system.rb +287 -0
  62. data/lib/pghero/methods/tables.rb +68 -0
  63. data/lib/pghero/methods/users.rb +87 -0
  64. data/lib/pghero/query_stats.rb +5 -0
  65. data/lib/pghero/space_stats.rb +5 -0
  66. data/lib/pghero/stats.rb +6 -0
  67. data/lib/pghero/version.rb +3 -0
  68. data/lib/tasks/pghero.rake +27 -0
  69. data/licenses/LICENSE-chart.js.txt +9 -0
  70. data/licenses/LICENSE-chartkick.js.txt +22 -0
  71. data/licenses/LICENSE-highlight.js.txt +29 -0
  72. data/licenses/LICENSE-jquery.txt +20 -0
  73. data/licenses/LICENSE-moment.txt +22 -0
  74. data/licenses/LICENSE-nouislider.txt +21 -0
  75. metadata +130 -0
@@ -0,0 +1,158 @@
1
+ //= require ./jquery
2
+ //= require ./nouislider
3
+ //= require ./Chart.bundle
4
+ //= require ./chartkick
5
+ //= require ./highlight.pack
6
+
7
+ function highlightQueries() {
8
+ $("pre code").each(function(i, block) {
9
+ hljs.highlightBlock(block);
10
+ });
11
+ }
12
+
13
+ function initSlider() {
14
+ function roundTime(time) {
15
+ var period = 1000 * 60 * 5;
16
+ return new Date(Math.ceil(time.getTime() / period) * period);
17
+ }
18
+
19
+ function pad(num) {
20
+ return (num < 10) ? "0" + num : num;
21
+ }
22
+
23
+ var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
24
+
25
+ var days = 1;
26
+ var now = new Date();
27
+ var sliderStartAt = roundTime(now) - days * 24 * 60 * 60 * 1000;
28
+ var sliderMax = 24 * 12 * days;
29
+
30
+ startAt = startAt || sliderStartAt;
31
+ var min = (startAt > 0) ? (startAt - sliderStartAt) / (1000 * 60 * 5) : 0;
32
+
33
+ var max = (endAt > 0) ? (endAt - sliderStartAt) / (1000 * 60 * 5) : sliderMax;
34
+
35
+ var slider = document.getElementById("slider");
36
+
37
+ noUiSlider.create(slider, {
38
+ range: {
39
+ min: 0,
40
+ max: sliderMax
41
+ },
42
+ step: 1,
43
+ connect: true,
44
+ start: [min, max]
45
+ });
46
+
47
+ // remove outline for mouse only
48
+ $(".noUi-handle").mousedown(function() {
49
+ $(this).addClass("no-outline");
50
+ }).blur(function() {
51
+ $(this).removeClass("no-outline");
52
+ });
53
+
54
+ function updateText() {
55
+ var values = slider.noUiSlider.get();
56
+ setText("#range-start", values[0]);
57
+ setText("#range-end", values[1]);
58
+ }
59
+
60
+ function setText(selector, offset) {
61
+ var time = timeAt(offset);
62
+
63
+ var html = "";
64
+ if (time == now) {
65
+ if (selector == "#range-end") {
66
+ html = "Now";
67
+ }
68
+ } else {
69
+ html = time.getDate() + " " + months[time.getMonth()] + " " + pad(time.getHours()) + ":" + pad(time.getMinutes());
70
+ }
71
+ $(selector).html(html);
72
+ }
73
+
74
+ function timeAt(offset) {
75
+ var time = new Date(sliderStartAt + (offset * 5) * 60 * 1000);
76
+ return (time > now) ? now : time;
77
+ }
78
+
79
+ function timeParam(time) {
80
+ return time.toISOString();
81
+ }
82
+
83
+ function queriesPath(params) {
84
+ var path = "queries";
85
+ if (params.start_at || params.end_at || params.sort || params.min_average_time || params.min_calls || params.debug) {
86
+ path += "?" + $.param(params);
87
+ }
88
+ return path;
89
+ }
90
+
91
+ function refreshStats(push) {
92
+ var values = slider.noUiSlider.get();
93
+ var startAt = push ? timeAt(values[0]) : new Date(window.startAt);
94
+ var endAt = timeAt(values[1]);
95
+
96
+ var params = {}
97
+ if (startAt.getTime() != sliderStartAt) {
98
+ params.start_at = timeParam(startAt);
99
+ }
100
+ if (endAt < now) {
101
+ params.end_at = timeParam(endAt);
102
+ }
103
+ if (sort) {
104
+ params.sort = sort;
105
+ }
106
+ if (minAverageTime) {
107
+ params.min_average_time = minAverageTime;
108
+ }
109
+ if (minCalls) {
110
+ params.min_calls = minCalls;
111
+ }
112
+ if (debug) {
113
+ params.debug = debug;
114
+ }
115
+
116
+ var path = queriesPath(params);
117
+
118
+ $(".queries-table th a").each( function () {
119
+ var p = $.extend({}, params, {sort: $(this).data("sort"), min_average_time: minAverageTime, min_calls: minCalls, debug: debug});
120
+ if (!p.sort) {
121
+ delete p.sort;
122
+ }
123
+ if (!p.min_average_time) {
124
+ delete p.min_average_time;
125
+ }
126
+ if (!p.min_calls) {
127
+ delete p.min_calls;
128
+ }
129
+ if (!p.debug) {
130
+ delete p.debug;
131
+ }
132
+ $(this).attr("href", queriesPath(p));
133
+ });
134
+
135
+
136
+ var callback = function (response, status, xhr) {
137
+ if (status === "error" ) {
138
+ $(".queries-info").css("color", "red").html(xhr.status + " " + xhr.statusText);
139
+ } else {
140
+ highlightQueries();
141
+ }
142
+ };
143
+ $("#queries").html('<tr><td colspan="3"><p class="queries-info text-muted">...</p></td></tr>').load(path, callback);
144
+
145
+ if (push && history.pushState) {
146
+ history.pushState(null, null, path);
147
+ }
148
+ }
149
+
150
+ slider.noUiSlider.on("slide", updateText);
151
+ slider.noUiSlider.on("change", function () {
152
+ refreshStats(true);
153
+ });
154
+ updateText();
155
+ $( function () {
156
+ refreshStats(false);
157
+ });
158
+ }
@@ -0,0 +1,2436 @@
1
+ /*
2
+ * Chartkick.js
3
+ * Create beautiful charts with one line of JavaScript
4
+ * https://github.com/ankane/chartkick.js
5
+ * v3.2.0
6
+ * MIT License
7
+ */
8
+
9
+ (function (global, factory) {
10
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
11
+ typeof define === 'function' && define.amd ? define(factory) :
12
+ (global = global || self, global.Chartkick = factory());
13
+ }(this, (function () { 'use strict';
14
+
15
+ function isArray(variable) {
16
+ return Object.prototype.toString.call(variable) === "[object Array]";
17
+ }
18
+
19
+ function isFunction(variable) {
20
+ return variable instanceof Function;
21
+ }
22
+
23
+ function isPlainObject(variable) {
24
+ // protect against prototype pollution, defense 2
25
+ return Object.prototype.toString.call(variable) === "[object Object]" && !isFunction(variable) && variable instanceof Object;
26
+ }
27
+
28
+ // https://github.com/madrobby/zepto/blob/master/src/zepto.js
29
+ function extend(target, source) {
30
+ var key;
31
+ for (key in source) {
32
+ // protect against prototype pollution, defense 1
33
+ if (key === "__proto__") { continue; }
34
+
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
+ var DATE_PATTERN = /^(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)$/i;
57
+
58
+ // https://github.com/Do/iso8601.js
59
+ var 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
+ var 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 toStr(n) {
108
+ return "" + n;
109
+ }
110
+
111
+ function toFloat(n) {
112
+ return parseFloat(n);
113
+ }
114
+
115
+ function toDate(n) {
116
+ var matches, year, month, day;
117
+ if (typeof n !== "object") {
118
+ if (typeof n === "number") {
119
+ n = new Date(n * 1000); // ms
120
+ } else {
121
+ n = toStr(n);
122
+ if ((matches = n.match(DATE_PATTERN))) {
123
+ year = parseInt(matches[1], 10);
124
+ month = parseInt(matches[3], 10) - 1;
125
+ day = parseInt(matches[5], 10);
126
+ return new Date(year, month, day);
127
+ } else { // str
128
+ // try our best to get the str into iso8601
129
+ // TODO be smarter about this
130
+ var str = n.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
131
+ n = parseISO8601(str) || new Date(n);
132
+ }
133
+ }
134
+ }
135
+ return n;
136
+ }
137
+
138
+ function toArr(n) {
139
+ if (!isArray(n)) {
140
+ var arr = [], i;
141
+ for (i in n) {
142
+ if (n.hasOwnProperty(i)) {
143
+ arr.push([i, n[i]]);
144
+ }
145
+ }
146
+ n = arr;
147
+ }
148
+ return n;
149
+ }
150
+
151
+ function jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle) {
152
+ return function (chart, opts, chartOptions) {
153
+ var series = chart.data;
154
+ var options = merge({}, defaultOptions);
155
+ options = merge(options, chartOptions || {});
156
+
157
+ if (chart.hideLegend || "legend" in opts) {
158
+ hideLegend(options, opts.legend, chart.hideLegend);
159
+ }
160
+
161
+ if (opts.title) {
162
+ setTitle(options, opts.title);
163
+ }
164
+
165
+ // min
166
+ if ("min" in opts) {
167
+ setMin(options, opts.min);
168
+ } else if (!negativeValues(series)) {
169
+ setMin(options, 0);
170
+ }
171
+
172
+ // max
173
+ if (opts.max) {
174
+ setMax(options, opts.max);
175
+ }
176
+
177
+ if ("stacked" in opts) {
178
+ setStacked(options, opts.stacked);
179
+ }
180
+
181
+ if (opts.colors) {
182
+ options.colors = opts.colors;
183
+ }
184
+
185
+ if (opts.xtitle) {
186
+ setXtitle(options, opts.xtitle);
187
+ }
188
+
189
+ if (opts.ytitle) {
190
+ setYtitle(options, opts.ytitle);
191
+ }
192
+
193
+ // merge library last
194
+ options = merge(options, opts.library || {});
195
+
196
+ return options;
197
+ };
198
+ }
199
+
200
+ function sortByTime(a, b) {
201
+ return a[0].getTime() - b[0].getTime();
202
+ }
203
+
204
+ function sortByNumberSeries(a, b) {
205
+ return a[0] - b[0];
206
+ }
207
+
208
+ function sortByNumber(a, b) {
209
+ return a - b;
210
+ }
211
+
212
+ function isMinute(d) {
213
+ return d.getMilliseconds() === 0 && d.getSeconds() === 0;
214
+ }
215
+
216
+ function isHour(d) {
217
+ return isMinute(d) && d.getMinutes() === 0;
218
+ }
219
+
220
+ function isDay(d) {
221
+ return isHour(d) && d.getHours() === 0;
222
+ }
223
+
224
+ function isWeek(d, dayOfWeek) {
225
+ return isDay(d) && d.getDay() === dayOfWeek;
226
+ }
227
+
228
+ function isMonth(d) {
229
+ return isDay(d) && d.getDate() === 1;
230
+ }
231
+
232
+ function isYear(d) {
233
+ return isMonth(d) && d.getMonth() === 0;
234
+ }
235
+
236
+ function isDate(obj) {
237
+ return !isNaN(toDate(obj)) && toStr(obj).length >= 6;
238
+ }
239
+
240
+ function isNumber(obj) {
241
+ return typeof obj === "number";
242
+ }
243
+
244
+ var byteSuffixes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB"];
245
+
246
+ function formatValue(pre, value, options, axis) {
247
+ pre = pre || "";
248
+ if (options.prefix) {
249
+ if (value < 0) {
250
+ value = value * -1;
251
+ pre += "-";
252
+ }
253
+ pre += options.prefix;
254
+ }
255
+
256
+ var suffix = options.suffix || "";
257
+ var precision = options.precision;
258
+ var round = options.round;
259
+
260
+ if (options.byteScale) {
261
+ var suffixIdx;
262
+ var baseValue = axis ? options.byteScale : value;
263
+
264
+ if (baseValue >= 1152921504606846976) {
265
+ value /= 1152921504606846976;
266
+ suffixIdx = 6;
267
+ } else if (baseValue >= 1125899906842624) {
268
+ value /= 1125899906842624;
269
+ suffixIdx = 5;
270
+ } else if (baseValue >= 1099511627776) {
271
+ value /= 1099511627776;
272
+ suffixIdx = 4;
273
+ } else if (baseValue >= 1073741824) {
274
+ value /= 1073741824;
275
+ suffixIdx = 3;
276
+ } else if (baseValue >= 1048576) {
277
+ value /= 1048576;
278
+ suffixIdx = 2;
279
+ } else if (baseValue >= 1024) {
280
+ value /= 1024;
281
+ suffixIdx = 1;
282
+ } else {
283
+ suffixIdx = 0;
284
+ }
285
+
286
+ // TODO handle manual precision case
287
+ if (precision === undefined && round === undefined) {
288
+ if (value >= 1023.5) {
289
+ if (suffixIdx < byteSuffixes.length - 1) {
290
+ value = 1.0;
291
+ suffixIdx += 1;
292
+ }
293
+ }
294
+ precision = value >= 1000 ? 4 : 3;
295
+ }
296
+ suffix = " " + byteSuffixes[suffixIdx];
297
+ }
298
+
299
+ if (precision !== undefined && round !== undefined) {
300
+ throw Error("Use either round or precision, not both");
301
+ }
302
+
303
+ if (!axis) {
304
+ if (precision !== undefined) {
305
+ value = value.toPrecision(precision);
306
+ if (!options.zeros) {
307
+ value = parseFloat(value);
308
+ }
309
+ }
310
+
311
+ if (round !== undefined) {
312
+ if (round < 0) {
313
+ var num = Math.pow(10, -1 * round);
314
+ value = parseInt((1.0 * value / num).toFixed(0)) * num;
315
+ } else {
316
+ value = value.toFixed(round);
317
+ if (!options.zeros) {
318
+ value = parseFloat(value);
319
+ }
320
+ }
321
+ }
322
+ }
323
+
324
+ if (options.thousands || options.decimal) {
325
+ value = toStr(value);
326
+ var parts = value.split(".");
327
+ value = parts[0];
328
+ if (options.thousands) {
329
+ value = value.replace(/\B(?=(\d{3})+(?!\d))/g, options.thousands);
330
+ }
331
+ if (parts.length > 1) {
332
+ value += (options.decimal || ".") + parts[1];
333
+ }
334
+ }
335
+
336
+ return pre + value + suffix;
337
+ }
338
+
339
+ function seriesOption(chart, series, option) {
340
+ if (option in series) {
341
+ return series[option];
342
+ } else if (option in chart.options) {
343
+ return chart.options[option];
344
+ }
345
+ return null;
346
+ }
347
+
348
+ function allZeros(data) {
349
+ var i, j, d;
350
+ for (i = 0; i < data.length; i++) {
351
+ d = data[i].data;
352
+ for (j = 0; j < d.length; j++) {
353
+ if (d[j][1] != 0) {
354
+ return false;
355
+ }
356
+ }
357
+ }
358
+ return true;
359
+ }
360
+
361
+ var baseOptions = {
362
+ maintainAspectRatio: false,
363
+ animation: false,
364
+ tooltips: {
365
+ displayColors: false,
366
+ callbacks: {}
367
+ },
368
+ legend: {},
369
+ title: {fontSize: 20, fontColor: "#333"}
370
+ };
371
+
372
+ var defaultOptions = {
373
+ scales: {
374
+ yAxes: [
375
+ {
376
+ ticks: {
377
+ maxTicksLimit: 4
378
+ },
379
+ scaleLabel: {
380
+ fontSize: 16,
381
+ // fontStyle: "bold",
382
+ fontColor: "#333"
383
+ }
384
+ }
385
+ ],
386
+ xAxes: [
387
+ {
388
+ gridLines: {
389
+ drawOnChartArea: false
390
+ },
391
+ scaleLabel: {
392
+ fontSize: 16,
393
+ // fontStyle: "bold",
394
+ fontColor: "#333"
395
+ },
396
+ time: {},
397
+ ticks: {}
398
+ }
399
+ ]
400
+ }
401
+ };
402
+
403
+ // http://there4.io/2012/05/02/google-chart-color-list/
404
+ var defaultColors = [
405
+ "#3366CC", "#DC3912", "#FF9900", "#109618", "#990099", "#3B3EAC", "#0099C6",
406
+ "#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11",
407
+ "#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#651067"
408
+ ];
409
+
410
+ var hideLegend = function (options, legend, hideLegend) {
411
+ if (legend !== undefined) {
412
+ options.legend.display = !!legend;
413
+ if (legend && legend !== true) {
414
+ options.legend.position = legend;
415
+ }
416
+ } else if (hideLegend) {
417
+ options.legend.display = false;
418
+ }
419
+ };
420
+
421
+ var setTitle = function (options, title) {
422
+ options.title.display = true;
423
+ options.title.text = title;
424
+ };
425
+
426
+ var setMin = function (options, min) {
427
+ if (min !== null) {
428
+ options.scales.yAxes[0].ticks.min = toFloat(min);
429
+ }
430
+ };
431
+
432
+ var setMax = function (options, max) {
433
+ options.scales.yAxes[0].ticks.max = toFloat(max);
434
+ };
435
+
436
+ var setBarMin = function (options, min) {
437
+ if (min !== null) {
438
+ options.scales.xAxes[0].ticks.min = toFloat(min);
439
+ }
440
+ };
441
+
442
+ var setBarMax = function (options, max) {
443
+ options.scales.xAxes[0].ticks.max = toFloat(max);
444
+ };
445
+
446
+ var setStacked = function (options, stacked) {
447
+ options.scales.xAxes[0].stacked = !!stacked;
448
+ options.scales.yAxes[0].stacked = !!stacked;
449
+ };
450
+
451
+ var setXtitle = function (options, title) {
452
+ options.scales.xAxes[0].scaleLabel.display = true;
453
+ options.scales.xAxes[0].scaleLabel.labelString = title;
454
+ };
455
+
456
+ var setYtitle = function (options, title) {
457
+ options.scales.yAxes[0].scaleLabel.display = true;
458
+ options.scales.yAxes[0].scaleLabel.labelString = title;
459
+ };
460
+
461
+ // https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
462
+ var addOpacity = function(hex, opacity) {
463
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
464
+ return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
465
+ };
466
+
467
+ // check if not null or undefined
468
+ // https://stackoverflow.com/a/27757708/1177228
469
+ var notnull = function(x) {
470
+ return x != null;
471
+ };
472
+
473
+ var setLabelSize = function (chart, data, options) {
474
+ var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
475
+ if (maxLabelSize > 25) {
476
+ maxLabelSize = 25;
477
+ } else if (maxLabelSize < 10) {
478
+ maxLabelSize = 10;
479
+ }
480
+ if (!options.scales.xAxes[0].ticks.callback) {
481
+ options.scales.xAxes[0].ticks.callback = function (value) {
482
+ value = toStr(value);
483
+ if (value.length > maxLabelSize) {
484
+ return value.substring(0, maxLabelSize - 2) + "...";
485
+ } else {
486
+ return value;
487
+ }
488
+ };
489
+ }
490
+ };
491
+
492
+ var setFormatOptions = function(chart, options, chartType) {
493
+ var formatOptions = {
494
+ prefix: chart.options.prefix,
495
+ suffix: chart.options.suffix,
496
+ thousands: chart.options.thousands,
497
+ decimal: chart.options.decimal,
498
+ precision: chart.options.precision,
499
+ round: chart.options.round,
500
+ zeros: chart.options.zeros
501
+ };
502
+
503
+ if (chart.options.bytes) {
504
+ var series = chart.data;
505
+ if (chartType === "pie") {
506
+ series = [{data: series}];
507
+ }
508
+
509
+ // calculate max
510
+ var max = 0;
511
+ for (var i = 0; i < series.length; i++) {
512
+ var s = series[i];
513
+ for (var j = 0; j < s.data.length; j++) {
514
+ if (s.data[j][1] > max) {
515
+ max = s.data[j][1];
516
+ }
517
+ }
518
+ }
519
+
520
+ // calculate scale
521
+ var scale = 1;
522
+ while (max >= 1024) {
523
+ scale *= 1024;
524
+ max /= 1024;
525
+ }
526
+
527
+ // set step size
528
+ formatOptions.byteScale = scale;
529
+ }
530
+
531
+ if (chartType !== "pie") {
532
+ var myAxes = options.scales.yAxes;
533
+ if (chartType === "bar") {
534
+ myAxes = options.scales.xAxes;
535
+ }
536
+
537
+ if (formatOptions.byteScale) {
538
+ if (!myAxes[0].ticks.stepSize) {
539
+ myAxes[0].ticks.stepSize = formatOptions.byteScale / 2;
540
+ }
541
+ if (!myAxes[0].ticks.maxTicksLimit) {
542
+ myAxes[0].ticks.maxTicksLimit = 4;
543
+ }
544
+ }
545
+
546
+ if (!myAxes[0].ticks.callback) {
547
+ myAxes[0].ticks.callback = function (value) {
548
+ return formatValue("", value, formatOptions, true);
549
+ };
550
+ }
551
+ }
552
+
553
+ if (!options.tooltips.callbacks.label) {
554
+ if (chartType === "scatter") {
555
+ options.tooltips.callbacks.label = function (item, data) {
556
+ var label = data.datasets[item.datasetIndex].label || '';
557
+ if (label) {
558
+ label += ': ';
559
+ }
560
+ return label + '(' + item.xLabel + ', ' + item.yLabel + ')';
561
+ };
562
+ } else if (chartType === "bubble") {
563
+ options.tooltips.callbacks.label = function (item, data) {
564
+ var label = data.datasets[item.datasetIndex].label || '';
565
+ if (label) {
566
+ label += ': ';
567
+ }
568
+ var dataPoint = data.datasets[item.datasetIndex].data[item.index];
569
+ return label + '(' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.v + ')';
570
+ };
571
+ } else if (chartType === "pie") {
572
+ // need to use separate label for pie charts
573
+ options.tooltips.callbacks.label = function (tooltipItem, data) {
574
+ var dataLabel = data.labels[tooltipItem.index];
575
+ var value = ': ';
576
+
577
+ if (isArray(dataLabel)) {
578
+ // show value on first line of multiline label
579
+ // need to clone because we are changing the value
580
+ dataLabel = dataLabel.slice();
581
+ dataLabel[0] += value;
582
+ } else {
583
+ dataLabel += value;
584
+ }
585
+
586
+ return formatValue(dataLabel, data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index], formatOptions);
587
+ };
588
+ } else {
589
+ var valueLabel = chartType === "bar" ? "xLabel" : "yLabel";
590
+ options.tooltips.callbacks.label = function (tooltipItem, data) {
591
+ var label = data.datasets[tooltipItem.datasetIndex].label || '';
592
+ if (label) {
593
+ label += ': ';
594
+ }
595
+ return formatValue(label, tooltipItem[valueLabel], formatOptions);
596
+ };
597
+ }
598
+ }
599
+ };
600
+
601
+ var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
602
+
603
+ var createDataTable = function (chart, options, chartType, library) {
604
+ var datasets = [];
605
+ var labels = [];
606
+
607
+ var colors = chart.options.colors || defaultColors;
608
+
609
+ var day = true;
610
+ var week = true;
611
+ var dayOfWeek;
612
+ var month = true;
613
+ var year = true;
614
+ var hour = true;
615
+ var minute = true;
616
+
617
+ var series = chart.data;
618
+
619
+ var max = 0;
620
+ if (chartType === "bubble") {
621
+ for (var i$1 = 0; i$1 < series.length; i$1++) {
622
+ var s$1 = series[i$1];
623
+ for (var j$1 = 0; j$1 < s$1.data.length; j$1++) {
624
+ if (s$1.data[j$1][2] > max) {
625
+ max = s$1.data[j$1][2];
626
+ }
627
+ }
628
+ }
629
+ }
630
+
631
+ var i, j, s, d, key, rows = [], rows2 = [];
632
+
633
+ if (chartType === "bar" || chartType === "column" || (chart.xtype !== "number" && chart.xtype !== "bubble")) {
634
+ var sortedLabels = [];
635
+
636
+ for (i = 0; i < series.length; i++) {
637
+ s = series[i];
638
+
639
+ for (j = 0; j < s.data.length; j++) {
640
+ d = s.data[j];
641
+ key = chart.xtype == "datetime" ? d[0].getTime() : d[0];
642
+ if (!rows[key]) {
643
+ rows[key] = new Array(series.length);
644
+ }
645
+ rows[key][i] = toFloat(d[1]);
646
+ if (sortedLabels.indexOf(key) === -1) {
647
+ sortedLabels.push(key);
648
+ }
649
+ }
650
+ }
651
+
652
+ if (chart.xtype === "datetime" || chart.xtype === "number") {
653
+ sortedLabels.sort(sortByNumber);
654
+ }
655
+
656
+ for (j = 0; j < series.length; j++) {
657
+ rows2.push([]);
658
+ }
659
+
660
+ var value;
661
+ var k;
662
+ for (k = 0; k < sortedLabels.length; k++) {
663
+ i = sortedLabels[k];
664
+ if (chart.xtype === "datetime") {
665
+ value = new Date(toFloat(i));
666
+ // TODO make this efficient
667
+ day = day && isDay(value);
668
+ if (!dayOfWeek) {
669
+ dayOfWeek = value.getDay();
670
+ }
671
+ week = week && isWeek(value, dayOfWeek);
672
+ month = month && isMonth(value);
673
+ year = year && isYear(value);
674
+ hour = hour && isHour(value);
675
+ minute = minute && isMinute(value);
676
+ } else {
677
+ value = i;
678
+ }
679
+ labels.push(value);
680
+ for (j = 0; j < series.length; j++) {
681
+ // Chart.js doesn't like undefined
682
+ rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
683
+ }
684
+ }
685
+ } else {
686
+ for (var i$2 = 0; i$2 < series.length; i$2++) {
687
+ var s$2 = series[i$2];
688
+ var d$1 = [];
689
+ for (var j$2 = 0; j$2 < s$2.data.length; j$2++) {
690
+ var point = {
691
+ x: toFloat(s$2.data[j$2][0]),
692
+ y: toFloat(s$2.data[j$2][1])
693
+ };
694
+ if (chartType === "bubble") {
695
+ point.r = toFloat(s$2.data[j$2][2]) * 20 / max;
696
+ // custom attribute, for tooltip
697
+ point.v = s$2.data[j$2][2];
698
+ }
699
+ d$1.push(point);
700
+ }
701
+ rows2.push(d$1);
702
+ }
703
+ }
704
+
705
+ for (i = 0; i < series.length; i++) {
706
+ s = series[i];
707
+
708
+ var color = s.color || colors[i];
709
+ var backgroundColor = chartType !== "line" ? addOpacity(color, 0.5) : color;
710
+
711
+ var dataset = {
712
+ label: s.name || "",
713
+ data: rows2[i],
714
+ fill: chartType === "area",
715
+ borderColor: color,
716
+ backgroundColor: backgroundColor,
717
+ pointBackgroundColor: color,
718
+ borderWidth: 2,
719
+ pointHoverBackgroundColor: color
720
+ };
721
+
722
+ if (s.stack) {
723
+ dataset.stack = s.stack;
724
+ }
725
+
726
+ var curve = seriesOption(chart, s, "curve");
727
+ if (curve === false) {
728
+ dataset.lineTension = 0;
729
+ }
730
+
731
+ var points = seriesOption(chart, s, "points");
732
+ if (points === false) {
733
+ dataset.pointRadius = 0;
734
+ dataset.pointHitRadius = 5;
735
+ }
736
+
737
+ dataset = merge(dataset, chart.options.dataset || {});
738
+ dataset = merge(dataset, s.library || {});
739
+ dataset = merge(dataset, s.dataset || {});
740
+
741
+ datasets.push(dataset);
742
+ }
743
+
744
+ var xmin = chart.options.xmin;
745
+ var xmax = chart.options.xmax;
746
+
747
+ if (chart.xtype === "datetime") {
748
+ // hacky check for Chart.js >= 2.9.0
749
+ // https://github.com/chartjs/Chart.js/compare/v2.8.0...v2.9.0
750
+ var gte29 = "math" in library.helpers;
751
+ var ticksKey = gte29 ? "ticks" : "time";
752
+ if (notnull(xmin)) {
753
+ options.scales.xAxes[0][ticksKey].min = toDate(xmin).getTime();
754
+ }
755
+ if (notnull(xmax)) {
756
+ options.scales.xAxes[0][ticksKey].max = toDate(xmax).getTime();
757
+ }
758
+ } else if (chart.xtype === "number") {
759
+ if (notnull(xmin)) {
760
+ options.scales.xAxes[0].ticks.min = xmin;
761
+ }
762
+ if (notnull(xmax)) {
763
+ options.scales.xAxes[0].ticks.max = xmax;
764
+ }
765
+ }
766
+
767
+ if (chart.xtype === "datetime" && labels.length > 0) {
768
+ var minTime = (notnull(xmin) ? toDate(xmin) : labels[0]).getTime();
769
+ var maxTime = (notnull(xmax) ? toDate(xmax) : labels[0]).getTime();
770
+
771
+ for (i = 1; i < labels.length; i++) {
772
+ var value$1 = labels[i].getTime();
773
+ if (value$1 < minTime) {
774
+ minTime = value$1;
775
+ }
776
+ if (value$1 > maxTime) {
777
+ maxTime = value$1;
778
+ }
779
+ }
780
+
781
+ var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
782
+
783
+ if (!options.scales.xAxes[0].time.unit) {
784
+ var step;
785
+ if (year || timeDiff > 365 * 10) {
786
+ options.scales.xAxes[0].time.unit = "year";
787
+ step = 365;
788
+ } else if (month || timeDiff > 30 * 10) {
789
+ options.scales.xAxes[0].time.unit = "month";
790
+ step = 30;
791
+ } else if (day || timeDiff > 10) {
792
+ options.scales.xAxes[0].time.unit = "day";
793
+ step = 1;
794
+ } else if (hour || timeDiff > 0.5) {
795
+ options.scales.xAxes[0].time.displayFormats = {hour: "MMM D, h a"};
796
+ options.scales.xAxes[0].time.unit = "hour";
797
+ step = 1 / 24.0;
798
+ } else if (minute) {
799
+ options.scales.xAxes[0].time.displayFormats = {minute: "h:mm a"};
800
+ options.scales.xAxes[0].time.unit = "minute";
801
+ step = 1 / 24.0 / 60.0;
802
+ }
803
+
804
+ if (step && timeDiff > 0) {
805
+ var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
806
+ if (week && step === 1) {
807
+ unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
808
+ }
809
+ options.scales.xAxes[0].time.unitStepSize = unitStepSize;
810
+ }
811
+ }
812
+
813
+ if (!options.scales.xAxes[0].time.tooltipFormat) {
814
+ if (day) {
815
+ options.scales.xAxes[0].time.tooltipFormat = "ll";
816
+ } else if (hour) {
817
+ options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
818
+ } else if (minute) {
819
+ options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
820
+ }
821
+ }
822
+ }
823
+
824
+ var data = {
825
+ labels: labels,
826
+ datasets: datasets
827
+ };
828
+
829
+ return data;
830
+ };
831
+
832
+ var defaultExport = function defaultExport(library) {
833
+ this.name = "chartjs";
834
+ this.library = library;
835
+ };
836
+
837
+ defaultExport.prototype.renderLineChart = function renderLineChart (chart, chartType) {
838
+ var chartOptions = {};
839
+ // fix for https://github.com/chartjs/Chart.js/issues/2441
840
+ if (!chart.options.max && allZeros(chart.data)) {
841
+ chartOptions.max = 1;
842
+ }
843
+
844
+ var options = jsOptions(chart, merge(chartOptions, chart.options));
845
+ setFormatOptions(chart, options, chartType);
846
+
847
+ var data = createDataTable(chart, options, chartType || "line", this.library);
848
+
849
+ if (chart.xtype === "number") {
850
+ options.scales.xAxes[0].type = "linear";
851
+ options.scales.xAxes[0].position = "bottom";
852
+ } else {
853
+ options.scales.xAxes[0].type = chart.xtype === "string" ? "category" : "time";
854
+ }
855
+
856
+ this.drawChart(chart, "line", data, options);
857
+ };
858
+
859
+ defaultExport.prototype.renderPieChart = function renderPieChart (chart) {
860
+ var options = merge({}, baseOptions);
861
+ if (chart.options.donut) {
862
+ options.cutoutPercentage = 50;
863
+ }
864
+
865
+ if ("legend" in chart.options) {
866
+ hideLegend(options, chart.options.legend);
867
+ }
868
+
869
+ if (chart.options.title) {
870
+ setTitle(options, chart.options.title);
871
+ }
872
+
873
+ options = merge(options, chart.options.library || {});
874
+ setFormatOptions(chart, options, "pie");
875
+
876
+ var labels = [];
877
+ var values = [];
878
+ for (var i = 0; i < chart.data.length; i++) {
879
+ var point = chart.data[i];
880
+ labels.push(point[0]);
881
+ values.push(point[1]);
882
+ }
883
+
884
+ var dataset = {
885
+ data: values,
886
+ backgroundColor: chart.options.colors || defaultColors
887
+ };
888
+ dataset = merge(dataset, chart.options.dataset || {});
889
+
890
+ var data = {
891
+ labels: labels,
892
+ datasets: [dataset]
893
+ };
894
+
895
+ this.drawChart(chart, "pie", data, options);
896
+ };
897
+
898
+ defaultExport.prototype.renderColumnChart = function renderColumnChart (chart, chartType) {
899
+ var options;
900
+ if (chartType === "bar") {
901
+ var barOptions = merge(baseOptions, defaultOptions);
902
+ delete barOptions.scales.yAxes[0].ticks.maxTicksLimit;
903
+ options = jsOptionsFunc(barOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options);
904
+ } else {
905
+ options = jsOptions(chart, chart.options);
906
+ }
907
+ setFormatOptions(chart, options, chartType);
908
+ var data = createDataTable(chart, options, "column", this.library);
909
+ if (chartType !== "bar") {
910
+ setLabelSize(chart, data, options);
911
+ }
912
+ this.drawChart(chart, (chartType === "bar" ? "horizontalBar" : "bar"), data, options);
913
+ };
914
+
915
+ defaultExport.prototype.renderAreaChart = function renderAreaChart (chart) {
916
+ this.renderLineChart(chart, "area");
917
+ };
918
+
919
+ defaultExport.prototype.renderBarChart = function renderBarChart (chart) {
920
+ this.renderColumnChart(chart, "bar");
921
+ };
922
+
923
+ defaultExport.prototype.renderScatterChart = function renderScatterChart (chart, chartType) {
924
+ chartType = chartType || "scatter";
925
+
926
+ var options = jsOptions(chart, chart.options);
927
+ setFormatOptions(chart, options, chartType);
928
+
929
+ if (!("showLines" in options)) {
930
+ options.showLines = false;
931
+ }
932
+
933
+ var data = createDataTable(chart, options, chartType, this.library);
934
+
935
+ options.scales.xAxes[0].type = "linear";
936
+ options.scales.xAxes[0].position = "bottom";
937
+
938
+ this.drawChart(chart, chartType, data, options);
939
+ };
940
+
941
+ defaultExport.prototype.renderBubbleChart = function renderBubbleChart (chart) {
942
+ this.renderScatterChart(chart, "bubble");
943
+ };
944
+
945
+ defaultExport.prototype.destroy = function destroy (chart) {
946
+ if (chart.chart) {
947
+ chart.chart.destroy();
948
+ }
949
+ };
950
+
951
+ defaultExport.prototype.drawChart = function drawChart (chart, type, data, options) {
952
+ this.destroy(chart);
953
+
954
+ var chartOptions = {
955
+ type: type,
956
+ data: data,
957
+ options: options
958
+ };
959
+
960
+ if (chart.options.code) {
961
+ window.console.log("new Chart(ctx, " + JSON.stringify(chartOptions) + ");");
962
+ }
963
+
964
+ chart.element.innerHTML = "<canvas></canvas>";
965
+ var ctx = chart.element.getElementsByTagName("CANVAS")[0];
966
+ chart.chart = new this.library(ctx, chartOptions);
967
+ };
968
+
969
+ var defaultOptions$1 = {
970
+ chart: {},
971
+ xAxis: {
972
+ title: {
973
+ text: null
974
+ },
975
+ labels: {
976
+ style: {
977
+ fontSize: "12px"
978
+ }
979
+ }
980
+ },
981
+ yAxis: {
982
+ title: {
983
+ text: null
984
+ },
985
+ labels: {
986
+ style: {
987
+ fontSize: "12px"
988
+ }
989
+ }
990
+ },
991
+ title: {
992
+ text: null
993
+ },
994
+ credits: {
995
+ enabled: false
996
+ },
997
+ legend: {
998
+ borderWidth: 0
999
+ },
1000
+ tooltip: {
1001
+ style: {
1002
+ fontSize: "12px"
1003
+ }
1004
+ },
1005
+ plotOptions: {
1006
+ areaspline: {},
1007
+ area: {},
1008
+ series: {
1009
+ marker: {}
1010
+ }
1011
+ }
1012
+ };
1013
+
1014
+ var hideLegend$1 = function (options, legend, hideLegend) {
1015
+ if (legend !== undefined) {
1016
+ options.legend.enabled = !!legend;
1017
+ if (legend && legend !== true) {
1018
+ if (legend === "top" || legend === "bottom") {
1019
+ options.legend.verticalAlign = legend;
1020
+ } else {
1021
+ options.legend.layout = "vertical";
1022
+ options.legend.verticalAlign = "middle";
1023
+ options.legend.align = legend;
1024
+ }
1025
+ }
1026
+ } else if (hideLegend) {
1027
+ options.legend.enabled = false;
1028
+ }
1029
+ };
1030
+
1031
+ var setTitle$1 = function (options, title) {
1032
+ options.title.text = title;
1033
+ };
1034
+
1035
+ var setMin$1 = function (options, min) {
1036
+ options.yAxis.min = min;
1037
+ };
1038
+
1039
+ var setMax$1 = function (options, max) {
1040
+ options.yAxis.max = max;
1041
+ };
1042
+
1043
+ var setStacked$1 = function (options, stacked) {
1044
+ var stackedValue = stacked ? (stacked === true ? "normal" : stacked) : null;
1045
+ options.plotOptions.series.stacking = stackedValue;
1046
+ options.plotOptions.area.stacking = stackedValue;
1047
+ options.plotOptions.areaspline.stacking = stackedValue;
1048
+ };
1049
+
1050
+ var setXtitle$1 = function (options, title) {
1051
+ options.xAxis.title.text = title;
1052
+ };
1053
+
1054
+ var setYtitle$1 = function (options, title) {
1055
+ options.yAxis.title.text = title;
1056
+ };
1057
+
1058
+ var jsOptions$1 = jsOptionsFunc(defaultOptions$1, hideLegend$1, setTitle$1, setMin$1, setMax$1, setStacked$1, setXtitle$1, setYtitle$1);
1059
+
1060
+ var setFormatOptions$1 = function(chart, options, chartType) {
1061
+ var formatOptions = {
1062
+ prefix: chart.options.prefix,
1063
+ suffix: chart.options.suffix,
1064
+ thousands: chart.options.thousands,
1065
+ decimal: chart.options.decimal,
1066
+ precision: chart.options.precision,
1067
+ round: chart.options.round,
1068
+ zeros: chart.options.zeros
1069
+ };
1070
+
1071
+ if (chartType !== "pie" && !options.yAxis.labels.formatter) {
1072
+ options.yAxis.labels.formatter = function () {
1073
+ return formatValue("", this.value, formatOptions);
1074
+ };
1075
+ }
1076
+
1077
+ if (!options.tooltip.pointFormatter) {
1078
+ options.tooltip.pointFormatter = function () {
1079
+ return '<span style="color:' + this.color + '">\u25CF</span> ' + formatValue(this.series.name + ': <b>', this.y, formatOptions) + '</b><br/>';
1080
+ };
1081
+ }
1082
+ };
1083
+
1084
+ var defaultExport$1 = function defaultExport(library) {
1085
+ this.name = "highcharts";
1086
+ this.library = library;
1087
+ };
1088
+
1089
+ defaultExport$1.prototype.renderLineChart = function renderLineChart (chart, chartType) {
1090
+ chartType = chartType || "spline";
1091
+ var chartOptions = {};
1092
+ if (chartType === "areaspline") {
1093
+ chartOptions = {
1094
+ plotOptions: {
1095
+ areaspline: {
1096
+ stacking: "normal"
1097
+ },
1098
+ area: {
1099
+ stacking: "normal"
1100
+ },
1101
+ series: {
1102
+ marker: {
1103
+ enabled: false
1104
+ }
1105
+ }
1106
+ }
1107
+ };
1108
+ }
1109
+
1110
+ if (chart.options.curve === false) {
1111
+ if (chartType === "areaspline") {
1112
+ chartType = "area";
1113
+ } else if (chartType === "spline") {
1114
+ chartType = "line";
1115
+ }
1116
+ }
1117
+
1118
+ var options = jsOptions$1(chart, chart.options, chartOptions), data, i, j;
1119
+ options.xAxis.type = chart.xtype === "string" ? "category" : (chart.xtype === "number" ? "linear" : "datetime");
1120
+ if (!options.chart.type) {
1121
+ options.chart.type = chartType;
1122
+ }
1123
+ setFormatOptions$1(chart, options, chartType);
1124
+
1125
+ var series = chart.data;
1126
+ for (i = 0; i < series.length; i++) {
1127
+ series[i].name = series[i].name || "Value";
1128
+ data = series[i].data;
1129
+ if (chart.xtype === "datetime") {
1130
+ for (j = 0; j < data.length; j++) {
1131
+ data[j][0] = data[j][0].getTime();
1132
+ }
1133
+ }
1134
+ series[i].marker = {symbol: "circle"};
1135
+ if (chart.options.points === false) {
1136
+ series[i].marker.enabled = false;
1137
+ }
1138
+ }
1139
+
1140
+ this.drawChart(chart, series, options);
1141
+ };
1142
+
1143
+ defaultExport$1.prototype.renderScatterChart = function renderScatterChart (chart) {
1144
+ var options = jsOptions$1(chart, chart.options, {});
1145
+ options.chart.type = "scatter";
1146
+ this.drawChart(chart, chart.data, options);
1147
+ };
1148
+
1149
+ defaultExport$1.prototype.renderPieChart = function renderPieChart (chart) {
1150
+ var chartOptions = merge(defaultOptions$1, {});
1151
+
1152
+ if (chart.options.colors) {
1153
+ chartOptions.colors = chart.options.colors;
1154
+ }
1155
+ if (chart.options.donut) {
1156
+ chartOptions.plotOptions = {pie: {innerSize: "50%"}};
1157
+ }
1158
+
1159
+ if ("legend" in chart.options) {
1160
+ hideLegend$1(chartOptions, chart.options.legend);
1161
+ }
1162
+
1163
+ if (chart.options.title) {
1164
+ setTitle$1(chartOptions, chart.options.title);
1165
+ }
1166
+
1167
+ var options = merge(chartOptions, chart.options.library || {});
1168
+ setFormatOptions$1(chart, options, "pie");
1169
+ var series = [{
1170
+ type: "pie",
1171
+ name: chart.options.label || "Value",
1172
+ data: chart.data
1173
+ }];
1174
+
1175
+ this.drawChart(chart, series, options);
1176
+ };
1177
+
1178
+ defaultExport$1.prototype.renderColumnChart = function renderColumnChart (chart, chartType) {
1179
+ chartType = chartType || "column";
1180
+ var series = chart.data;
1181
+ var options = jsOptions$1(chart, chart.options), i, j, s, d, rows = [], categories = [];
1182
+ options.chart.type = chartType;
1183
+ setFormatOptions$1(chart, options, chartType);
1184
+
1185
+ for (i = 0; i < series.length; i++) {
1186
+ s = series[i];
1187
+
1188
+ for (j = 0; j < s.data.length; j++) {
1189
+ d = s.data[j];
1190
+ if (!rows[d[0]]) {
1191
+ rows[d[0]] = new Array(series.length);
1192
+ categories.push(d[0]);
1193
+ }
1194
+ rows[d[0]][i] = d[1];
1195
+ }
1196
+ }
1197
+
1198
+ if (chart.xtype === "number") {
1199
+ categories.sort(sortByNumber);
1200
+ }
1201
+
1202
+ options.xAxis.categories = categories;
1203
+
1204
+ var newSeries = [], d2;
1205
+ for (i = 0; i < series.length; i++) {
1206
+ d = [];
1207
+ for (j = 0; j < categories.length; j++) {
1208
+ d.push(rows[categories[j]][i] || 0);
1209
+ }
1210
+
1211
+ d2 = {
1212
+ name: series[i].name || "Value",
1213
+ data: d
1214
+ };
1215
+ if (series[i].stack) {
1216
+ d2.stack = series[i].stack;
1217
+ }
1218
+
1219
+ newSeries.push(d2);
1220
+ }
1221
+
1222
+ this.drawChart(chart, newSeries, options);
1223
+ };
1224
+
1225
+ defaultExport$1.prototype.renderBarChart = function renderBarChart (chart) {
1226
+ this.renderColumnChart(chart, "bar");
1227
+ };
1228
+
1229
+ defaultExport$1.prototype.renderAreaChart = function renderAreaChart (chart) {
1230
+ this.renderLineChart(chart, "areaspline");
1231
+ };
1232
+
1233
+ defaultExport$1.prototype.destroy = function destroy (chart) {
1234
+ if (chart.chart) {
1235
+ chart.chart.destroy();
1236
+ }
1237
+ };
1238
+
1239
+ defaultExport$1.prototype.drawChart = function drawChart (chart, data, options) {
1240
+ this.destroy(chart);
1241
+
1242
+ options.chart.renderTo = chart.element.id;
1243
+ options.series = data;
1244
+
1245
+ if (chart.options.code) {
1246
+ window.console.log("new Highcharts.Chart(" + JSON.stringify(options) + ");");
1247
+ }
1248
+
1249
+ chart.chart = new this.library.Chart(options);
1250
+ };
1251
+
1252
+ var loaded = {};
1253
+ var callbacks = [];
1254
+
1255
+ // Set chart options
1256
+ var defaultOptions$2 = {
1257
+ chartArea: {},
1258
+ fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
1259
+ pointSize: 6,
1260
+ legend: {
1261
+ textStyle: {
1262
+ fontSize: 12,
1263
+ color: "#444"
1264
+ },
1265
+ alignment: "center",
1266
+ position: "right"
1267
+ },
1268
+ curveType: "function",
1269
+ hAxis: {
1270
+ textStyle: {
1271
+ color: "#666",
1272
+ fontSize: 12
1273
+ },
1274
+ titleTextStyle: {},
1275
+ gridlines: {
1276
+ color: "transparent"
1277
+ },
1278
+ baselineColor: "#ccc",
1279
+ viewWindow: {}
1280
+ },
1281
+ vAxis: {
1282
+ textStyle: {
1283
+ color: "#666",
1284
+ fontSize: 12
1285
+ },
1286
+ titleTextStyle: {},
1287
+ baselineColor: "#ccc",
1288
+ viewWindow: {}
1289
+ },
1290
+ tooltip: {
1291
+ textStyle: {
1292
+ color: "#666",
1293
+ fontSize: 12
1294
+ }
1295
+ }
1296
+ };
1297
+
1298
+ var hideLegend$2 = function (options, legend, hideLegend) {
1299
+ if (legend !== undefined) {
1300
+ var position;
1301
+ if (!legend) {
1302
+ position = "none";
1303
+ } else if (legend === true) {
1304
+ position = "right";
1305
+ } else {
1306
+ position = legend;
1307
+ }
1308
+ options.legend.position = position;
1309
+ } else if (hideLegend) {
1310
+ options.legend.position = "none";
1311
+ }
1312
+ };
1313
+
1314
+ var setTitle$2 = function (options, title) {
1315
+ options.title = title;
1316
+ options.titleTextStyle = {color: "#333", fontSize: "20px"};
1317
+ };
1318
+
1319
+ var setMin$2 = function (options, min) {
1320
+ options.vAxis.viewWindow.min = min;
1321
+ };
1322
+
1323
+ var setMax$2 = function (options, max) {
1324
+ options.vAxis.viewWindow.max = max;
1325
+ };
1326
+
1327
+ var setBarMin$1 = function (options, min) {
1328
+ options.hAxis.viewWindow.min = min;
1329
+ };
1330
+
1331
+ var setBarMax$1 = function (options, max) {
1332
+ options.hAxis.viewWindow.max = max;
1333
+ };
1334
+
1335
+ var setStacked$2 = function (options, stacked) {
1336
+ options.isStacked = stacked ? stacked : false;
1337
+ };
1338
+
1339
+ var setXtitle$2 = function (options, title) {
1340
+ options.hAxis.title = title;
1341
+ options.hAxis.titleTextStyle.italic = false;
1342
+ };
1343
+
1344
+ var setYtitle$2 = function (options, title) {
1345
+ options.vAxis.title = title;
1346
+ options.vAxis.titleTextStyle.italic = false;
1347
+ };
1348
+
1349
+ var jsOptions$2 = jsOptionsFunc(defaultOptions$2, hideLegend$2, setTitle$2, setMin$2, setMax$2, setStacked$2, setXtitle$2, setYtitle$2);
1350
+
1351
+ var resize = function (callback) {
1352
+ if (window.attachEvent) {
1353
+ window.attachEvent("onresize", callback);
1354
+ } else if (window.addEventListener) {
1355
+ window.addEventListener("resize", callback, true);
1356
+ }
1357
+ callback();
1358
+ };
1359
+
1360
+ var defaultExport$2 = function defaultExport(library) {
1361
+ this.name = "google";
1362
+ this.library = library;
1363
+ };
1364
+
1365
+ defaultExport$2.prototype.renderLineChart = function renderLineChart (chart) {
1366
+ var this$1 = this;
1367
+
1368
+ this.waitForLoaded(chart, function () {
1369
+ var chartOptions = {};
1370
+
1371
+ if (chart.options.curve === false) {
1372
+ chartOptions.curveType = "none";
1373
+ }
1374
+
1375
+ if (chart.options.points === false) {
1376
+ chartOptions.pointSize = 0;
1377
+ }
1378
+
1379
+ var options = jsOptions$2(chart, chart.options, chartOptions);
1380
+ var data = this$1.createDataTable(chart.data, chart.xtype);
1381
+
1382
+ this$1.drawChart(chart, "LineChart", data, options);
1383
+ });
1384
+ };
1385
+
1386
+ defaultExport$2.prototype.renderPieChart = function renderPieChart (chart) {
1387
+ var this$1 = this;
1388
+
1389
+ this.waitForLoaded(chart, function () {
1390
+ var chartOptions = {
1391
+ chartArea: {
1392
+ top: "10%",
1393
+ height: "80%"
1394
+ },
1395
+ legend: {}
1396
+ };
1397
+ if (chart.options.colors) {
1398
+ chartOptions.colors = chart.options.colors;
1399
+ }
1400
+ if (chart.options.donut) {
1401
+ chartOptions.pieHole = 0.5;
1402
+ }
1403
+ if ("legend" in chart.options) {
1404
+ hideLegend$2(chartOptions, chart.options.legend);
1405
+ }
1406
+ if (chart.options.title) {
1407
+ setTitle$2(chartOptions, chart.options.title);
1408
+ }
1409
+ var options = merge(merge(defaultOptions$2, chartOptions), chart.options.library || {});
1410
+
1411
+ var data = new this$1.library.visualization.DataTable();
1412
+ data.addColumn("string", "");
1413
+ data.addColumn("number", "Value");
1414
+ data.addRows(chart.data);
1415
+
1416
+ this$1.drawChart(chart, "PieChart", data, options);
1417
+ });
1418
+ };
1419
+
1420
+ defaultExport$2.prototype.renderColumnChart = function renderColumnChart (chart) {
1421
+ var this$1 = this;
1422
+
1423
+ this.waitForLoaded(chart, function () {
1424
+ var options = jsOptions$2(chart, chart.options);
1425
+ var data = this$1.createDataTable(chart.data, chart.xtype);
1426
+
1427
+ this$1.drawChart(chart, "ColumnChart", data, options);
1428
+ });
1429
+ };
1430
+
1431
+ defaultExport$2.prototype.renderBarChart = function renderBarChart (chart) {
1432
+ var this$1 = this;
1433
+
1434
+ this.waitForLoaded(chart, function () {
1435
+ var chartOptions = {
1436
+ hAxis: {
1437
+ gridlines: {
1438
+ color: "#ccc"
1439
+ }
1440
+ }
1441
+ };
1442
+ var options = jsOptionsFunc(defaultOptions$2, hideLegend$2, setTitle$2, setBarMin$1, setBarMax$1, setStacked$2, setXtitle$2, setYtitle$2)(chart, chart.options, chartOptions);
1443
+ var data = this$1.createDataTable(chart.data, chart.xtype);
1444
+
1445
+ this$1.drawChart(chart, "BarChart", data, options);
1446
+ });
1447
+ };
1448
+
1449
+ defaultExport$2.prototype.renderAreaChart = function renderAreaChart (chart) {
1450
+ var this$1 = this;
1451
+
1452
+ this.waitForLoaded(chart, function () {
1453
+ var chartOptions = {
1454
+ isStacked: true,
1455
+ pointSize: 0,
1456
+ areaOpacity: 0.5
1457
+ };
1458
+
1459
+ var options = jsOptions$2(chart, chart.options, chartOptions);
1460
+ var data = this$1.createDataTable(chart.data, chart.xtype);
1461
+
1462
+ this$1.drawChart(chart, "AreaChart", data, options);
1463
+ });
1464
+ };
1465
+
1466
+ defaultExport$2.prototype.renderGeoChart = function renderGeoChart (chart) {
1467
+ var this$1 = this;
1468
+
1469
+ this.waitForLoaded(chart, function () {
1470
+ var chartOptions = {
1471
+ legend: "none",
1472
+ colorAxis: {
1473
+ colors: chart.options.colors || ["#f6c7b6", "#ce502d"]
1474
+ }
1475
+ };
1476
+ var options = merge(merge(defaultOptions$2, chartOptions), chart.options.library || {});
1477
+
1478
+ var data = new this$1.library.visualization.DataTable();
1479
+ data.addColumn("string", "");
1480
+ data.addColumn("number", chart.options.label || "Value");
1481
+ data.addRows(chart.data);
1482
+
1483
+ this$1.drawChart(chart, "GeoChart", data, options);
1484
+ });
1485
+ };
1486
+
1487
+ defaultExport$2.prototype.renderScatterChart = function renderScatterChart (chart) {
1488
+ var this$1 = this;
1489
+
1490
+ this.waitForLoaded(chart, function () {
1491
+ var chartOptions = {};
1492
+ var options = jsOptions$2(chart, chart.options, chartOptions);
1493
+
1494
+ var series = chart.data, rows2 = [], i, j, data, d;
1495
+ for (i = 0; i < series.length; i++) {
1496
+ series[i].name = series[i].name || "Value";
1497
+ d = series[i].data;
1498
+ for (j = 0; j < d.length; j++) {
1499
+ var row = new Array(series.length + 1);
1500
+ row[0] = d[j][0];
1501
+ row[i + 1] = d[j][1];
1502
+ rows2.push(row);
1503
+ }
1504
+ }
1505
+
1506
+ data = new this$1.library.visualization.DataTable();
1507
+ data.addColumn("number", "");
1508
+ for (i = 0; i < series.length; i++) {
1509
+ data.addColumn("number", series[i].name);
1510
+ }
1511
+ data.addRows(rows2);
1512
+
1513
+ this$1.drawChart(chart, "ScatterChart", data, options);
1514
+ });
1515
+ };
1516
+
1517
+ defaultExport$2.prototype.renderTimeline = function renderTimeline (chart) {
1518
+ var this$1 = this;
1519
+
1520
+ this.waitForLoaded(chart, "timeline", function () {
1521
+ var chartOptions = {
1522
+ legend: "none"
1523
+ };
1524
+
1525
+ if (chart.options.colors) {
1526
+ chartOptions.colors = chart.options.colors;
1527
+ }
1528
+ var options = merge(merge(defaultOptions$2, chartOptions), chart.options.library || {});
1529
+
1530
+ var data = new this$1.library.visualization.DataTable();
1531
+ data.addColumn({type: "string", id: "Name"});
1532
+ data.addColumn({type: "date", id: "Start"});
1533
+ data.addColumn({type: "date", id: "End"});
1534
+ data.addRows(chart.data);
1535
+
1536
+ chart.element.style.lineHeight = "normal";
1537
+
1538
+ this$1.drawChart(chart, "Timeline", data, options);
1539
+ });
1540
+ };
1541
+
1542
+ defaultExport$2.prototype.destroy = function destroy (chart) {
1543
+ if (chart.chart) {
1544
+ chart.chart.clearChart();
1545
+ }
1546
+ };
1547
+
1548
+ defaultExport$2.prototype.drawChart = function drawChart (chart, type, data, options) {
1549
+ this.destroy(chart);
1550
+
1551
+ if (chart.options.code) {
1552
+ window.console.log("var data = new google.visualization.DataTable(" + data.toJSON() + ");\nvar chart = new google.visualization." + type + "(element);\nchart.draw(data, " + JSON.stringify(options) + ");");
1553
+ }
1554
+
1555
+ chart.chart = new this.library.visualization[type](chart.element);
1556
+ resize(function () {
1557
+ chart.chart.draw(data, options);
1558
+ });
1559
+ };
1560
+
1561
+ defaultExport$2.prototype.waitForLoaded = function waitForLoaded (chart, pack, callback) {
1562
+ var this$1 = this;
1563
+
1564
+ if (!callback) {
1565
+ callback = pack;
1566
+ pack = "corechart";
1567
+ }
1568
+
1569
+ callbacks.push({pack: pack, callback: callback});
1570
+
1571
+ if (loaded[pack]) {
1572
+ this.runCallbacks();
1573
+ } else {
1574
+ loaded[pack] = true;
1575
+
1576
+ // https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
1577
+ var loadOptions = {
1578
+ packages: [pack],
1579
+ callback: function () { this$1.runCallbacks(); }
1580
+ };
1581
+ var config = chart.__config();
1582
+ if (config.language) {
1583
+ loadOptions.language = config.language;
1584
+ }
1585
+ if (pack === "corechart" && config.mapsApiKey) {
1586
+ loadOptions.mapsApiKey = config.mapsApiKey;
1587
+ }
1588
+
1589
+ this.library.charts.load("current", loadOptions);
1590
+ }
1591
+ };
1592
+
1593
+ defaultExport$2.prototype.runCallbacks = function runCallbacks () {
1594
+ var cb, call;
1595
+ for (var i = 0; i < callbacks.length; i++) {
1596
+ cb = callbacks[i];
1597
+ call = this.library.visualization && ((cb.pack === "corechart" && this.library.visualization.LineChart) || (cb.pack === "timeline" && this.library.visualization.Timeline));
1598
+ if (call) {
1599
+ cb.callback();
1600
+ callbacks.splice(i, 1);
1601
+ i--;
1602
+ }
1603
+ }
1604
+ };
1605
+
1606
+ // cant use object as key
1607
+ defaultExport$2.prototype.createDataTable = function createDataTable (series, columnType) {
1608
+ var i, j, s, d, key, rows = [], sortedLabels = [];
1609
+ for (i = 0; i < series.length; i++) {
1610
+ s = series[i];
1611
+ series[i].name = series[i].name || "Value";
1612
+
1613
+ for (j = 0; j < s.data.length; j++) {
1614
+ d = s.data[j];
1615
+ key = (columnType === "datetime") ? d[0].getTime() : d[0];
1616
+ if (!rows[key]) {
1617
+ rows[key] = new Array(series.length);
1618
+ sortedLabels.push(key);
1619
+ }
1620
+ rows[key][i] = toFloat(d[1]);
1621
+ }
1622
+ }
1623
+
1624
+ var rows2 = [];
1625
+ var day = true;
1626
+ var value;
1627
+ for (j = 0; j < sortedLabels.length; j++) {
1628
+ i = sortedLabels[j];
1629
+ if (columnType === "datetime") {
1630
+ value = new Date(toFloat(i));
1631
+ day = day && isDay(value);
1632
+ } else if (columnType === "number") {
1633
+ value = toFloat(i);
1634
+ } else {
1635
+ value = i;
1636
+ }
1637
+ rows2.push([value].concat(rows[i]));
1638
+ }
1639
+ if (columnType === "datetime") {
1640
+ rows2.sort(sortByTime);
1641
+ } else if (columnType === "number") {
1642
+ rows2.sort(sortByNumberSeries);
1643
+
1644
+ for (i = 0; i < rows2.length; i++) {
1645
+ rows2[i][0] = toStr(rows2[i][0]);
1646
+ }
1647
+
1648
+ columnType = "string";
1649
+ }
1650
+
1651
+ // create datatable
1652
+ var data = new this.library.visualization.DataTable();
1653
+ columnType = columnType === "datetime" && day ? "date" : columnType;
1654
+ data.addColumn(columnType, "");
1655
+ for (i = 0; i < series.length; i++) {
1656
+ data.addColumn("number", series[i].name);
1657
+ }
1658
+ data.addRows(rows2);
1659
+
1660
+ return data;
1661
+ };
1662
+
1663
+ var pendingRequests = [], runningRequests = 0, maxRequests = 4;
1664
+
1665
+ function pushRequest(url, success, error) {
1666
+ pendingRequests.push([url, success, error]);
1667
+ runNext();
1668
+ }
1669
+
1670
+ function runNext() {
1671
+ if (runningRequests < maxRequests) {
1672
+ var request = pendingRequests.shift();
1673
+ if (request) {
1674
+ runningRequests++;
1675
+ getJSON(request[0], request[1], request[2]);
1676
+ runNext();
1677
+ }
1678
+ }
1679
+ }
1680
+
1681
+ function requestComplete() {
1682
+ runningRequests--;
1683
+ runNext();
1684
+ }
1685
+
1686
+ function getJSON(url, success, error) {
1687
+ ajaxCall(url, success, function (jqXHR, textStatus, errorThrown) {
1688
+ var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
1689
+ error(message);
1690
+ });
1691
+ }
1692
+
1693
+ function ajaxCall(url, success, error) {
1694
+ var $ = window.jQuery || window.Zepto || window.$;
1695
+
1696
+ if ($ && $.ajax) {
1697
+ $.ajax({
1698
+ dataType: "json",
1699
+ url: url,
1700
+ success: success,
1701
+ error: error,
1702
+ complete: requestComplete
1703
+ });
1704
+ } else {
1705
+ var xhr = new XMLHttpRequest();
1706
+ xhr.open("GET", url, true);
1707
+ xhr.setRequestHeader("Content-Type", "application/json");
1708
+ xhr.onload = function () {
1709
+ requestComplete();
1710
+ if (xhr.status === 200) {
1711
+ success(JSON.parse(xhr.responseText), xhr.statusText, xhr);
1712
+ } else {
1713
+ error(xhr, "error", xhr.statusText);
1714
+ }
1715
+ };
1716
+ xhr.send();
1717
+ }
1718
+ }
1719
+
1720
+ var config = {};
1721
+ var adapters = [];
1722
+
1723
+ // helpers
1724
+
1725
+ function setText(element, text) {
1726
+ if (document.body.innerText) {
1727
+ element.innerText = text;
1728
+ } else {
1729
+ element.textContent = text;
1730
+ }
1731
+ }
1732
+
1733
+ // TODO remove prefix for all messages
1734
+ function chartError(element, message, noPrefix) {
1735
+ if (!noPrefix) {
1736
+ message = "Error Loading Chart: " + message;
1737
+ }
1738
+ setText(element, message);
1739
+ element.style.color = "#ff0000";
1740
+ }
1741
+
1742
+ function errorCatcher(chart) {
1743
+ try {
1744
+ chart.__render();
1745
+ } catch (err) {
1746
+ chartError(chart.element, err.message);
1747
+ throw err;
1748
+ }
1749
+ }
1750
+
1751
+ function fetchDataSource(chart, dataSource) {
1752
+ if (typeof dataSource === "string") {
1753
+ pushRequest(dataSource, function (data) {
1754
+ chart.rawData = data;
1755
+ errorCatcher(chart);
1756
+ }, function (message) {
1757
+ chartError(chart.element, message);
1758
+ });
1759
+ } else if (typeof dataSource === "function") {
1760
+ try {
1761
+ dataSource(function (data) {
1762
+ chart.rawData = data;
1763
+ errorCatcher(chart);
1764
+ }, function (message) {
1765
+ chartError(chart.element, message, true);
1766
+ });
1767
+ } catch (err) {
1768
+ chartError(chart.element, err, true);
1769
+ }
1770
+ } else {
1771
+ chart.rawData = dataSource;
1772
+ errorCatcher(chart);
1773
+ }
1774
+ }
1775
+
1776
+ function addDownloadButton(chart) {
1777
+ var element = chart.element;
1778
+ var link = document.createElement("a");
1779
+
1780
+ var download = chart.options.download;
1781
+ if (download === true) {
1782
+ download = {};
1783
+ } else if (typeof download === "string") {
1784
+ download = {filename: download};
1785
+ }
1786
+ link.download = download.filename || "chart.png"; // https://caniuse.com/download
1787
+
1788
+ link.style.position = "absolute";
1789
+ link.style.top = "20px";
1790
+ link.style.right = "20px";
1791
+ link.style.zIndex = 1000;
1792
+ link.style.lineHeight = "20px";
1793
+ link.target = "_blank"; // for safari
1794
+ var image = document.createElement("img");
1795
+ image.alt = "Download";
1796
+ image.style.border = "none";
1797
+ // icon from font-awesome
1798
+ // http://fa2png.io/
1799
+ image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAABCFBMVEUAAADMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMywEsqxAAAAV3RSTlMAAQIDBggJCgsMDQ4PERQaHB0eISIjJCouLzE0OTo/QUJHSUpLTU5PUllhYmltcHh5foWLjI+SlaCio6atr7S1t7m6vsHHyM7R2tze5Obo7fHz9ff5+/1hlxK2AAAA30lEQVQYGUXBhVYCQQBA0TdYWAt2d3d3YWAHyur7/z9xgD16Lw0DW+XKx+1GgX+FRzM3HWQWrHl5N/oapW5RPe0PkBu+UYeICvozTWZVK23Ao04B79oJrOsJDOoxkZoQPWgX29pHpCZEk7rEvQYiNSFq1UMqvlCjJkRBS1R8hb00Vb/TajtBL7nTHE1X1vyMQF732dQhyF2o6SAwrzP06iUQzvwsArlnzcOdrgBhJyHa1QOgO9U1GsKuvjUTjavliZYQ8nNPapG6sap/3nrIdJ6bOWzmX/fy0XVpfzZP3S8OJT3g9EEiJwAAAABJRU5ErkJggg==";
1800
+ link.appendChild(image);
1801
+ element.style.position = "relative";
1802
+
1803
+ chart.__downloadAttached = true;
1804
+
1805
+ // mouseenter
1806
+ chart.__enterEvent = addEvent(element, "mouseover", function(e) {
1807
+ var related = e.relatedTarget;
1808
+ // check download option again to ensure it wasn't changed
1809
+ if ((!related || (related !== this && !childOf(this, related))) && chart.options.download) {
1810
+ link.href = chart.toImage(download);
1811
+ element.appendChild(link);
1812
+ }
1813
+ });
1814
+
1815
+ // mouseleave
1816
+ chart.__leaveEvent = addEvent(element, "mouseout", function(e) {
1817
+ var related = e.relatedTarget;
1818
+ if (!related || (related !== this && !childOf(this, related))) {
1819
+ if (link.parentNode) {
1820
+ link.parentNode.removeChild(link);
1821
+ }
1822
+ }
1823
+ });
1824
+ }
1825
+
1826
+ // https://stackoverflow.com/questions/10149963/adding-event-listener-cross-browser
1827
+ function addEvent(elem, event, fn) {
1828
+ if (elem.addEventListener) {
1829
+ elem.addEventListener(event, fn, false);
1830
+ return fn;
1831
+ } else {
1832
+ var fn2 = function() {
1833
+ // set the this pointer same as addEventListener when fn is called
1834
+ return(fn.call(elem, window.event));
1835
+ };
1836
+ elem.attachEvent("on" + event, fn2);
1837
+ return fn2;
1838
+ }
1839
+ }
1840
+
1841
+ function removeEvent(elem, event, fn) {
1842
+ if (elem.removeEventListener) {
1843
+ elem.removeEventListener(event, fn, false);
1844
+ } else {
1845
+ elem.detachEvent("on" + event, fn);
1846
+ }
1847
+ }
1848
+
1849
+ // https://gist.github.com/shawnbot/4166283
1850
+ function childOf(p, c) {
1851
+ if (p === c) { return false; }
1852
+ while (c && c !== p) { c = c.parentNode; }
1853
+ return c === p;
1854
+ }
1855
+
1856
+ function getAdapterType(library) {
1857
+ if (library) {
1858
+ if (library.product === "Highcharts") {
1859
+ return defaultExport$1;
1860
+ } else if (library.charts) {
1861
+ return defaultExport$2;
1862
+ } else if (isFunction(library)) {
1863
+ return defaultExport;
1864
+ }
1865
+ }
1866
+ throw new Error("Unknown adapter");
1867
+ }
1868
+
1869
+ function addAdapter(library) {
1870
+ var adapterType = getAdapterType(library);
1871
+ var adapter = new adapterType(library);
1872
+
1873
+ if (adapters.indexOf(adapter) === -1) {
1874
+ adapters.push(adapter);
1875
+ }
1876
+ }
1877
+
1878
+ function loadAdapters() {
1879
+ if ("Chart" in window) {
1880
+ addAdapter(window.Chart);
1881
+ }
1882
+
1883
+ if ("Highcharts" in window) {
1884
+ addAdapter(window.Highcharts);
1885
+ }
1886
+
1887
+ if (window.google && window.google.charts) {
1888
+ addAdapter(window.google);
1889
+ }
1890
+ }
1891
+
1892
+ function dataEmpty(data, chartType) {
1893
+ if (chartType === "PieChart" || chartType === "GeoChart" || chartType === "Timeline") {
1894
+ return data.length === 0;
1895
+ } else {
1896
+ for (var i = 0; i < data.length; i++) {
1897
+ if (data[i].data.length > 0) {
1898
+ return false;
1899
+ }
1900
+ }
1901
+ return true;
1902
+ }
1903
+ }
1904
+
1905
+ function renderChart(chartType, chart) {
1906
+ if (chart.options.messages && chart.options.messages.empty && dataEmpty(chart.data, chartType)) {
1907
+ setText(chart.element, chart.options.messages.empty);
1908
+ } else {
1909
+ callAdapter(chartType, chart);
1910
+ if (chart.options.download && !chart.__downloadAttached && chart.adapter === "chartjs") {
1911
+ addDownloadButton(chart);
1912
+ }
1913
+ }
1914
+ }
1915
+
1916
+ // TODO remove chartType if cross-browser way
1917
+ // to get the name of the chart class
1918
+ function callAdapter(chartType, chart) {
1919
+ var i, adapter, fnName, adapterName;
1920
+ fnName = "render" + chartType;
1921
+ adapterName = chart.options.adapter;
1922
+
1923
+ loadAdapters();
1924
+
1925
+ for (i = 0; i < adapters.length; i++) {
1926
+ adapter = adapters[i];
1927
+ if ((!adapterName || adapterName === adapter.name) && isFunction(adapter[fnName])) {
1928
+ chart.adapter = adapter.name;
1929
+ chart.__adapterObject = adapter;
1930
+ return adapter[fnName](chart);
1931
+ }
1932
+ }
1933
+
1934
+ if (adapters.length > 0) {
1935
+ throw new Error("No charting library found for " + chartType);
1936
+ } else {
1937
+ throw new Error("No charting libraries found - be sure to include one before your charts");
1938
+ }
1939
+ }
1940
+
1941
+ // process data
1942
+
1943
+ var toFormattedKey = function (key, keyType) {
1944
+ if (keyType === "number") {
1945
+ key = toFloat(key);
1946
+ } else if (keyType === "datetime") {
1947
+ key = toDate(key);
1948
+ } else {
1949
+ key = toStr(key);
1950
+ }
1951
+ return key;
1952
+ };
1953
+
1954
+ var formatSeriesData = function (data, keyType) {
1955
+ var r = [], key, j;
1956
+ for (j = 0; j < data.length; j++) {
1957
+ if (keyType === "bubble") {
1958
+ r.push([toFloat(data[j][0]), toFloat(data[j][1]), toFloat(data[j][2])]);
1959
+ } else {
1960
+ key = toFormattedKey(data[j][0], keyType);
1961
+ r.push([key, toFloat(data[j][1])]);
1962
+ }
1963
+ }
1964
+ if (keyType === "datetime") {
1965
+ r.sort(sortByTime);
1966
+ } else if (keyType === "number") {
1967
+ r.sort(sortByNumberSeries);
1968
+ }
1969
+ return r;
1970
+ };
1971
+
1972
+ function detectXType(series, noDatetime) {
1973
+ if (detectXTypeWithFunction(series, isNumber)) {
1974
+ return "number";
1975
+ } else if (!noDatetime && detectXTypeWithFunction(series, isDate)) {
1976
+ return "datetime";
1977
+ } else {
1978
+ return "string";
1979
+ }
1980
+ }
1981
+
1982
+ function detectXTypeWithFunction(series, func) {
1983
+ var i, j, data;
1984
+ for (i = 0; i < series.length; i++) {
1985
+ data = toArr(series[i].data);
1986
+ for (j = 0; j < data.length; j++) {
1987
+ if (!func(data[j][0])) {
1988
+ return false;
1989
+ }
1990
+ }
1991
+ }
1992
+ return true;
1993
+ }
1994
+
1995
+ // creates a shallow copy of each element of the array
1996
+ // elements are expected to be objects
1997
+ function copySeries(series) {
1998
+ var newSeries = [], i, j;
1999
+ for (i = 0; i < series.length; i++) {
2000
+ var copy = {};
2001
+ for (j in series[i]) {
2002
+ if (series[i].hasOwnProperty(j)) {
2003
+ copy[j] = series[i][j];
2004
+ }
2005
+ }
2006
+ newSeries.push(copy);
2007
+ }
2008
+ return newSeries;
2009
+ }
2010
+
2011
+ function processSeries(chart, keyType, noDatetime) {
2012
+ var i;
2013
+
2014
+ var opts = chart.options;
2015
+ var series = chart.rawData;
2016
+
2017
+ // see if one series or multiple
2018
+ if (!isArray(series) || typeof series[0] !== "object" || isArray(series[0])) {
2019
+ series = [{name: opts.label, data: series}];
2020
+ chart.hideLegend = true;
2021
+ } else {
2022
+ chart.hideLegend = false;
2023
+ }
2024
+
2025
+ chart.xtype = keyType ? keyType : (opts.discrete ? "string" : detectXType(series, noDatetime));
2026
+
2027
+ // right format
2028
+ series = copySeries(series);
2029
+ for (i = 0; i < series.length; i++) {
2030
+ series[i].data = formatSeriesData(toArr(series[i].data), chart.xtype);
2031
+ }
2032
+
2033
+ return series;
2034
+ }
2035
+
2036
+ function processSimple(chart) {
2037
+ var perfectData = toArr(chart.rawData), i;
2038
+ for (i = 0; i < perfectData.length; i++) {
2039
+ perfectData[i] = [toStr(perfectData[i][0]), toFloat(perfectData[i][1])];
2040
+ }
2041
+ return perfectData;
2042
+ }
2043
+
2044
+ // define classes
2045
+
2046
+ var Chart = function Chart(element, dataSource, options) {
2047
+ var elementId;
2048
+ if (typeof element === "string") {
2049
+ elementId = element;
2050
+ element = document.getElementById(element);
2051
+ if (!element) {
2052
+ throw new Error("No element with id " + elementId);
2053
+ }
2054
+ }
2055
+ this.element = element;
2056
+ this.options = merge(Chartkick.options, options || {});
2057
+ this.dataSource = dataSource;
2058
+
2059
+ Chartkick.charts[element.id] = this;
2060
+
2061
+ fetchDataSource(this, dataSource);
2062
+
2063
+ if (this.options.refresh) {
2064
+ this.startRefresh();
2065
+ }
2066
+ };
2067
+
2068
+ Chart.prototype.getElement = function getElement () {
2069
+ return this.element;
2070
+ };
2071
+
2072
+ Chart.prototype.getDataSource = function getDataSource () {
2073
+ return this.dataSource;
2074
+ };
2075
+
2076
+ Chart.prototype.getData = function getData () {
2077
+ return this.data;
2078
+ };
2079
+
2080
+ Chart.prototype.getOptions = function getOptions () {
2081
+ return this.options;
2082
+ };
2083
+
2084
+ Chart.prototype.getChartObject = function getChartObject () {
2085
+ return this.chart;
2086
+ };
2087
+
2088
+ Chart.prototype.getAdapter = function getAdapter () {
2089
+ return this.adapter;
2090
+ };
2091
+
2092
+ Chart.prototype.updateData = function updateData (dataSource, options) {
2093
+ this.dataSource = dataSource;
2094
+ if (options) {
2095
+ this.__updateOptions(options);
2096
+ }
2097
+ fetchDataSource(this, dataSource);
2098
+ };
2099
+
2100
+ Chart.prototype.setOptions = function setOptions (options) {
2101
+ this.__updateOptions(options);
2102
+ this.redraw();
2103
+ };
2104
+
2105
+ Chart.prototype.redraw = function redraw () {
2106
+ fetchDataSource(this, this.rawData);
2107
+ };
2108
+
2109
+ Chart.prototype.refreshData = function refreshData () {
2110
+ if (typeof this.dataSource === "string") {
2111
+ // prevent browser from caching
2112
+ var sep = this.dataSource.indexOf("?") === -1 ? "?" : "&";
2113
+ var url = this.dataSource + sep + "_=" + (new Date()).getTime();
2114
+ fetchDataSource(this, url);
2115
+ } else if (typeof this.dataSource === "function") {
2116
+ fetchDataSource(this, this.dataSource);
2117
+ }
2118
+ };
2119
+
2120
+ Chart.prototype.startRefresh = function startRefresh () {
2121
+ var this$1 = this;
2122
+
2123
+ var refresh = this.options.refresh;
2124
+
2125
+ if (refresh && typeof this.dataSource !== "string" && typeof this.dataSource !== "function") {
2126
+ throw new Error("Data source must be a URL or callback for refresh");
2127
+ }
2128
+
2129
+ if (!this.intervalId) {
2130
+ if (refresh) {
2131
+ this.intervalId = setInterval( function () {
2132
+ this$1.refreshData();
2133
+ }, refresh * 1000);
2134
+ } else {
2135
+ throw new Error("No refresh interval");
2136
+ }
2137
+ }
2138
+ };
2139
+
2140
+ Chart.prototype.stopRefresh = function stopRefresh () {
2141
+ if (this.intervalId) {
2142
+ clearInterval(this.intervalId);
2143
+ this.intervalId = null;
2144
+ }
2145
+ };
2146
+
2147
+ Chart.prototype.toImage = function toImage (download) {
2148
+ if (this.adapter === "chartjs") {
2149
+ if (download && download.background && download.background !== "transparent") {
2150
+ // https://stackoverflow.com/questions/30464750/chartjs-line-chart-set-background-color
2151
+ var canvas = this.chart.chart.canvas;
2152
+ var ctx = this.chart.chart.ctx;
2153
+ var tmpCanvas = document.createElement("canvas");
2154
+ var tmpCtx = tmpCanvas.getContext("2d");
2155
+ tmpCanvas.width = ctx.canvas.width;
2156
+ tmpCanvas.height = ctx.canvas.height;
2157
+ tmpCtx.fillStyle = download.background;
2158
+ tmpCtx.fillRect(0, 0, tmpCanvas.width, tmpCanvas.height);
2159
+ tmpCtx.drawImage(canvas, 0, 0);
2160
+ return tmpCanvas.toDataURL("image/png");
2161
+ } else {
2162
+ return this.chart.toBase64Image();
2163
+ }
2164
+ } else {
2165
+ // TODO throw error in next major version
2166
+ // throw new Error("Feature only available for Chart.js");
2167
+ return null;
2168
+ }
2169
+ };
2170
+
2171
+ Chart.prototype.destroy = function destroy () {
2172
+ if (this.__adapterObject) {
2173
+ this.__adapterObject.destroy(this);
2174
+ }
2175
+
2176
+ if (this.__enterEvent) {
2177
+ removeEvent(this.element, "mouseover", this.__enterEvent);
2178
+ }
2179
+
2180
+ if (this.__leaveEvent) {
2181
+ removeEvent(this.element, "mouseout", this.__leaveEvent);
2182
+ }
2183
+ };
2184
+
2185
+ Chart.prototype.__updateOptions = function __updateOptions (options) {
2186
+ var updateRefresh = options.refresh && options.refresh !== this.options.refresh;
2187
+ this.options = merge(Chartkick.options, options);
2188
+ if (updateRefresh) {
2189
+ this.stopRefresh();
2190
+ this.startRefresh();
2191
+ }
2192
+ };
2193
+
2194
+ Chart.prototype.__render = function __render () {
2195
+ this.data = this.__processData();
2196
+ renderChart(this.__chartName(), this);
2197
+ };
2198
+
2199
+ Chart.prototype.__config = function __config () {
2200
+ return config;
2201
+ };
2202
+
2203
+ var LineChart = /*@__PURE__*/(function (Chart) {
2204
+ function LineChart () {
2205
+ Chart.apply(this, arguments);
2206
+ }
2207
+
2208
+ if ( Chart ) LineChart.__proto__ = Chart;
2209
+ LineChart.prototype = Object.create( Chart && Chart.prototype );
2210
+ LineChart.prototype.constructor = LineChart;
2211
+
2212
+ LineChart.prototype.__processData = function __processData () {
2213
+ return processSeries(this);
2214
+ };
2215
+
2216
+ LineChart.prototype.__chartName = function __chartName () {
2217
+ return "LineChart";
2218
+ };
2219
+
2220
+ return LineChart;
2221
+ }(Chart));
2222
+
2223
+ var PieChart = /*@__PURE__*/(function (Chart) {
2224
+ function PieChart () {
2225
+ Chart.apply(this, arguments);
2226
+ }
2227
+
2228
+ if ( Chart ) PieChart.__proto__ = Chart;
2229
+ PieChart.prototype = Object.create( Chart && Chart.prototype );
2230
+ PieChart.prototype.constructor = PieChart;
2231
+
2232
+ PieChart.prototype.__processData = function __processData () {
2233
+ return processSimple(this);
2234
+ };
2235
+
2236
+ PieChart.prototype.__chartName = function __chartName () {
2237
+ return "PieChart";
2238
+ };
2239
+
2240
+ return PieChart;
2241
+ }(Chart));
2242
+
2243
+ var ColumnChart = /*@__PURE__*/(function (Chart) {
2244
+ function ColumnChart () {
2245
+ Chart.apply(this, arguments);
2246
+ }
2247
+
2248
+ if ( Chart ) ColumnChart.__proto__ = Chart;
2249
+ ColumnChart.prototype = Object.create( Chart && Chart.prototype );
2250
+ ColumnChart.prototype.constructor = ColumnChart;
2251
+
2252
+ ColumnChart.prototype.__processData = function __processData () {
2253
+ return processSeries(this, null, true);
2254
+ };
2255
+
2256
+ ColumnChart.prototype.__chartName = function __chartName () {
2257
+ return "ColumnChart";
2258
+ };
2259
+
2260
+ return ColumnChart;
2261
+ }(Chart));
2262
+
2263
+ var BarChart = /*@__PURE__*/(function (Chart) {
2264
+ function BarChart () {
2265
+ Chart.apply(this, arguments);
2266
+ }
2267
+
2268
+ if ( Chart ) BarChart.__proto__ = Chart;
2269
+ BarChart.prototype = Object.create( Chart && Chart.prototype );
2270
+ BarChart.prototype.constructor = BarChart;
2271
+
2272
+ BarChart.prototype.__processData = function __processData () {
2273
+ return processSeries(this, null, true);
2274
+ };
2275
+
2276
+ BarChart.prototype.__chartName = function __chartName () {
2277
+ return "BarChart";
2278
+ };
2279
+
2280
+ return BarChart;
2281
+ }(Chart));
2282
+
2283
+ var AreaChart = /*@__PURE__*/(function (Chart) {
2284
+ function AreaChart () {
2285
+ Chart.apply(this, arguments);
2286
+ }
2287
+
2288
+ if ( Chart ) AreaChart.__proto__ = Chart;
2289
+ AreaChart.prototype = Object.create( Chart && Chart.prototype );
2290
+ AreaChart.prototype.constructor = AreaChart;
2291
+
2292
+ AreaChart.prototype.__processData = function __processData () {
2293
+ return processSeries(this);
2294
+ };
2295
+
2296
+ AreaChart.prototype.__chartName = function __chartName () {
2297
+ return "AreaChart";
2298
+ };
2299
+
2300
+ return AreaChart;
2301
+ }(Chart));
2302
+
2303
+ var GeoChart = /*@__PURE__*/(function (Chart) {
2304
+ function GeoChart () {
2305
+ Chart.apply(this, arguments);
2306
+ }
2307
+
2308
+ if ( Chart ) GeoChart.__proto__ = Chart;
2309
+ GeoChart.prototype = Object.create( Chart && Chart.prototype );
2310
+ GeoChart.prototype.constructor = GeoChart;
2311
+
2312
+ GeoChart.prototype.__processData = function __processData () {
2313
+ return processSimple(this);
2314
+ };
2315
+
2316
+ GeoChart.prototype.__chartName = function __chartName () {
2317
+ return "GeoChart";
2318
+ };
2319
+
2320
+ return GeoChart;
2321
+ }(Chart));
2322
+
2323
+ var ScatterChart = /*@__PURE__*/(function (Chart) {
2324
+ function ScatterChart () {
2325
+ Chart.apply(this, arguments);
2326
+ }
2327
+
2328
+ if ( Chart ) ScatterChart.__proto__ = Chart;
2329
+ ScatterChart.prototype = Object.create( Chart && Chart.prototype );
2330
+ ScatterChart.prototype.constructor = ScatterChart;
2331
+
2332
+ ScatterChart.prototype.__processData = function __processData () {
2333
+ return processSeries(this, "number");
2334
+ };
2335
+
2336
+ ScatterChart.prototype.__chartName = function __chartName () {
2337
+ return "ScatterChart";
2338
+ };
2339
+
2340
+ return ScatterChart;
2341
+ }(Chart));
2342
+
2343
+ var BubbleChart = /*@__PURE__*/(function (Chart) {
2344
+ function BubbleChart () {
2345
+ Chart.apply(this, arguments);
2346
+ }
2347
+
2348
+ if ( Chart ) BubbleChart.__proto__ = Chart;
2349
+ BubbleChart.prototype = Object.create( Chart && Chart.prototype );
2350
+ BubbleChart.prototype.constructor = BubbleChart;
2351
+
2352
+ BubbleChart.prototype.__processData = function __processData () {
2353
+ return processSeries(this, "bubble");
2354
+ };
2355
+
2356
+ BubbleChart.prototype.__chartName = function __chartName () {
2357
+ return "BubbleChart";
2358
+ };
2359
+
2360
+ return BubbleChart;
2361
+ }(Chart));
2362
+
2363
+ var Timeline = /*@__PURE__*/(function (Chart) {
2364
+ function Timeline () {
2365
+ Chart.apply(this, arguments);
2366
+ }
2367
+
2368
+ if ( Chart ) Timeline.__proto__ = Chart;
2369
+ Timeline.prototype = Object.create( Chart && Chart.prototype );
2370
+ Timeline.prototype.constructor = Timeline;
2371
+
2372
+ Timeline.prototype.__processData = function __processData () {
2373
+ var i, data = this.rawData;
2374
+ for (i = 0; i < data.length; i++) {
2375
+ data[i][1] = toDate(data[i][1]);
2376
+ data[i][2] = toDate(data[i][2]);
2377
+ }
2378
+ return data;
2379
+ };
2380
+
2381
+ Timeline.prototype.__chartName = function __chartName () {
2382
+ return "Timeline";
2383
+ };
2384
+
2385
+ return Timeline;
2386
+ }(Chart));
2387
+
2388
+ var Chartkick = {
2389
+ LineChart: LineChart,
2390
+ PieChart: PieChart,
2391
+ ColumnChart: ColumnChart,
2392
+ BarChart: BarChart,
2393
+ AreaChart: AreaChart,
2394
+ GeoChart: GeoChart,
2395
+ ScatterChart: ScatterChart,
2396
+ BubbleChart: BubbleChart,
2397
+ Timeline: Timeline,
2398
+ charts: {},
2399
+ configure: function (options) {
2400
+ for (var key in options) {
2401
+ if (options.hasOwnProperty(key)) {
2402
+ config[key] = options[key];
2403
+ }
2404
+ }
2405
+ },
2406
+ setDefaultOptions: function (opts) {
2407
+ Chartkick.options = opts;
2408
+ },
2409
+ eachChart: function (callback) {
2410
+ for (var chartId in Chartkick.charts) {
2411
+ if (Chartkick.charts.hasOwnProperty(chartId)) {
2412
+ callback(Chartkick.charts[chartId]);
2413
+ }
2414
+ }
2415
+ },
2416
+ config: config,
2417
+ options: {},
2418
+ adapters: adapters,
2419
+ addAdapter: addAdapter,
2420
+ use: function(adapter) {
2421
+ addAdapter(adapter);
2422
+ return Chartkick;
2423
+ }
2424
+ };
2425
+
2426
+ // not ideal, but allows for simpler integration
2427
+ if (typeof window !== "undefined" && !window.Chartkick) {
2428
+ window.Chartkick = Chartkick;
2429
+ }
2430
+
2431
+ // backwards compatibility for esm require
2432
+ Chartkick.default = Chartkick;
2433
+
2434
+ return Chartkick;
2435
+
2436
+ })));