pghero_fork 2.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ })));