pghero 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pghero might be problematic. Click here for more details.

@@ -1,5 +1,5 @@
1
1
  //= require ./jquery
2
- //= require ./jquery.nouislider.min
2
+ //= require ./nouislider
3
3
  //= require ./Chart.bundle
4
4
  //= require ./chartkick
5
5
  //= require ./highlight.pack
@@ -32,9 +32,9 @@ function initSlider() {
32
32
 
33
33
  var max = (endAt > 0) ? (endAt - sliderStartAt) / (1000 * 60 * 5) : sliderMax;
34
34
 
35
- var $slider = $("#slider");
35
+ var slider = document.getElementById("slider");
36
36
 
37
- $slider.noUiSlider({
37
+ noUiSlider.create(slider, {
38
38
  range: {
39
39
  min: 0,
40
40
  max: sliderMax
@@ -45,7 +45,7 @@ function initSlider() {
45
45
  });
46
46
 
47
47
  function updateText() {
48
- var values = $slider.val();
48
+ var values = slider.noUiSlider.get();
49
49
  setText("#range-start", values[0]);
50
50
  setText("#range-end", values[1]);
51
51
  }
@@ -82,7 +82,7 @@ function initSlider() {
82
82
  }
83
83
 
84
84
  function refreshStats(push) {
85
- var values = $slider.val();
85
+ var values = slider.noUiSlider.get();
86
86
  var startAt = push ? timeAt(values[0]) : new Date(window.startAt);
87
87
  var endAt = timeAt(values[1]);
88
88
 
@@ -140,7 +140,8 @@ function initSlider() {
140
140
  }
141
141
  }
142
142
 
143
- $slider.on("slide", updateText).on("change", function () {
143
+ slider.noUiSlider.on("slide", updateText);
144
+ slider.noUiSlider.on("change", function () {
144
145
  refreshStats(true);
145
146
  });
146
147
  updateText();
@@ -2,22 +2,15 @@
2
2
  * Chartkick.js
3
3
  * Create beautiful charts with one line of JavaScript
4
4
  * https://github.com/ankane/chartkick.js
5
- * v2.2.2
5
+ * v3.2.0
6
6
  * MIT License
7
7
  */
8
8
 
9
- /*jslint browser: true, indent: 2, plusplus: true, vars: true */
10
-
11
- (function (window) {
12
- 'use strict';
13
-
14
- var config = window.Chartkick || {};
15
- var Chartkick, ISO8601_PATTERN, DECIMAL_SEPARATOR, adapters = [];
16
- var DATE_PATTERN = /^(\d\d\d\d)(\-)?(\d\d)(\-)?(\d\d)$/i;
17
- var GoogleChartsAdapter, HighchartsAdapter, ChartjsAdapter;
18
- var pendingRequests = [], runningRequests = 0, maxRequests = 4;
19
-
20
- // helpers
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';
21
14
 
22
15
  function isArray(variable) {
23
16
  return Object.prototype.toString.call(variable) === "[object Array]";
@@ -28,13 +21,17 @@
28
21
  }
29
22
 
30
23
  function isPlainObject(variable) {
31
- return !isFunction(variable) && variable instanceof Object;
24
+ // protect against prototype pollution, defense 2
25
+ return Object.prototype.toString.call(variable) === "[object Object]" && !isFunction(variable) && variable instanceof Object;
32
26
  }
33
27
 
34
28
  // https://github.com/madrobby/zepto/blob/master/src/zepto.js
35
29
  function extend(target, source) {
36
30
  var key;
37
31
  for (key in source) {
32
+ // protect against prototype pollution, defense 1
33
+ if (key === "__proto__") { continue; }
34
+
38
35
  if (isPlainObject(source[key]) || isArray(source[key])) {
39
36
  if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
40
37
  target[key] = {};
@@ -56,9 +53,11 @@
56
53
  return target;
57
54
  }
58
55
 
56
+ var DATE_PATTERN = /^(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)$/i;
57
+
59
58
  // https://github.com/Do/iso8601.js
60
- ISO8601_PATTERN = /(\d\d\d\d)(\-)?(\d\d)(\-)?(\d\d)(T)?(\d\d)(:)?(\d\d)?(:)?(\d\d)?([\.,]\d+)?($|Z|([\+\-])(\d\d)(:)?(\d\d)?)/i;
61
- DECIMAL_SEPARATOR = String(1.5).charAt(1);
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);
62
61
 
63
62
  function parseISO8601(input) {
64
63
  var day, hour, matches, milliseconds, minutes, month, offset, result, seconds, type, year;
@@ -105,6 +104,50 @@
105
104
  return false;
106
105
  }
107
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
+
108
151
  function jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle) {
109
152
  return function (chart, opts, chartOptions) {
110
153
  var series = chart.data;
@@ -154,1307 +197,1719 @@
154
197
  };
155
198
  }
156
199
 
157
- function setText(element, text) {
158
- if (document.body.innerText) {
159
- element.innerText = text;
160
- } else {
161
- element.textContent = text;
162
- }
200
+ function sortByTime(a, b) {
201
+ return a[0].getTime() - b[0].getTime();
163
202
  }
164
203
 
165
- function chartError(element, message) {
166
- setText(element, "Error Loading Chart: " + message);
167
- element.style.color = "#ff0000";
204
+ function sortByNumberSeries(a, b) {
205
+ return a[0] - b[0];
168
206
  }
169
207
 
170
- function pushRequest(element, url, success) {
171
- pendingRequests.push([element, url, success]);
172
- runNext();
208
+ function sortByNumber(a, b) {
209
+ return a - b;
173
210
  }
174
211
 
175
- function runNext() {
176
- if (runningRequests < maxRequests) {
177
- var request = pendingRequests.shift()
178
- if (request) {
179
- runningRequests++;
180
- getJSON(request[0], request[1], request[2]);
181
- runNext();
182
- }
183
- }
212
+ function isMinute(d) {
213
+ return d.getMilliseconds() === 0 && d.getSeconds() === 0;
184
214
  }
185
215
 
186
- function requestComplete() {
187
- runningRequests--;
188
- runNext();
216
+ function isHour(d) {
217
+ return isMinute(d) && d.getMinutes() === 0;
189
218
  }
190
219
 
191
- function getJSON(element, url, success) {
192
- ajaxCall(url, success, function (jqXHR, textStatus, errorThrown) {
193
- var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
194
- chartError(element, message);
195
- });
220
+ function isDay(d) {
221
+ return isHour(d) && d.getHours() === 0;
196
222
  }
197
223
 
198
- function ajaxCall(url, success, error) {
199
- var $ = window.jQuery || window.Zepto || window.$;
224
+ function isWeek(d, dayOfWeek) {
225
+ return isDay(d) && d.getDay() === dayOfWeek;
226
+ }
200
227
 
201
- if ($) {
202
- $.ajax({
203
- dataType: "json",
204
- url: url,
205
- success: success,
206
- error: error,
207
- complete: requestComplete
208
- });
209
- } else {
210
- var xhr = new XMLHttpRequest();
211
- xhr.open("GET", url, true);
212
- xhr.setRequestHeader("Content-Type", "application/json");
213
- xhr.onload = function () {
214
- requestComplete();
215
- if (xhr.status === 200) {
216
- success(JSON.parse(xhr.responseText), xhr.statusText, xhr);
217
- } else {
218
- error(xhr, "error", xhr.statusText);
219
- }
220
- };
221
- xhr.send();
222
- }
228
+ function isMonth(d) {
229
+ return isDay(d) && d.getDate() === 1;
223
230
  }
224
231
 
225
- function errorCatcher(chart, callback) {
226
- try {
227
- callback(chart);
228
- } catch (err) {
229
- chartError(chart.element, err.message);
230
- throw err;
231
- }
232
+ function isYear(d) {
233
+ return isMonth(d) && d.getMonth() === 0;
232
234
  }
233
235
 
234
- function fetchDataSource(chart, callback, dataSource) {
235
- if (typeof dataSource === "string") {
236
- pushRequest(chart.element, dataSource, function (data, textStatus, jqXHR) {
237
- chart.rawData = data;
238
- errorCatcher(chart, callback);
239
- });
240
- } else {
241
- chart.rawData = dataSource;
242
- errorCatcher(chart, callback);
243
- }
236
+ function isDate(obj) {
237
+ return !isNaN(toDate(obj)) && toStr(obj).length >= 6;
244
238
  }
245
239
 
246
- function addDownloadButton(chart) {
247
- var element = chart.element;
248
- var link = document.createElement("a");
249
- link.download = chart.options.download === true ? "chart.png" : chart.options.download; // http://caniuse.com/download
250
- link.style.position = "absolute";
251
- link.style.top = "20px";
252
- link.style.right = "20px";
253
- link.style.zIndex = 1000;
254
- link.style.lineHeight = "20px";
255
- link.target = "_blank"; // for safari
256
- var image = document.createElement("img");
257
- image.alt = "Download";
258
- image.style.border = "none";
259
- // icon from font-awesome
260
- // http://fa2png.io/
261
- image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAABCFBMVEUAAADMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMywEsqxAAAAV3RSTlMAAQIDBggJCgsMDQ4PERQaHB0eISIjJCouLzE0OTo/QUJHSUpLTU5PUllhYmltcHh5foWLjI+SlaCio6atr7S1t7m6vsHHyM7R2tze5Obo7fHz9ff5+/1hlxK2AAAA30lEQVQYGUXBhVYCQQBA0TdYWAt2d3d3YWAHyur7/z9xgD16Lw0DW+XKx+1GgX+FRzM3HWQWrHl5N/oapW5RPe0PkBu+UYeICvozTWZVK23Ao04B79oJrOsJDOoxkZoQPWgX29pHpCZEk7rEvQYiNSFq1UMqvlCjJkRBS1R8hb00Vb/TajtBL7nTHE1X1vyMQF732dQhyF2o6SAwrzP06iUQzvwsArlnzcOdrgBhJyHa1QOgO9U1GsKuvjUTjavliZYQ8nNPapG6sap/3nrIdJ6bOWzmX/fy0XVpfzZP3S8OJT3g9EEiJwAAAABJRU5ErkJggg==";
262
- link.appendChild(image);
263
- element.style.position = "relative";
240
+ function isNumber(obj) {
241
+ return typeof obj === "number";
242
+ }
264
243
 
265
- chart.downloadAttached = true;
244
+ var byteSuffixes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB"];
266
245
 
267
- // mouseenter
268
- addEvent(element, "mouseover", function(e) {
269
- var related = e.relatedTarget;
270
- // check download option again to ensure it wasn't changed
271
- if (!related || (related !== this && !childOf(this, related)) && chart.options.download) {
272
- link.href = chart.toImage();
273
- element.appendChild(link);
246
+ function formatValue(pre, value, options, axis) {
247
+ pre = pre || "";
248
+ if (options.prefix) {
249
+ if (value < 0) {
250
+ value = value * -1;
251
+ pre += "-";
274
252
  }
275
- });
253
+ pre += options.prefix;
254
+ }
276
255
 
277
- // mouseleave
278
- addEvent(element, "mouseout", function(e) {
279
- var related = e.relatedTarget;
280
- if (!related || (related !== this && !childOf(this, related))) {
281
- if (link.parentNode) {
282
- link.parentNode.removeChild(link);
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
+ }
283
293
  }
294
+ precision = value >= 1000 ? 4 : 3;
284
295
  }
285
- });
286
- }
296
+ suffix = " " + byteSuffixes[suffixIdx];
297
+ }
287
298
 
288
- // http://stackoverflow.com/questions/10149963/adding-event-listener-cross-browser
289
- function addEvent(elem, event, fn) {
290
- if (elem.addEventListener) {
291
- elem.addEventListener(event, fn, false);
292
- } else {
293
- elem.attachEvent("on" + event, function() {
294
- // set the this pointer same as addEventListener when fn is called
295
- return(fn.call(elem, window.event));
296
- });
299
+ if (precision !== undefined && round !== undefined) {
300
+ throw Error("Use either round or precision, not both");
297
301
  }
298
- }
299
302
 
300
- // https://gist.github.com/shawnbot/4166283
301
- function childOf(p, c) {
302
- if (p === c) return false;
303
- while (c && c !== p) c = c.parentNode;
304
- return c === p;
305
- }
303
+ if (!axis) {
304
+ if (precision !== undefined) {
305
+ value = value.toPrecision(precision);
306
+ if (!options.zeros) {
307
+ value = parseFloat(value);
308
+ }
309
+ }
306
310
 
307
- // type conversions
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
+ }
308
323
 
309
- function toStr(n) {
310
- return "" + n;
311
- }
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
+ }
312
335
 
313
- function toFloat(n) {
314
- return parseFloat(n);
336
+ return pre + value + suffix;
315
337
  }
316
338
 
317
- function toDate(n) {
318
- var matches, year, month, day;
319
- if (typeof n !== "object") {
320
- if (typeof n === "number") {
321
- n = new Date(n * 1000); // ms
322
- } else if ((matches = n.match(DATE_PATTERN))) {
323
- year = parseInt(matches[1], 10);
324
- month = parseInt(matches[3], 10) - 1;
325
- day = parseInt(matches[5], 10);
326
- return new Date(year, month, day);
327
- } else { // str
328
- // try our best to get the str into iso8601
329
- // TODO be smarter about this
330
- var str = n.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
331
- n = parseISO8601(str) || new Date(n);
332
- }
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];
333
344
  }
334
- return n;
345
+ return null;
335
346
  }
336
347
 
337
- function toArr(n) {
338
- if (!isArray(n)) {
339
- var arr = [], i;
340
- for (i in n) {
341
- if (n.hasOwnProperty(i)) {
342
- arr.push([i, n[i]]);
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;
343
355
  }
344
356
  }
345
- n = arr;
346
357
  }
347
- return n;
348
- }
349
-
350
- function sortByTime(a, b) {
351
- return a[0].getTime() - b[0].getTime();
352
- }
353
-
354
- function sortByNumberSeries(a, b) {
355
- return a[0] - b[0];
358
+ return true;
356
359
  }
357
360
 
358
- function sortByNumber(a, b) {
359
- return a - b;
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
+ };
361
371
 
362
- function loadAdapters() {
363
- if (!HighchartsAdapter && "Highcharts" in window) {
364
- HighchartsAdapter = new function () {
365
- var Highcharts = window.Highcharts;
366
-
367
- this.name = "highcharts";
368
-
369
- var defaultOptions = {
370
- chart: {},
371
- xAxis: {
372
- title: {
373
- text: null
374
- },
375
- labels: {
376
- style: {
377
- fontSize: "12px"
378
- }
379
- }
380
- },
381
- yAxis: {
382
- title: {
383
- text: null
384
- },
385
- labels: {
386
- style: {
387
- fontSize: "12px"
388
- }
389
- }
372
+ var defaultOptions = {
373
+ scales: {
374
+ yAxes: [
375
+ {
376
+ ticks: {
377
+ maxTicksLimit: 4
390
378
  },
391
- title: {
392
- text: null
393
- },
394
- credits: {
395
- enabled: false
396
- },
397
- legend: {
398
- borderWidth: 0
379
+ scaleLabel: {
380
+ fontSize: 16,
381
+ // fontStyle: "bold",
382
+ fontColor: "#333"
383
+ }
384
+ }
385
+ ],
386
+ xAxes: [
387
+ {
388
+ gridLines: {
389
+ drawOnChartArea: false
399
390
  },
400
- tooltip: {
401
- style: {
402
- fontSize: "12px"
403
- }
391
+ scaleLabel: {
392
+ fontSize: 16,
393
+ // fontStyle: "bold",
394
+ fontColor: "#333"
404
395
  },
405
- plotOptions: {
406
- areaspline: {},
407
- series: {
408
- marker: {}
409
- }
410
- }
411
- };
396
+ time: {},
397
+ ticks: {}
398
+ }
399
+ ]
400
+ }
401
+ };
412
402
 
413
- var hideLegend = function (options, legend, hideLegend) {
414
- if (legend !== undefined) {
415
- options.legend.enabled = !!legend;
416
- if (legend && legend !== true) {
417
- if (legend === "top" || legend === "bottom") {
418
- options.legend.verticalAlign = legend;
419
- } else {
420
- options.legend.layout = "vertical";
421
- options.legend.verticalAlign = "middle";
422
- options.legend.align = legend;
423
- }
424
- }
425
- } else if (hideLegend) {
426
- options.legend.enabled = false;
427
- }
428
- };
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
+ };
429
420
 
430
- var setTitle = function (options, title) {
431
- options.title.text = title;
432
- };
421
+ var setTitle = function (options, title) {
422
+ options.title.display = true;
423
+ options.title.text = title;
424
+ };
433
425
 
434
- var setMin = function (options, min) {
435
- options.yAxis.min = min;
436
- };
426
+ var setMin = function (options, min) {
427
+ if (min !== null) {
428
+ options.scales.yAxes[0].ticks.min = toFloat(min);
429
+ }
430
+ };
437
431
 
438
- var setMax = function (options, max) {
439
- options.yAxis.max = max;
440
- };
432
+ var setMax = function (options, max) {
433
+ options.scales.yAxes[0].ticks.max = toFloat(max);
434
+ };
441
435
 
442
- var setStacked = function (options, stacked) {
443
- options.plotOptions.series.stacking = stacked ? "normal" : null;
444
- };
436
+ var setBarMin = function (options, min) {
437
+ if (min !== null) {
438
+ options.scales.xAxes[0].ticks.min = toFloat(min);
439
+ }
440
+ };
445
441
 
446
- var setXtitle = function (options, title) {
447
- options.xAxis.title.text = title;
448
- };
449
-
450
- var setYtitle = function (options, title) {
451
- options.yAxis.title.text = title;
452
- };
453
-
454
- var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
455
-
456
- this.renderLineChart = function (chart, chartType) {
457
- chartType = chartType || "spline";
458
- var chartOptions = {};
459
- if (chartType === "areaspline") {
460
- chartOptions = {
461
- plotOptions: {
462
- areaspline: {
463
- stacking: "normal"
464
- },
465
- area: {
466
- stacking: "normal"
467
- },
468
- series: {
469
- marker: {
470
- enabled: false
471
- }
472
- }
473
- }
474
- };
475
- }
476
-
477
- if (chart.options.curve === false) {
478
- if (chartType === "areaspline") {
479
- chartType = "area";
480
- } else if (chartType === "spline") {
481
- chartType = "line";
482
- }
483
- }
442
+ var setBarMax = function (options, max) {
443
+ options.scales.xAxes[0].ticks.max = toFloat(max);
444
+ };
484
445
 
485
- var options = jsOptions(chart, chart.options, chartOptions), data, i, j;
486
- options.xAxis.type = chart.discrete ? "category" : "datetime";
487
- if (!options.chart.type) {
488
- options.chart.type = chartType;
489
- }
490
- options.chart.renderTo = chart.element.id;
491
-
492
- var series = chart.data;
493
- for (i = 0; i < series.length; i++) {
494
- data = series[i].data;
495
- if (!chart.discrete) {
496
- for (j = 0; j < data.length; j++) {
497
- data[j][0] = data[j][0].getTime();
498
- }
499
- }
500
- series[i].marker = {symbol: "circle"};
501
- if (chart.options.points === false) {
502
- series[i].marker.enabled = false;
503
- }
504
- }
505
- options.series = series;
506
- chart.chart = new Highcharts.Chart(options);
507
- };
446
+ var setStacked = function (options, stacked) {
447
+ options.scales.xAxes[0].stacked = !!stacked;
448
+ options.scales.yAxes[0].stacked = !!stacked;
449
+ };
508
450
 
509
- this.renderScatterChart = function (chart) {
510
- var chartOptions = {};
511
- var options = jsOptions(chart, chart.options, chartOptions);
512
- options.chart.type = "scatter";
513
- options.chart.renderTo = chart.element.id;
514
- options.series = chart.data;
515
- chart.chart = new Highcharts.Chart(options);
516
- };
451
+ var setXtitle = function (options, title) {
452
+ options.scales.xAxes[0].scaleLabel.display = true;
453
+ options.scales.xAxes[0].scaleLabel.labelString = title;
454
+ };
517
455
 
518
- this.renderPieChart = function (chart) {
519
- var chartOptions = merge(defaultOptions, {});
456
+ var setYtitle = function (options, title) {
457
+ options.scales.yAxes[0].scaleLabel.display = true;
458
+ options.scales.yAxes[0].scaleLabel.labelString = title;
459
+ };
520
460
 
521
- if (chart.options.colors) {
522
- chartOptions.colors = chart.options.colors;
523
- }
524
- if (chart.options.donut) {
525
- chartOptions.plotOptions = {pie: {innerSize: "50%"}};
526
- }
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
+ };
527
466
 
528
- if ("legend" in chart.options) {
529
- hideLegend(chartOptions, chart.options.legend);
530
- }
467
+ // check if not null or undefined
468
+ // https://stackoverflow.com/a/27757708/1177228
469
+ var notnull = function(x) {
470
+ return x != null;
471
+ };
531
472
 
532
- if (chart.options.title) {
533
- setTitle(chartOptions, chart.options.title);
534
- }
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
+ };
535
491
 
536
- var options = merge(chartOptions, chart.options.library || {});
537
- options.chart.renderTo = chart.element.id;
538
- options.series = [{
539
- type: "pie",
540
- name: chart.options.label || "Value",
541
- data: chart.data
542
- }];
543
- chart.chart = new Highcharts.Chart(options);
544
- };
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
+ };
545
502
 
546
- this.renderColumnChart = function (chart, chartType) {
547
- chartType = chartType || "column";
548
- var series = chart.data;
549
- var options = jsOptions(chart, chart.options), i, j, s, d, rows = [], categories = [];
550
- options.chart.type = chartType;
551
- options.chart.renderTo = chart.element.id;
552
-
553
- for (i = 0; i < series.length; i++) {
554
- s = series[i];
555
-
556
- for (j = 0; j < s.data.length; j++) {
557
- d = s.data[j];
558
- if (!rows[d[0]]) {
559
- rows[d[0]] = new Array(series.length);
560
- categories.push(d[0]);
561
- }
562
- rows[d[0]][i] = d[1];
563
- }
564
- }
503
+ if (chart.options.bytes) {
504
+ var series = chart.data;
505
+ if (chartType === "pie") {
506
+ series = [{data: series}];
507
+ }
565
508
 
566
- if (chart.options.xtype === "number") {
567
- categories.sort(sortByNumber);
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];
568
516
  }
517
+ }
518
+ }
569
519
 
570
- options.xAxis.categories = categories;
571
-
572
- var newSeries = [];
573
- for (i = 0; i < series.length; i++) {
574
- d = [];
575
- for (j = 0; j < categories.length; j++) {
576
- d.push(rows[categories[j]][i] || 0);
577
- }
520
+ // calculate scale
521
+ var scale = 1;
522
+ while (max >= 1024) {
523
+ scale *= 1024;
524
+ max /= 1024;
525
+ }
578
526
 
579
- newSeries.push({
580
- name: series[i].name,
581
- data: d
582
- });
583
- }
584
- options.series = newSeries;
527
+ // set step size
528
+ formatOptions.byteScale = scale;
529
+ }
585
530
 
586
- chart.chart = new Highcharts.Chart(options);
587
- };
531
+ if (chartType !== "pie") {
532
+ var myAxes = options.scales.yAxes;
533
+ if (chartType === "bar") {
534
+ myAxes = options.scales.xAxes;
535
+ }
588
536
 
589
- var self = this;
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
+ }
590
545
 
591
- this.renderBarChart = function (chart) {
592
- self.renderColumnChart(chart, "bar");
546
+ if (!myAxes[0].ticks.callback) {
547
+ myAxes[0].ticks.callback = function (value) {
548
+ return formatValue("", value, formatOptions, true);
593
549
  };
550
+ }
551
+ }
594
552
 
595
- this.renderAreaChart = function (chart) {
596
- self.renderLineChart(chart, "areaspline");
597
- };
598
- };
599
- adapters.push(HighchartsAdapter);
600
- }
601
- if (!GoogleChartsAdapter && window.google && (window.google.setOnLoadCallback || window.google.charts)) {
602
- GoogleChartsAdapter = new function () {
603
- var google = window.google;
604
-
605
- this.name = "google";
606
-
607
- var loaded = {};
608
- var callbacks = [];
609
-
610
- var runCallbacks = function () {
611
- var cb, call;
612
- for (var i = 0; i < callbacks.length; i++) {
613
- cb = callbacks[i];
614
- call = google.visualization && ((cb.pack === "corechart" && google.visualization.LineChart) || (cb.pack === "timeline" && google.visualization.Timeline));
615
- if (call) {
616
- cb.callback();
617
- callbacks.splice(i, 1);
618
- i--;
619
- }
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 += ': ';
620
559
  }
560
+ return label + '(' + item.xLabel + ', ' + item.yLabel + ')';
621
561
  };
622
-
623
- var waitForLoaded = function (pack, callback) {
624
- if (!callback) {
625
- callback = pack;
626
- pack = "corechart";
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 += ': ';
627
567
  }
628
-
629
- callbacks.push({pack: pack, callback: callback});
630
-
631
- if (loaded[pack]) {
632
- runCallbacks();
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;
633
582
  } else {
634
- loaded[pack] = true;
635
-
636
- // https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
637
- var loadOptions = {
638
- packages: [pack],
639
- callback: runCallbacks
640
- };
641
- if (config.language) {
642
- loadOptions.language = config.language;
643
- }
644
-
645
- if (window.google.setOnLoadCallback) {
646
- google.load("visualization", "1", loadOptions);
647
- } else {
648
- google.charts.load("current", loadOptions);
649
- }
583
+ dataLabel += value;
650
584
  }
651
- };
652
585
 
653
- // Set chart options
654
- var defaultOptions = {
655
- chartArea: {},
656
- fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
657
- pointSize: 6,
658
- legend: {
659
- textStyle: {
660
- fontSize: 12,
661
- color: "#444"
662
- },
663
- alignment: "center",
664
- position: "right"
665
- },
666
- curveType: "function",
667
- hAxis: {
668
- textStyle: {
669
- color: "#666",
670
- fontSize: 12
671
- },
672
- titleTextStyle: {},
673
- gridlines: {
674
- color: "transparent"
675
- },
676
- baselineColor: "#ccc",
677
- viewWindow: {}
678
- },
679
- vAxis: {
680
- textStyle: {
681
- color: "#666",
682
- fontSize: 12
683
- },
684
- titleTextStyle: {},
685
- baselineColor: "#ccc",
686
- viewWindow: {}
687
- },
688
- tooltip: {
689
- textStyle: {
690
- color: "#666",
691
- fontSize: 12
692
- }
693
- }
586
+ return formatValue(dataLabel, data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index], formatOptions);
694
587
  };
695
-
696
- var hideLegend = function (options, legend, hideLegend) {
697
- if (legend !== undefined) {
698
- var position;
699
- if (!legend) {
700
- position = "none";
701
- } else if (legend === true) {
702
- position = "right";
703
- } else {
704
- position = legend;
705
- }
706
- options.legend.position = position;
707
- } else if (hideLegend) {
708
- options.legend.position = "none";
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 += ': ';
709
594
  }
595
+ return formatValue(label, tooltipItem[valueLabel], formatOptions);
710
596
  };
597
+ }
598
+ }
599
+ };
711
600
 
712
- var setTitle = function (options, title) {
713
- options.title = title;
714
- options.titleTextStyle = {color: "#333", fontSize: "20px"};
715
- };
601
+ var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
716
602
 
717
- var setMin = function (options, min) {
718
- options.vAxis.viewWindow.min = min;
719
- };
603
+ var createDataTable = function (chart, options, chartType, library) {
604
+ var datasets = [];
605
+ var labels = [];
720
606
 
721
- var setMax = function (options, max) {
722
- options.vAxis.viewWindow.max = max;
723
- };
607
+ var colors = chart.options.colors || defaultColors;
724
608
 
725
- var setBarMin = function (options, min) {
726
- options.hAxis.viewWindow.min = min;
727
- };
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;
728
616
 
729
- var setBarMax = function (options, max) {
730
- options.hAxis.viewWindow.max = max;
731
- };
617
+ var series = chart.data;
732
618
 
733
- var setStacked = function (options, stacked) {
734
- options.isStacked = !!stacked;
735
- };
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
+ }
736
630
 
737
- var setXtitle = function (options, title) {
738
- options.hAxis.title = title;
739
- options.hAxis.titleTextStyle.italic = false;
740
- };
631
+ var i, j, s, d, key, rows = [], rows2 = [];
741
632
 
742
- var setYtitle = function (options, title) {
743
- options.vAxis.title = title;
744
- options.vAxis.titleTextStyle.italic = false;
745
- };
633
+ if (chartType === "bar" || chartType === "column" || (chart.xtype !== "number" && chart.xtype !== "bubble")) {
634
+ var sortedLabels = [];
746
635
 
747
- var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
748
-
749
- // cant use object as key
750
- var createDataTable = function (series, columnType, xtype) {
751
- var i, j, s, d, key, rows = [], sortedLabels = [];
752
- for (i = 0; i < series.length; i++) {
753
- s = series[i];
754
-
755
- for (j = 0; j < s.data.length; j++) {
756
- d = s.data[j];
757
- key = (columnType === "datetime") ? d[0].getTime() : d[0];
758
- if (!rows[key]) {
759
- rows[key] = new Array(series.length);
760
- sortedLabels.push(key);
761
- }
762
- rows[key][i] = toFloat(d[1]);
763
- }
764
- }
636
+ for (i = 0; i < series.length; i++) {
637
+ s = series[i];
765
638
 
766
- var rows2 = [];
767
- var day = true;
768
- var value;
769
- for (var j = 0; j < sortedLabels.length; j++) {
770
- var i = sortedLabels[j];
771
- if (columnType === "datetime") {
772
- value = new Date(toFloat(i));
773
- day = day && isDay(value);
774
- } else if (columnType === "number") {
775
- value = toFloat(i);
776
- } else {
777
- value = i;
778
- }
779
- rows2.push([value].concat(rows[i]));
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);
780
644
  }
781
- if (columnType === "datetime") {
782
- rows2.sort(sortByTime);
783
- } else if (columnType === "number") {
784
- rows2.sort(sortByNumberSeries);
645
+ rows[key][i] = toFloat(d[1]);
646
+ if (sortedLabels.indexOf(key) === -1) {
647
+ sortedLabels.push(key);
785
648
  }
649
+ }
650
+ }
786
651
 
787
- if (xtype === "number") {
788
- rows2.sort(sortByNumberSeries);
652
+ if (chart.xtype === "datetime" || chart.xtype === "number") {
653
+ sortedLabels.sort(sortByNumber);
654
+ }
789
655
 
790
- for (var i = 0; i < rows2.length; i++) {
791
- rows2[i][0] = toStr(rows2[i][0]);
792
- }
793
- }
656
+ for (j = 0; j < series.length; j++) {
657
+ rows2.push([]);
658
+ }
794
659
 
795
- // create datatable
796
- var data = new google.visualization.DataTable();
797
- columnType = columnType === "datetime" && day ? "date" : columnType;
798
- data.addColumn(columnType, "");
799
- for (i = 0; i < series.length; i++) {
800
- data.addColumn("number", series[i].name);
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();
801
670
  }
802
- data.addRows(rows2);
803
-
804
- return data;
805
- };
806
-
807
- var resize = function (callback) {
808
- if (window.attachEvent) {
809
- window.attachEvent("onresize", callback);
810
- } else if (window.addEventListener) {
811
- window.addEventListener("resize", callback, true);
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];
812
698
  }
813
- callback();
814
- };
815
-
816
- this.renderLineChart = function (chart) {
817
- waitForLoaded(function () {
818
- var chartOptions = {};
699
+ d$1.push(point);
700
+ }
701
+ rows2.push(d$1);
702
+ }
703
+ }
819
704
 
820
- if (chart.options.curve === false) {
821
- chartOptions.curveType = "none";
822
- }
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
+ };
823
721
 
824
- if (chart.options.points === false) {
825
- chartOptions.pointSize = 0;
826
- }
722
+ if (s.stack) {
723
+ dataset.stack = s.stack;
724
+ }
827
725
 
828
- var options = jsOptions(chart, chart.options, chartOptions);
829
- var columnType = chart.discrete ? "string" : "datetime";
830
- if (chart.options.xtype === "number") {
831
- columnType = "number";
832
- }
833
- var data = createDataTable(chart.data, columnType);
834
- chart.chart = new google.visualization.LineChart(chart.element);
835
- resize(function () {
836
- chart.chart.draw(data, options);
837
- });
838
- });
839
- };
726
+ var curve = seriesOption(chart, s, "curve");
727
+ if (curve === false) {
728
+ dataset.lineTension = 0;
729
+ }
840
730
 
841
- this.renderPieChart = function (chart) {
842
- waitForLoaded(function () {
843
- var chartOptions = {
844
- chartArea: {
845
- top: "10%",
846
- height: "80%"
847
- },
848
- legend: {}
849
- };
850
- if (chart.options.colors) {
851
- chartOptions.colors = chart.options.colors;
852
- }
853
- if (chart.options.donut) {
854
- chartOptions.pieHole = 0.5;
855
- }
856
- if ("legend" in chart.options) {
857
- hideLegend(chartOptions, chart.options.legend);
858
- }
859
- if (chart.options.title) {
860
- setTitle(chartOptions, chart.options.title);
861
- }
862
- var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
863
-
864
- var data = new google.visualization.DataTable();
865
- data.addColumn("string", "");
866
- data.addColumn("number", "Value");
867
- data.addRows(chart.data);
868
-
869
- chart.chart = new google.visualization.PieChart(chart.element);
870
- resize(function () {
871
- chart.chart.draw(data, options);
872
- });
873
- });
874
- };
731
+ var points = seriesOption(chart, s, "points");
732
+ if (points === false) {
733
+ dataset.pointRadius = 0;
734
+ dataset.pointHitRadius = 5;
735
+ }
875
736
 
876
- this.renderColumnChart = function (chart) {
877
- waitForLoaded(function () {
878
- var options = jsOptions(chart, chart.options);
879
- var data = createDataTable(chart.data, "string", chart.options.xtype);
880
- chart.chart = new google.visualization.ColumnChart(chart.element);
881
- resize(function () {
882
- chart.chart.draw(data, options);
883
- });
884
- });
885
- };
737
+ dataset = merge(dataset, chart.options.dataset || {});
738
+ dataset = merge(dataset, s.library || {});
739
+ dataset = merge(dataset, s.dataset || {});
886
740
 
887
- this.renderBarChart = function (chart) {
888
- waitForLoaded(function () {
889
- var chartOptions = {
890
- hAxis: {
891
- gridlines: {
892
- color: "#ccc"
893
- }
894
- }
895
- };
896
- var options = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options, chartOptions);
897
- var data = createDataTable(chart.data, "string", chart.options.xtype);
898
- chart.chart = new google.visualization.BarChart(chart.element);
899
- resize(function () {
900
- chart.chart.draw(data, options);
901
- });
902
- });
903
- };
741
+ datasets.push(dataset);
742
+ }
904
743
 
905
- this.renderAreaChart = function (chart) {
906
- waitForLoaded(function () {
907
- var chartOptions = {
908
- isStacked: true,
909
- pointSize: 0,
910
- areaOpacity: 0.5
911
- };
912
-
913
- var options = jsOptions(chart, chart.options, chartOptions);
914
- var columnType = chart.discrete ? "string" : "datetime";
915
- if (chart.options.xtype === "number") {
916
- columnType = "number";
917
- }
918
- var data = createDataTable(chart.data, columnType);
919
- chart.chart = new google.visualization.AreaChart(chart.element);
920
- resize(function () {
921
- chart.chart.draw(data, options);
922
- });
923
- });
924
- };
744
+ var xmin = chart.options.xmin;
745
+ var xmax = chart.options.xmax;
925
746
 
926
- this.renderGeoChart = function (chart) {
927
- waitForLoaded(function () {
928
- var chartOptions = {
929
- legend: "none",
930
- colorAxis: {
931
- colors: chart.options.colors || ["#f6c7b6", "#ce502d"]
932
- }
933
- };
934
- var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
935
-
936
- var data = new google.visualization.DataTable();
937
- data.addColumn("string", "");
938
- data.addColumn("number", chart.options.label || "Value");
939
- data.addRows(chart.data);
940
-
941
- chart.chart = new google.visualization.GeoChart(chart.element);
942
- resize(function () {
943
- chart.chart.draw(data, options);
944
- });
945
- });
946
- };
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
+ }
947
766
 
948
- this.renderScatterChart = function (chart) {
949
- waitForLoaded(function () {
950
- var chartOptions = {};
951
- var options = jsOptions(chart, chart.options, chartOptions);
952
-
953
- var series = chart.data, rows2 = [], i, j, data, d;
954
- for (i = 0; i < series.length; i++) {
955
- d = series[i].data;
956
- for (j = 0; j < d.length; j++) {
957
- var row = new Array(series.length + 1);
958
- row[0] = d[j][0];
959
- row[i + 1] = d[j][1];
960
- rows2.push(row);
961
- }
962
- }
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();
963
770
 
964
- var data = new google.visualization.DataTable();
965
- data.addColumn("number", "");
966
- for (i = 0; i < series.length; i++) {
967
- data.addColumn("number", series[i].name);
968
- }
969
- data.addRows(rows2);
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
+ }
970
780
 
971
- chart.chart = new google.visualization.ScatterChart(chart.element);
972
- resize(function () {
973
- chart.chart.draw(data, options);
974
- });
975
- });
976
- };
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
+ }
977
803
 
978
- this.renderTimeline = function (chart) {
979
- waitForLoaded("timeline", function () {
980
- var chartOptions = {
981
- legend: "none"
982
- };
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
+ }
983
812
 
984
- if (chart.options.colors) {
985
- chartOptions.colors = chart.options.colors;
986
- }
987
- var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
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
+ }
988
823
 
989
- var data = new google.visualization.DataTable();
990
- data.addColumn({type: "string", id: "Name"});
991
- data.addColumn({type: "date", id: "Start"});
992
- data.addColumn({type: "date", id: "End"});
993
- data.addRows(chart.data);
824
+ var data = {
825
+ labels: labels,
826
+ datasets: datasets
827
+ };
994
828
 
995
- chart.element.style.lineHeight = "normal";
996
- chart.chart = new google.visualization.Timeline(chart.element);
829
+ return data;
830
+ };
997
831
 
998
- resize(function () {
999
- chart.chart.draw(data, options);
1000
- });
1001
- });
1002
- };
1003
- };
832
+ var defaultExport = function defaultExport(library) {
833
+ this.name = "chartjs";
834
+ this.library = library;
835
+ };
1004
836
 
1005
- adapters.push(GoogleChartsAdapter);
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;
1006
842
  }
1007
- if (!ChartjsAdapter && "Chart" in window) {
1008
- ChartjsAdapter = new function () {
1009
- var Chart = window.Chart;
1010
-
1011
- this.name = "chartjs";
1012
843
 
1013
- var baseOptions = {
1014
- maintainAspectRatio: false,
1015
- animation: false,
1016
- tooltips: {
1017
- displayColors: false
1018
- },
1019
- legend: {},
1020
- title: {fontSize: 20, fontColor: "#333"}
1021
- };
844
+ var options = jsOptions(chart, merge(chartOptions, chart.options));
845
+ setFormatOptions(chart, options, chartType);
1022
846
 
1023
- var defaultOptions = {
1024
- scales: {
1025
- yAxes: [
1026
- {
1027
- ticks: {
1028
- maxTicksLimit: 4
1029
- },
1030
- scaleLabel: {
1031
- fontSize: 16,
1032
- // fontStyle: "bold",
1033
- fontColor: "#333"
1034
- }
1035
- }
1036
- ],
1037
- xAxes: [
1038
- {
1039
- gridLines: {
1040
- drawOnChartArea: false
1041
- },
1042
- scaleLabel: {
1043
- fontSize: 16,
1044
- // fontStyle: "bold",
1045
- fontColor: "#333"
1046
- },
1047
- time: {},
1048
- ticks: {}
1049
- }
1050
- ]
1051
- }
1052
- };
847
+ var data = createDataTable(chart, options, chartType || "line", this.library);
1053
848
 
1054
- // http://there4.io/2012/05/02/google-chart-color-list/
1055
- var defaultColors = [
1056
- "#3366CC", "#DC3912", "#FF9900", "#109618", "#990099", "#3B3EAC", "#0099C6",
1057
- "#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11",
1058
- "#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#3B3EAC"
1059
- ];
1060
-
1061
- var hideLegend = function (options, legend, hideLegend) {
1062
- if (legend !== undefined) {
1063
- options.legend.display = !!legend;
1064
- if (legend && legend !== true) {
1065
- options.legend.position = legend;
1066
- }
1067
- } else if (hideLegend) {
1068
- options.legend.display = false;
1069
- }
1070
- };
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
+ }
1071
855
 
1072
- var setTitle = function (options, title) {
1073
- options.title.display = true;
1074
- options.title.text = title;
1075
- };
856
+ this.drawChart(chart, "line", data, options);
857
+ };
1076
858
 
1077
- var setMin = function (options, min) {
1078
- if (min !== null) {
1079
- options.scales.yAxes[0].ticks.min = toFloat(min);
1080
- }
1081
- };
859
+ defaultExport.prototype.renderPieChart = function renderPieChart (chart) {
860
+ var options = merge({}, baseOptions);
861
+ if (chart.options.donut) {
862
+ options.cutoutPercentage = 50;
863
+ }
1082
864
 
1083
- var setMax = function (options, max) {
1084
- options.scales.yAxes[0].ticks.max = toFloat(max);
1085
- };
865
+ if ("legend" in chart.options) {
866
+ hideLegend(options, chart.options.legend);
867
+ }
1086
868
 
1087
- var setBarMin = function (options, min) {
1088
- if (min !== null) {
1089
- options.scales.xAxes[0].ticks.min = toFloat(min);
1090
- }
1091
- };
869
+ if (chart.options.title) {
870
+ setTitle(options, chart.options.title);
871
+ }
1092
872
 
1093
- var setBarMax = function (options, max) {
1094
- options.scales.xAxes[0].ticks.max = toFloat(max);
1095
- };
873
+ options = merge(options, chart.options.library || {});
874
+ setFormatOptions(chart, options, "pie");
1096
875
 
1097
- var setStacked = function (options, stacked) {
1098
- options.scales.xAxes[0].stacked = !!stacked;
1099
- options.scales.yAxes[0].stacked = !!stacked;
1100
- };
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
+ }
1101
883
 
1102
- var setXtitle = function (options, title) {
1103
- options.scales.xAxes[0].scaleLabel.display = true;
1104
- options.scales.xAxes[0].scaleLabel.labelString = title;
1105
- };
884
+ var dataset = {
885
+ data: values,
886
+ backgroundColor: chart.options.colors || defaultColors
887
+ };
888
+ dataset = merge(dataset, chart.options.dataset || {});
1106
889
 
1107
- var setYtitle = function (options, title) {
1108
- options.scales.yAxes[0].scaleLabel.display = true;
1109
- options.scales.yAxes[0].scaleLabel.labelString = title;
1110
- };
890
+ var data = {
891
+ labels: labels,
892
+ datasets: [dataset]
893
+ };
1111
894
 
1112
- var drawChart = function(chart, type, data, options) {
1113
- if (chart.chart) {
1114
- chart.chart.destroy();
1115
- } else {
1116
- chart.element.innerHTML = "<canvas></canvas>";
1117
- }
895
+ this.drawChart(chart, "pie", data, options);
896
+ };
1118
897
 
1119
- var ctx = chart.element.getElementsByTagName("CANVAS")[0];
1120
- chart.chart = new Chart(ctx, {
1121
- type: type,
1122
- data: data,
1123
- options: options
1124
- });
1125
- };
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
+ };
1126
914
 
1127
- // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
1128
- var addOpacity = function(hex, opacity) {
1129
- var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1130
- return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
1131
- };
915
+ defaultExport.prototype.renderAreaChart = function renderAreaChart (chart) {
916
+ this.renderLineChart(chart, "area");
917
+ };
1132
918
 
1133
- var setLabelSize = function (chart, data, options) {
1134
- var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
1135
- if (maxLabelSize > 25) {
1136
- maxLabelSize = 25;
1137
- }
1138
- options.scales.xAxes[0].ticks.callback = function (value) {
1139
- value = toStr(value);
1140
- if (value.length > maxLabelSize) {
1141
- return value.substring(0, maxLabelSize - 2) + "...";
1142
- } else {
1143
- return value;
1144
- }
1145
- };
1146
- };
919
+ defaultExport.prototype.renderBarChart = function renderBarChart (chart) {
920
+ this.renderColumnChart(chart, "bar");
921
+ };
1147
922
 
1148
- var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
1149
-
1150
- var createDataTable = function (chart, options, chartType) {
1151
- var datasets = [];
1152
- var labels = [];
1153
-
1154
- var colors = chart.options.colors || defaultColors;
1155
-
1156
- var day = true;
1157
- var week = true;
1158
- var dayOfWeek;
1159
- var month = true;
1160
- var year = true;
1161
- var hour = true;
1162
- var minute = true;
1163
- var detectType = (chartType === "line" || chartType === "area") && !chart.discrete;
1164
-
1165
- var series = chart.data;
1166
-
1167
- var sortedLabels = [];
1168
-
1169
- var i, j, s, d, key, rows = [];
1170
- for (i = 0; i < series.length; i++) {
1171
- s = series[i];
1172
-
1173
- for (j = 0; j < s.data.length; j++) {
1174
- d = s.data[j];
1175
- key = detectType ? d[0].getTime() : d[0];
1176
- if (!rows[key]) {
1177
- rows[key] = new Array(series.length);
1178
- }
1179
- rows[key][i] = toFloat(d[1]);
1180
- if (sortedLabels.indexOf(key) === -1) {
1181
- sortedLabels.push(key);
1182
- }
1183
- }
1184
- }
923
+ defaultExport.prototype.renderScatterChart = function renderScatterChart (chart, chartType) {
924
+ chartType = chartType || "scatter";
1185
925
 
1186
- if (detectType || chart.options.xtype === "number") {
1187
- sortedLabels.sort(sortByNumber);
1188
- }
926
+ var options = jsOptions(chart, chart.options);
927
+ setFormatOptions(chart, options, chartType);
1189
928
 
1190
- var rows2 = [];
1191
- for (j = 0; j < series.length; j++) {
1192
- rows2.push([]);
1193
- }
929
+ if (!("showLines" in options)) {
930
+ options.showLines = false;
931
+ }
1194
932
 
1195
- var value;
1196
- var k;
1197
- for (k = 0; k < sortedLabels.length; k++) {
1198
- i = sortedLabels[k];
1199
- if (detectType) {
1200
- value = new Date(toFloat(i));
1201
- // TODO make this efficient
1202
- day = day && isDay(value);
1203
- if (!dayOfWeek) {
1204
- dayOfWeek = value.getDay();
1205
- }
1206
- week = week && isWeek(value, dayOfWeek);
1207
- month = month && isMonth(value);
1208
- year = year && isYear(value);
1209
- hour = hour && isHour(value);
1210
- minute = minute && isMinute(value);
1211
- } else {
1212
- value = i;
1213
- }
1214
- labels.push(value);
1215
- for (j = 0; j < series.length; j++) {
1216
- // Chart.js doesn't like undefined
1217
- rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
1218
- }
1219
- }
933
+ var data = createDataTable(chart, options, chartType, this.library);
1220
934
 
1221
- for (i = 0; i < series.length; i++) {
1222
- s = series[i];
935
+ options.scales.xAxes[0].type = "linear";
936
+ options.scales.xAxes[0].position = "bottom";
1223
937
 
1224
- var color = s.color || colors[i];
1225
- var backgroundColor = chartType !== "line" ? addOpacity(color, 0.5) : color;
938
+ this.drawChart(chart, chartType, data, options);
939
+ };
1226
940
 
1227
- var dataset = {
1228
- label: s.name,
1229
- data: rows2[i],
1230
- fill: chartType === "area",
1231
- borderColor: color,
1232
- backgroundColor: backgroundColor,
1233
- pointBackgroundColor: color,
1234
- borderWidth: 2
1235
- };
941
+ defaultExport.prototype.renderBubbleChart = function renderBubbleChart (chart) {
942
+ this.renderScatterChart(chart, "bubble");
943
+ };
1236
944
 
1237
- if (chart.options.curve === false) {
1238
- dataset.lineTension = 0;
1239
- }
945
+ defaultExport.prototype.destroy = function destroy (chart) {
946
+ if (chart.chart) {
947
+ chart.chart.destroy();
948
+ }
949
+ };
1240
950
 
1241
- if (chart.options.points === false) {
1242
- dataset.pointRadius = 0;
1243
- dataset.pointHitRadius = 5;
1244
- }
951
+ defaultExport.prototype.drawChart = function drawChart (chart, type, data, options) {
952
+ this.destroy(chart);
1245
953
 
1246
- datasets.push(merge(dataset, s.library || {}));
1247
- }
954
+ var chartOptions = {
955
+ type: type,
956
+ data: data,
957
+ options: options
958
+ };
1248
959
 
1249
- if (detectType && labels.length > 0) {
1250
- var minTime = labels[0].getTime();
1251
- var maxTime = labels[0].getTime();
1252
- for (i = 1; i < labels.length; i++) {
1253
- value = labels[i].getTime();
1254
- if (value < minTime) {
1255
- minTime = value;
1256
- }
1257
- if (value > maxTime) {
1258
- maxTime = value;
1259
- }
1260
- }
960
+ if (chart.options.code) {
961
+ window.console.log("new Chart(ctx, " + JSON.stringify(chartOptions) + ");");
962
+ }
1261
963
 
1262
- var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
1263
-
1264
- if (!options.scales.xAxes[0].time.unit) {
1265
- var step;
1266
- if (year || timeDiff > 365 * 10) {
1267
- options.scales.xAxes[0].time.unit = "year";
1268
- step = 365;
1269
- } else if (month || timeDiff > 30 * 10) {
1270
- options.scales.xAxes[0].time.unit = "month";
1271
- step = 30;
1272
- } else if (day || timeDiff > 10) {
1273
- options.scales.xAxes[0].time.unit = "day";
1274
- step = 1;
1275
- } else if (hour || timeDiff > 0.5) {
1276
- options.scales.xAxes[0].time.displayFormats = {hour: "MMM D, h a"};
1277
- options.scales.xAxes[0].time.unit = "hour";
1278
- step = 1 / 24.0;
1279
- } else if (minute) {
1280
- options.scales.xAxes[0].time.displayFormats = {minute: "h:mm a"};
1281
- options.scales.xAxes[0].time.unit = "minute";
1282
- step = 1 / 24.0 / 60.0;
1283
- }
1284
-
1285
- if (step && timeDiff > 0) {
1286
- var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
1287
- if (week && step === 1) {
1288
- unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
1289
- }
1290
- options.scales.xAxes[0].time.unitStepSize = unitStepSize;
1291
- }
1292
- }
964
+ chart.element.innerHTML = "<canvas></canvas>";
965
+ var ctx = chart.element.getElementsByTagName("CANVAS")[0];
966
+ chart.chart = new this.library(ctx, chartOptions);
967
+ };
1293
968
 
1294
- if (!options.scales.xAxes[0].time.tooltipFormat) {
1295
- if (day) {
1296
- options.scales.xAxes[0].time.tooltipFormat = "ll";
1297
- } else if (hour) {
1298
- options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
1299
- } else if (minute) {
1300
- options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
1301
- }
1302
- }
1303
- }
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
+ };
1304
1013
 
1305
- var data = {
1306
- labels: labels,
1307
- datasets: datasets
1308
- };
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
+ };
1309
1030
 
1310
- return data;
1311
- };
1031
+ var setTitle$1 = function (options, title) {
1032
+ options.title.text = title;
1033
+ };
1312
1034
 
1313
- this.renderLineChart = function (chart, chartType) {
1314
- if (chart.options.xtype === "number") {
1315
- return self.renderScatterChart(chart, chartType, true);
1316
- }
1035
+ var setMin$1 = function (options, min) {
1036
+ options.yAxis.min = min;
1037
+ };
1317
1038
 
1318
- var chartOptions = {};
1319
- if (chartType === "area") {
1320
- // TODO fix area stacked
1321
- // chartOptions.stacked = true;
1322
- }
1323
- // fix for https://github.com/chartjs/Chart.js/issues/2441
1324
- if (!chart.options.max && allZeros(chart.data)) {
1325
- chartOptions.max = 1;
1326
- }
1039
+ var setMax$1 = function (options, max) {
1040
+ options.yAxis.max = max;
1041
+ };
1327
1042
 
1328
- var options = jsOptions(chart, merge(chartOptions, chart.options));
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
+ };
1329
1049
 
1330
- var data = createDataTable(chart, options, chartType || "line");
1050
+ var setXtitle$1 = function (options, title) {
1051
+ options.xAxis.title.text = title;
1052
+ };
1331
1053
 
1332
- options.scales.xAxes[0].type = chart.discrete ? "category" : "time";
1054
+ var setYtitle$1 = function (options, title) {
1055
+ options.yAxis.title.text = title;
1056
+ };
1333
1057
 
1334
- drawChart(chart, "line", data, options);
1335
- };
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
+ };
1336
1070
 
1337
- this.renderPieChart = function (chart) {
1338
- var options = merge({}, baseOptions);
1339
- if (chart.options.donut) {
1340
- options.cutoutPercentage = 50;
1341
- }
1071
+ if (chartType !== "pie" && !options.yAxis.labels.formatter) {
1072
+ options.yAxis.labels.formatter = function () {
1073
+ return formatValue("", this.value, formatOptions);
1074
+ };
1075
+ }
1342
1076
 
1343
- if ("legend" in chart.options) {
1344
- hideLegend(options, chart.options.legend);
1345
- }
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
+ };
1346
1083
 
1347
- if (chart.options.title) {
1348
- setTitle(options, chart.options.title);
1349
- }
1084
+ var defaultExport$1 = function defaultExport(library) {
1085
+ this.name = "highcharts";
1086
+ this.library = library;
1087
+ };
1350
1088
 
1351
- options = merge(options, chart.options.library || {});
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
+ };
1352
1224
 
1353
- var labels = [];
1354
- var values = [];
1355
- for (var i = 0; i < chart.data.length; i++) {
1356
- var point = chart.data[i];
1357
- labels.push(point[0]);
1358
- values.push(point[1]);
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"
1359
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);
1360
1444
 
1361
- var data = {
1362
- labels: labels,
1363
- datasets: [
1364
- {
1365
- data: values,
1366
- backgroundColor: chart.options.colors || defaultColors
1367
- }
1368
- ]
1369
- };
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";
1370
1802
 
1371
- drawChart(chart, "pie", data, options);
1372
- };
1803
+ chart.__downloadAttached = true;
1373
1804
 
1374
- this.renderColumnChart = function (chart, chartType) {
1375
- var options;
1376
- if (chartType === "bar") {
1377
- options = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options);
1378
- } else {
1379
- options = jsOptions(chart, chart.options);
1380
- }
1381
- var data = createDataTable(chart, options, "column");
1382
- setLabelSize(chart, data, options);
1383
- drawChart(chart, (chartType === "bar" ? "horizontalBar" : "bar"), data, options);
1384
- };
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
+ });
1385
1814
 
1386
- var self = this;
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
+ }
1387
1825
 
1388
- this.renderAreaChart = function (chart) {
1389
- self.renderLineChart(chart, "area");
1390
- };
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
+ }
1391
1840
 
1392
- this.renderBarChart = function (chart) {
1393
- self.renderColumnChart(chart, "bar");
1394
- };
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
+ }
1395
1848
 
1396
- this.renderScatterChart = function (chart, chartType, lineChart) {
1397
- chartType = chartType || "line";
1398
-
1399
- var options = jsOptions(chart, chart.options);
1400
-
1401
- var colors = chart.options.colors || defaultColors;
1402
-
1403
- var datasets = [];
1404
- var series = chart.data;
1405
- for (var i = 0; i < series.length; i++) {
1406
- var s = series[i];
1407
- var d = [];
1408
- for (var j = 0; j < s.data.length; j++) {
1409
- var point = {
1410
- x: toFloat(s.data[j][0]),
1411
- y: toFloat(s.data[j][1])
1412
- };
1413
- if (chartType === "bubble") {
1414
- point.r = toFloat(s.data[j][2]);
1415
- }
1416
- d.push(point);
1417
- }
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
+ }
1418
1855
 
1419
- var color = s.color || colors[i];
1420
- var backgroundColor = chartType === "area" ? addOpacity(color, 0.5) : color;
1421
-
1422
- datasets.push({
1423
- label: s.name,
1424
- showLine: lineChart || false,
1425
- data: d,
1426
- borderColor: color,
1427
- backgroundColor: backgroundColor,
1428
- pointBackgroundColor: color,
1429
- fill: chartType === "area"
1430
- })
1431
- }
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
+ }
1432
1868
 
1433
- if (chartType === "area") {
1434
- chartType = "line";
1435
- }
1869
+ function addAdapter(library) {
1870
+ var adapterType = getAdapterType(library);
1871
+ var adapter = new adapterType(library);
1436
1872
 
1437
- var data = {datasets: datasets};
1873
+ if (adapters.indexOf(adapter) === -1) {
1874
+ adapters.push(adapter);
1875
+ }
1876
+ }
1438
1877
 
1439
- options.scales.xAxes[0].type = "linear";
1440
- options.scales.xAxes[0].position = "bottom";
1878
+ function loadAdapters() {
1879
+ if ("Chart" in window) {
1880
+ addAdapter(window.Chart);
1881
+ }
1441
1882
 
1442
- drawChart(chart, chartType, data, options);
1443
- };
1883
+ if ("Highcharts" in window) {
1884
+ addAdapter(window.Highcharts);
1885
+ }
1444
1886
 
1445
- this.renderBubbleChart = function (chart) {
1446
- this.renderScatterChart(chart, "bubble");
1447
- };
1448
- };
1887
+ if (window.google && window.google.charts) {
1888
+ addAdapter(window.google);
1889
+ }
1890
+ }
1449
1891
 
1450
- adapters.unshift(ChartjsAdapter);
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;
1451
1902
  }
1452
1903
  }
1453
1904
 
1454
1905
  function renderChart(chartType, chart) {
1455
- callAdapter(chartType, chart);
1456
- if (chart.options.download && !chart.downloadAttached && chart.adapter === "chartjs") {
1457
- addDownloadButton(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
+ }
1458
1913
  }
1459
1914
  }
1460
1915
 
@@ -1471,10 +1926,16 @@
1471
1926
  adapter = adapters[i];
1472
1927
  if ((!adapterName || adapterName === adapter.name) && isFunction(adapter[fnName])) {
1473
1928
  chart.adapter = adapter.name;
1929
+ chart.__adapterObject = adapter;
1474
1930
  return adapter[fnName](chart);
1475
1931
  }
1476
1932
  }
1477
- throw new Error("No adapter found");
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
+ }
1478
1939
  }
1479
1940
 
1480
1941
  // process data
@@ -1508,40 +1969,22 @@
1508
1969
  return r;
1509
1970
  };
1510
1971
 
1511
- function isMinute(d) {
1512
- return d.getMilliseconds() === 0 && d.getSeconds() === 0;
1513
- }
1514
-
1515
- function isHour(d) {
1516
- return isMinute(d) && d.getMinutes() === 0;
1517
- }
1518
-
1519
- function isDay(d) {
1520
- return isHour(d) && d.getHours() === 0;
1521
- }
1522
-
1523
- function isWeek(d, dayOfWeek) {
1524
- return isDay(d) && d.getDay() === dayOfWeek;
1525
- }
1526
-
1527
- function isMonth(d) {
1528
- return isDay(d) && d.getDate() === 1;
1529
- }
1530
-
1531
- function isYear(d) {
1532
- return isMonth(d) && d.getMonth() === 0;
1533
- }
1534
-
1535
- function isDate(obj) {
1536
- return !isNaN(toDate(obj)) && toStr(obj).length >= 6;
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
+ }
1537
1980
  }
1538
1981
 
1539
- function allZeros(data) {
1540
- var i, j, d;
1541
- for (i = 0; i < data.length; i++) {
1542
- d = data[i].data;
1543
- for (j = 0; j < d.length; j++) {
1544
- if (d[j][1] != 0) {
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])) {
1545
1988
  return false;
1546
1989
  }
1547
1990
  }
@@ -1549,20 +1992,23 @@
1549
1992
  return true;
1550
1993
  }
1551
1994
 
1552
- function detectDiscrete(series) {
1553
- var i, j, data;
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;
1554
1999
  for (i = 0; i < series.length; i++) {
1555
- data = toArr(series[i].data);
1556
- for (j = 0; j < data.length; j++) {
1557
- if (!isDate(data[j][0])) {
1558
- return true;
2000
+ var copy = {};
2001
+ for (j in series[i]) {
2002
+ if (series[i].hasOwnProperty(j)) {
2003
+ copy[j] = series[i][j];
1559
2004
  }
1560
2005
  }
2006
+ newSeries.push(copy);
1561
2007
  }
1562
- return false;
2008
+ return newSeries;
1563
2009
  }
1564
2010
 
1565
- function processSeries(chart, keyType) {
2011
+ function processSeries(chart, keyType, noDatetime) {
1566
2012
  var i;
1567
2013
 
1568
2014
  var opts = chart.options;
@@ -1570,26 +2016,18 @@
1570
2016
 
1571
2017
  // see if one series or multiple
1572
2018
  if (!isArray(series) || typeof series[0] !== "object" || isArray(series[0])) {
1573
- series = [{name: opts.label || "Value", data: series}];
2019
+ series = [{name: opts.label, data: series}];
1574
2020
  chart.hideLegend = true;
1575
2021
  } else {
1576
2022
  chart.hideLegend = false;
1577
2023
  }
1578
- if ((opts.discrete === null || opts.discrete === undefined) && keyType !== "bubble" && keyType !== "number") {
1579
- chart.discrete = detectDiscrete(series);
1580
- } else {
1581
- chart.discrete = opts.discrete;
1582
- }
1583
- if (chart.discrete) {
1584
- keyType = "string";
1585
- }
1586
- if (chart.options.xtype) {
1587
- keyType = chart.options.xtype;
1588
- }
2024
+
2025
+ chart.xtype = keyType ? keyType : (opts.discrete ? "string" : detectXType(series, noDatetime));
1589
2026
 
1590
2027
  // right format
2028
+ series = copySeries(series);
1591
2029
  for (i = 0; i < series.length; i++) {
1592
- series[i].data = formatSeriesData(toArr(series[i].data), keyType);
2030
+ series[i].data = formatSeriesData(toArr(series[i].data), chart.xtype);
1593
2031
  }
1594
2032
 
1595
2033
  return series;
@@ -1603,163 +2041,360 @@
1603
2041
  return perfectData;
1604
2042
  }
1605
2043
 
1606
- function processTime(chart)
1607
- {
1608
- var i, data = chart.rawData;
1609
- for (i = 0; i < data.length; i++) {
1610
- data[i][1] = toDate(data[i][1]);
1611
- data[i][2] = toDate(data[i][2]);
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
+ }
1612
2054
  }
1613
- return data;
1614
- }
2055
+ this.element = element;
2056
+ this.options = merge(Chartkick.options, options || {});
2057
+ this.dataSource = dataSource;
1615
2058
 
1616
- function processLineData(chart) {
1617
- return processSeries(chart, "datetime");
1618
- }
2059
+ Chartkick.charts[element.id] = this;
1619
2060
 
1620
- function processColumnData(chart) {
1621
- return processSeries(chart, "string");
1622
- }
2061
+ fetchDataSource(this, dataSource);
1623
2062
 
1624
- function processBarData(chart) {
1625
- return processSeries(chart, "string");
1626
- }
2063
+ if (this.options.refresh) {
2064
+ this.startRefresh();
2065
+ }
2066
+ };
1627
2067
 
1628
- function processAreaData(chart) {
1629
- return processSeries(chart, "datetime");
1630
- }
2068
+ Chart.prototype.getElement = function getElement () {
2069
+ return this.element;
2070
+ };
1631
2071
 
1632
- function processScatterData(chart) {
1633
- return processSeries(chart, "number");
1634
- }
2072
+ Chart.prototype.getDataSource = function getDataSource () {
2073
+ return this.dataSource;
2074
+ };
1635
2075
 
1636
- function processBubbleData(chart) {
1637
- return processSeries(chart, "bubble");
1638
- }
2076
+ Chart.prototype.getData = function getData () {
2077
+ return this.data;
2078
+ };
1639
2079
 
1640
- function createChart(chartType, chart, element, dataSource, opts, processData) {
1641
- var elementId;
1642
- if (typeof element === "string") {
1643
- elementId = element;
1644
- element = document.getElementById(element);
1645
- if (!element) {
1646
- throw new Error("No element with id " + elementId);
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");
1647
2136
  }
1648
2137
  }
2138
+ };
1649
2139
 
1650
- chart.element = element;
1651
- opts = merge(Chartkick.options, opts || {});
1652
- chart.options = opts;
1653
- chart.dataSource = dataSource;
2140
+ Chart.prototype.stopRefresh = function stopRefresh () {
2141
+ if (this.intervalId) {
2142
+ clearInterval(this.intervalId);
2143
+ this.intervalId = null;
2144
+ }
2145
+ };
1654
2146
 
1655
- if (!processData) {
1656
- processData = function (chart) {
1657
- return chart.rawData;
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();
1658
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);
1659
2226
  }
1660
2227
 
1661
- // getters
1662
- chart.getElement = function () {
1663
- return element;
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);
1664
2234
  };
1665
- chart.getDataSource = function () {
1666
- return chart.dataSource;
2235
+
2236
+ PieChart.prototype.__chartName = function __chartName () {
2237
+ return "PieChart";
1667
2238
  };
1668
- chart.getData = function () {
1669
- return chart.data;
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);
1670
2254
  };
1671
- chart.getOptions = function () {
1672
- return chart.options;
2255
+
2256
+ ColumnChart.prototype.__chartName = function __chartName () {
2257
+ return "ColumnChart";
1673
2258
  };
1674
- chart.getChartObject = function () {
1675
- return chart.chart;
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);
1676
2274
  };
1677
- chart.getAdapter = function () {
1678
- return chart.adapter;
2275
+
2276
+ BarChart.prototype.__chartName = function __chartName () {
2277
+ return "BarChart";
1679
2278
  };
1680
2279
 
1681
- var callback = function () {
1682
- chart.data = processData(chart);
1683
- renderChart(chartType, chart);
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);
1684
2294
  };
1685
2295
 
1686
- // functions
1687
- chart.updateData = function (dataSource, options) {
1688
- chart.dataSource = dataSource;
1689
- if (options) {
1690
- chart.options = merge(Chartkick.options, options);
1691
- }
1692
- fetchDataSource(chart, callback, dataSource);
2296
+ AreaChart.prototype.__chartName = function __chartName () {
2297
+ return "AreaChart";
1693
2298
  };
1694
- chart.setOptions = function (options) {
1695
- chart.options = merge(Chartkick.options, options);
1696
- chart.redraw();
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);
1697
2314
  };
1698
- chart.redraw = function() {
1699
- fetchDataSource(chart, callback, chart.rawData);
2315
+
2316
+ GeoChart.prototype.__chartName = function __chartName () {
2317
+ return "GeoChart";
1700
2318
  };
1701
- chart.refreshData = function () {
1702
- if (typeof dataSource === "string") {
1703
- // prevent browser from caching
1704
- var sep = dataSource.indexOf("?") === -1 ? "?" : "&";
1705
- var url = dataSource + sep + "_=" + (new Date()).getTime();
1706
- fetchDataSource(chart, callback, url);
1707
- }
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");
1708
2334
  };
1709
- chart.stopRefresh = function () {
1710
- if (chart.intervalId) {
1711
- clearInterval(chart.intervalId);
1712
- }
2335
+
2336
+ ScatterChart.prototype.__chartName = function __chartName () {
2337
+ return "ScatterChart";
1713
2338
  };
1714
- chart.toImage = function () {
1715
- if (chart.adapter === "chartjs") {
1716
- return chart.chart.toBase64Image();
1717
- } else {
1718
- return null;
1719
- }
2339
+
2340
+ return ScatterChart;
2341
+ }(Chart));
2342
+
2343
+ var BubbleChart = /*@__PURE__*/(function (Chart) {
2344
+ function BubbleChart () {
2345
+ Chart.apply(this, arguments);
1720
2346
  }
1721
2347
 
1722
- Chartkick.charts[element.id] = chart;
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
+ };
1723
2359
 
1724
- fetchDataSource(chart, callback, dataSource);
2360
+ return BubbleChart;
2361
+ }(Chart));
1725
2362
 
1726
- if (opts.refresh) {
1727
- chart.intervalId = setInterval( function () {
1728
- chart.refreshData();
1729
- }, opts.refresh * 1000);
2363
+ var Timeline = /*@__PURE__*/(function (Chart) {
2364
+ function Timeline () {
2365
+ Chart.apply(this, arguments);
1730
2366
  }
1731
- }
1732
2367
 
1733
- // define classes
2368
+ if ( Chart ) Timeline.__proto__ = Chart;
2369
+ Timeline.prototype = Object.create( Chart && Chart.prototype );
2370
+ Timeline.prototype.constructor = Timeline;
1734
2371
 
1735
- Chartkick = {
1736
- LineChart: function (element, dataSource, options) {
1737
- createChart("LineChart", this, element, dataSource, options, processLineData);
1738
- },
1739
- PieChart: function (element, dataSource, options) {
1740
- createChart("PieChart", this, element, dataSource, options, processSimple);
1741
- },
1742
- ColumnChart: function (element, dataSource, options) {
1743
- createChart("ColumnChart", this, element, dataSource, options, processColumnData);
1744
- },
1745
- BarChart: function (element, dataSource, options) {
1746
- createChart("BarChart", this, element, dataSource, options, processBarData);
1747
- },
1748
- AreaChart: function (element, dataSource, options) {
1749
- createChart("AreaChart", this, element, dataSource, options, processAreaData);
1750
- },
1751
- GeoChart: function (element, dataSource, options) {
1752
- createChart("GeoChart", this, element, dataSource, options, processSimple);
1753
- },
1754
- ScatterChart: function (element, dataSource, options) {
1755
- createChart("ScatterChart", this, element, dataSource, options, processScatterData);
1756
- },
1757
- BubbleChart: function (element, dataSource, options) {
1758
- createChart("BubbleChart", this, element, dataSource, options, processBubbleData);
1759
- },
1760
- Timeline: function (element, dataSource, options) {
1761
- createChart("Timeline", this, element, dataSource, options, processTime);
1762
- },
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,
1763
2398
  charts: {},
1764
2399
  configure: function (options) {
1765
2400
  for (var key in options) {
@@ -1768,6 +2403,9 @@
1768
2403
  }
1769
2404
  }
1770
2405
  },
2406
+ setDefaultOptions: function (opts) {
2407
+ Chartkick.options = opts;
2408
+ },
1771
2409
  eachChart: function (callback) {
1772
2410
  for (var chartId in Chartkick.charts) {
1773
2411
  if (Chartkick.charts.hasOwnProperty(chartId)) {
@@ -1775,14 +2413,24 @@
1775
2413
  }
1776
2414
  }
1777
2415
  },
2416
+ config: config,
1778
2417
  options: {},
1779
2418
  adapters: adapters,
1780
- createChart: createChart
2419
+ addAdapter: addAdapter,
2420
+ use: function(adapter) {
2421
+ addAdapter(adapter);
2422
+ return Chartkick;
2423
+ }
1781
2424
  };
1782
2425
 
1783
- if (typeof module === "object" && typeof module.exports === "object") {
1784
- module.exports = Chartkick;
1785
- } else {
2426
+ // not ideal, but allows for simpler integration
2427
+ if (typeof window !== "undefined" && !window.Chartkick) {
1786
2428
  window.Chartkick = Chartkick;
1787
2429
  }
1788
- }(window));
2430
+
2431
+ // backwards compatibility for esm require
2432
+ Chartkick.default = Chartkick;
2433
+
2434
+ return Chartkick;
2435
+
2436
+ })));