app/assets/javascripts/pghero/chartkick.js in pghero-2.3.0 vs app/assets/javascripts/pghero/chartkick.js in pghero-2.4.0
- old
+ new
@@ -1,42 +1,39 @@
/*
* Chartkick.js
* Create beautiful charts with one line of JavaScript
* https://github.com/ankane/chartkick.js
- * v2.2.2
+ * v3.2.0
* MIT License
*/
-/*jslint browser: true, indent: 2, plusplus: true, vars: true */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = global || self, global.Chartkick = factory());
+}(this, (function () { 'use strict';
-(function (window) {
- 'use strict';
-
- var config = window.Chartkick || {};
- var Chartkick, ISO8601_PATTERN, DECIMAL_SEPARATOR, adapters = [];
- var DATE_PATTERN = /^(\d\d\d\d)(\-)?(\d\d)(\-)?(\d\d)$/i;
- var GoogleChartsAdapter, HighchartsAdapter, ChartjsAdapter;
- var pendingRequests = [], runningRequests = 0, maxRequests = 4;
-
- // helpers
-
function isArray(variable) {
return Object.prototype.toString.call(variable) === "[object Array]";
}
function isFunction(variable) {
return variable instanceof Function;
}
function isPlainObject(variable) {
- return !isFunction(variable) && variable instanceof Object;
+ // protect against prototype pollution, defense 2
+ return Object.prototype.toString.call(variable) === "[object Object]" && !isFunction(variable) && variable instanceof Object;
}
// https://github.com/madrobby/zepto/blob/master/src/zepto.js
function extend(target, source) {
var key;
for (key in source) {
+ // protect against prototype pollution, defense 1
+ if (key === "__proto__") { continue; }
+
if (isPlainObject(source[key]) || isArray(source[key])) {
if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
target[key] = {};
}
if (isArray(source[key]) && !isArray(target[key])) {
@@ -54,13 +51,15 @@
extend(target, obj1);
extend(target, obj2);
return target;
}
+ var DATE_PATTERN = /^(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)$/i;
+
// https://github.com/Do/iso8601.js
- ISO8601_PATTERN = /(\d\d\d\d)(\-)?(\d\d)(\-)?(\d\d)(T)?(\d\d)(:)?(\d\d)?(:)?(\d\d)?([\.,]\d+)?($|Z|([\+\-])(\d\d)(:)?(\d\d)?)/i;
- DECIMAL_SEPARATOR = String(1.5).charAt(1);
+ 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;
+ var DECIMAL_SEPARATOR = String(1.5).charAt(1);
function parseISO8601(input) {
var day, hour, matches, milliseconds, minutes, month, offset, result, seconds, type, year;
type = Object.prototype.toString.call(input);
if (type === "[object Date]") {
@@ -103,10 +102,54 @@
}
}
return false;
}
+ function toStr(n) {
+ return "" + n;
+ }
+
+ function toFloat(n) {
+ return parseFloat(n);
+ }
+
+ function toDate(n) {
+ var matches, year, month, day;
+ if (typeof n !== "object") {
+ if (typeof n === "number") {
+ n = new Date(n * 1000); // ms
+ } else {
+ n = toStr(n);
+ if ((matches = n.match(DATE_PATTERN))) {
+ year = parseInt(matches[1], 10);
+ month = parseInt(matches[3], 10) - 1;
+ day = parseInt(matches[5], 10);
+ return new Date(year, month, day);
+ } else { // str
+ // try our best to get the str into iso8601
+ // TODO be smarter about this
+ var str = n.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
+ n = parseISO8601(str) || new Date(n);
+ }
+ }
+ }
+ return n;
+ }
+
+ function toArr(n) {
+ if (!isArray(n)) {
+ var arr = [], i;
+ for (i in n) {
+ if (n.hasOwnProperty(i)) {
+ arr.push([i, n[i]]);
+ }
+ }
+ n = arr;
+ }
+ return n;
+ }
+
function jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle) {
return function (chart, opts, chartOptions) {
var series = chart.data;
var options = merge({}, defaultOptions);
options = merge(options, chartOptions || {});
@@ -152,1311 +195,1723 @@
return options;
};
}
- function setText(element, text) {
- if (document.body.innerText) {
- element.innerText = text;
- } else {
- element.textContent = text;
- }
+ function sortByTime(a, b) {
+ return a[0].getTime() - b[0].getTime();
}
- function chartError(element, message) {
- setText(element, "Error Loading Chart: " + message);
- element.style.color = "#ff0000";
+ function sortByNumberSeries(a, b) {
+ return a[0] - b[0];
}
- function pushRequest(element, url, success) {
- pendingRequests.push([element, url, success]);
- runNext();
+ function sortByNumber(a, b) {
+ return a - b;
}
- function runNext() {
- if (runningRequests < maxRequests) {
- var request = pendingRequests.shift()
- if (request) {
- runningRequests++;
- getJSON(request[0], request[1], request[2]);
- runNext();
- }
- }
+ function isMinute(d) {
+ return d.getMilliseconds() === 0 && d.getSeconds() === 0;
}
- function requestComplete() {
- runningRequests--;
- runNext();
+ function isHour(d) {
+ return isMinute(d) && d.getMinutes() === 0;
}
- function getJSON(element, url, success) {
- ajaxCall(url, success, function (jqXHR, textStatus, errorThrown) {
- var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
- chartError(element, message);
- });
+ function isDay(d) {
+ return isHour(d) && d.getHours() === 0;
}
- function ajaxCall(url, success, error) {
- var $ = window.jQuery || window.Zepto || window.$;
+ function isWeek(d, dayOfWeek) {
+ return isDay(d) && d.getDay() === dayOfWeek;
+ }
- if ($) {
- $.ajax({
- dataType: "json",
- url: url,
- success: success,
- error: error,
- complete: requestComplete
- });
- } else {
- var xhr = new XMLHttpRequest();
- xhr.open("GET", url, true);
- xhr.setRequestHeader("Content-Type", "application/json");
- xhr.onload = function () {
- requestComplete();
- if (xhr.status === 200) {
- success(JSON.parse(xhr.responseText), xhr.statusText, xhr);
- } else {
- error(xhr, "error", xhr.statusText);
- }
- };
- xhr.send();
- }
+ function isMonth(d) {
+ return isDay(d) && d.getDate() === 1;
}
- function errorCatcher(chart, callback) {
- try {
- callback(chart);
- } catch (err) {
- chartError(chart.element, err.message);
- throw err;
- }
+ function isYear(d) {
+ return isMonth(d) && d.getMonth() === 0;
}
- function fetchDataSource(chart, callback, dataSource) {
- if (typeof dataSource === "string") {
- pushRequest(chart.element, dataSource, function (data, textStatus, jqXHR) {
- chart.rawData = data;
- errorCatcher(chart, callback);
- });
- } else {
- chart.rawData = dataSource;
- errorCatcher(chart, callback);
- }
+ function isDate(obj) {
+ return !isNaN(toDate(obj)) && toStr(obj).length >= 6;
}
- function addDownloadButton(chart) {
- var element = chart.element;
- var link = document.createElement("a");
- link.download = chart.options.download === true ? "chart.png" : chart.options.download; // http://caniuse.com/download
- link.style.position = "absolute";
- link.style.top = "20px";
- link.style.right = "20px";
- link.style.zIndex = 1000;
- link.style.lineHeight = "20px";
- link.target = "_blank"; // for safari
- var image = document.createElement("img");
- image.alt = "Download";
- image.style.border = "none";
- // icon from font-awesome
- // http://fa2png.io/
- image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAABCFBMVEUAAADMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMywEsqxAAAAV3RSTlMAAQIDBggJCgsMDQ4PERQaHB0eISIjJCouLzE0OTo/QUJHSUpLTU5PUllhYmltcHh5foWLjI+SlaCio6atr7S1t7m6vsHHyM7R2tze5Obo7fHz9ff5+/1hlxK2AAAA30lEQVQYGUXBhVYCQQBA0TdYWAt2d3d3YWAHyur7/z9xgD16Lw0DW+XKx+1GgX+FRzM3HWQWrHl5N/oapW5RPe0PkBu+UYeICvozTWZVK23Ao04B79oJrOsJDOoxkZoQPWgX29pHpCZEk7rEvQYiNSFq1UMqvlCjJkRBS1R8hb00Vb/TajtBL7nTHE1X1vyMQF732dQhyF2o6SAwrzP06iUQzvwsArlnzcOdrgBhJyHa1QOgO9U1GsKuvjUTjavliZYQ8nNPapG6sap/3nrIdJ6bOWzmX/fy0XVpfzZP3S8OJT3g9EEiJwAAAABJRU5ErkJggg==";
- link.appendChild(image);
- element.style.position = "relative";
+ function isNumber(obj) {
+ return typeof obj === "number";
+ }
- chart.downloadAttached = true;
+ var byteSuffixes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB"];
- // mouseenter
- addEvent(element, "mouseover", function(e) {
- var related = e.relatedTarget;
- // check download option again to ensure it wasn't changed
- if (!related || (related !== this && !childOf(this, related)) && chart.options.download) {
- link.href = chart.toImage();
- element.appendChild(link);
+ function formatValue(pre, value, options, axis) {
+ pre = pre || "";
+ if (options.prefix) {
+ if (value < 0) {
+ value = value * -1;
+ pre += "-";
}
- });
+ pre += options.prefix;
+ }
- // mouseleave
- addEvent(element, "mouseout", function(e) {
- var related = e.relatedTarget;
- if (!related || (related !== this && !childOf(this, related))) {
- if (link.parentNode) {
- link.parentNode.removeChild(link);
+ var suffix = options.suffix || "";
+ var precision = options.precision;
+ var round = options.round;
+
+ if (options.byteScale) {
+ var suffixIdx;
+ var baseValue = axis ? options.byteScale : value;
+
+ if (baseValue >= 1152921504606846976) {
+ value /= 1152921504606846976;
+ suffixIdx = 6;
+ } else if (baseValue >= 1125899906842624) {
+ value /= 1125899906842624;
+ suffixIdx = 5;
+ } else if (baseValue >= 1099511627776) {
+ value /= 1099511627776;
+ suffixIdx = 4;
+ } else if (baseValue >= 1073741824) {
+ value /= 1073741824;
+ suffixIdx = 3;
+ } else if (baseValue >= 1048576) {
+ value /= 1048576;
+ suffixIdx = 2;
+ } else if (baseValue >= 1024) {
+ value /= 1024;
+ suffixIdx = 1;
+ } else {
+ suffixIdx = 0;
+ }
+
+ // TODO handle manual precision case
+ if (precision === undefined && round === undefined) {
+ if (value >= 1023.5) {
+ if (suffixIdx < byteSuffixes.length - 1) {
+ value = 1.0;
+ suffixIdx += 1;
+ }
}
+ precision = value >= 1000 ? 4 : 3;
}
- });
- }
+ suffix = " " + byteSuffixes[suffixIdx];
+ }
- // http://stackoverflow.com/questions/10149963/adding-event-listener-cross-browser
- function addEvent(elem, event, fn) {
- if (elem.addEventListener) {
- elem.addEventListener(event, fn, false);
- } else {
- elem.attachEvent("on" + event, function() {
- // set the this pointer same as addEventListener when fn is called
- return(fn.call(elem, window.event));
- });
+ if (precision !== undefined && round !== undefined) {
+ throw Error("Use either round or precision, not both");
}
- }
- // https://gist.github.com/shawnbot/4166283
- function childOf(p, c) {
- if (p === c) return false;
- while (c && c !== p) c = c.parentNode;
- return c === p;
- }
+ if (!axis) {
+ if (precision !== undefined) {
+ value = value.toPrecision(precision);
+ if (!options.zeros) {
+ value = parseFloat(value);
+ }
+ }
- // type conversions
+ if (round !== undefined) {
+ if (round < 0) {
+ var num = Math.pow(10, -1 * round);
+ value = parseInt((1.0 * value / num).toFixed(0)) * num;
+ } else {
+ value = value.toFixed(round);
+ if (!options.zeros) {
+ value = parseFloat(value);
+ }
+ }
+ }
+ }
- function toStr(n) {
- return "" + n;
+ if (options.thousands || options.decimal) {
+ value = toStr(value);
+ var parts = value.split(".");
+ value = parts[0];
+ if (options.thousands) {
+ value = value.replace(/\B(?=(\d{3})+(?!\d))/g, options.thousands);
+ }
+ if (parts.length > 1) {
+ value += (options.decimal || ".") + parts[1];
+ }
+ }
+
+ return pre + value + suffix;
}
- function toFloat(n) {
- return parseFloat(n);
+ function seriesOption(chart, series, option) {
+ if (option in series) {
+ return series[option];
+ } else if (option in chart.options) {
+ return chart.options[option];
+ }
+ return null;
}
- function toDate(n) {
- var matches, year, month, day;
- if (typeof n !== "object") {
- if (typeof n === "number") {
- n = new Date(n * 1000); // ms
- } else if ((matches = n.match(DATE_PATTERN))) {
- year = parseInt(matches[1], 10);
- month = parseInt(matches[3], 10) - 1;
- day = parseInt(matches[5], 10);
- return new Date(year, month, day);
- } else { // str
- // try our best to get the str into iso8601
- // TODO be smarter about this
- var str = n.replace(/ /, "T").replace(" ", "").replace("UTC", "Z");
- n = parseISO8601(str) || new Date(n);
+ function allZeros(data) {
+ var i, j, d;
+ for (i = 0; i < data.length; i++) {
+ d = data[i].data;
+ for (j = 0; j < d.length; j++) {
+ if (d[j][1] != 0) {
+ return false;
+ }
}
}
- return n;
+ return true;
}
- function toArr(n) {
- if (!isArray(n)) {
- var arr = [], i;
- for (i in n) {
- if (n.hasOwnProperty(i)) {
- arr.push([i, n[i]]);
+ var baseOptions = {
+ maintainAspectRatio: false,
+ animation: false,
+ tooltips: {
+ displayColors: false,
+ callbacks: {}
+ },
+ legend: {},
+ title: {fontSize: 20, fontColor: "#333"}
+ };
+
+ var defaultOptions = {
+ scales: {
+ yAxes: [
+ {
+ ticks: {
+ maxTicksLimit: 4
+ },
+ scaleLabel: {
+ fontSize: 16,
+ // fontStyle: "bold",
+ fontColor: "#333"
+ }
}
+ ],
+ xAxes: [
+ {
+ gridLines: {
+ drawOnChartArea: false
+ },
+ scaleLabel: {
+ fontSize: 16,
+ // fontStyle: "bold",
+ fontColor: "#333"
+ },
+ time: {},
+ ticks: {}
+ }
+ ]
+ }
+ };
+
+ // http://there4.io/2012/05/02/google-chart-color-list/
+ var defaultColors = [
+ "#3366CC", "#DC3912", "#FF9900", "#109618", "#990099", "#3B3EAC", "#0099C6",
+ "#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11",
+ "#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#651067"
+ ];
+
+ var hideLegend = function (options, legend, hideLegend) {
+ if (legend !== undefined) {
+ options.legend.display = !!legend;
+ if (legend && legend !== true) {
+ options.legend.position = legend;
}
- n = arr;
+ } else if (hideLegend) {
+ options.legend.display = false;
}
- return n;
- }
+ };
- function sortByTime(a, b) {
- return a[0].getTime() - b[0].getTime();
- }
+ var setTitle = function (options, title) {
+ options.title.display = true;
+ options.title.text = title;
+ };
- function sortByNumberSeries(a, b) {
- return a[0] - b[0];
- }
+ var setMin = function (options, min) {
+ if (min !== null) {
+ options.scales.yAxes[0].ticks.min = toFloat(min);
+ }
+ };
- function sortByNumber(a, b) {
- return a - b;
- }
+ var setMax = function (options, max) {
+ options.scales.yAxes[0].ticks.max = toFloat(max);
+ };
- function loadAdapters() {
- if (!HighchartsAdapter && "Highcharts" in window) {
- HighchartsAdapter = new function () {
- var Highcharts = window.Highcharts;
+ var setBarMin = function (options, min) {
+ if (min !== null) {
+ options.scales.xAxes[0].ticks.min = toFloat(min);
+ }
+ };
- this.name = "highcharts";
+ var setBarMax = function (options, max) {
+ options.scales.xAxes[0].ticks.max = toFloat(max);
+ };
- var defaultOptions = {
- chart: {},
- xAxis: {
- title: {
- text: null
- },
- labels: {
- style: {
- fontSize: "12px"
- }
- }
- },
- yAxis: {
- title: {
- text: null
- },
- labels: {
- style: {
- fontSize: "12px"
- }
- }
- },
- title: {
- text: null
- },
- credits: {
- enabled: false
- },
- legend: {
- borderWidth: 0
- },
- tooltip: {
- style: {
- fontSize: "12px"
- }
- },
- plotOptions: {
- areaspline: {},
- series: {
- marker: {}
- }
+ var setStacked = function (options, stacked) {
+ options.scales.xAxes[0].stacked = !!stacked;
+ options.scales.yAxes[0].stacked = !!stacked;
+ };
+
+ var setXtitle = function (options, title) {
+ options.scales.xAxes[0].scaleLabel.display = true;
+ options.scales.xAxes[0].scaleLabel.labelString = title;
+ };
+
+ var setYtitle = function (options, title) {
+ options.scales.yAxes[0].scaleLabel.display = true;
+ options.scales.yAxes[0].scaleLabel.labelString = title;
+ };
+
+ // https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
+ var addOpacity = function(hex, opacity) {
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
+ };
+
+ // check if not null or undefined
+ // https://stackoverflow.com/a/27757708/1177228
+ var notnull = function(x) {
+ return x != null;
+ };
+
+ var setLabelSize = function (chart, data, options) {
+ var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
+ if (maxLabelSize > 25) {
+ maxLabelSize = 25;
+ } else if (maxLabelSize < 10) {
+ maxLabelSize = 10;
+ }
+ if (!options.scales.xAxes[0].ticks.callback) {
+ options.scales.xAxes[0].ticks.callback = function (value) {
+ value = toStr(value);
+ if (value.length > maxLabelSize) {
+ return value.substring(0, maxLabelSize - 2) + "...";
+ } else {
+ return value;
+ }
+ };
+ }
+ };
+
+ var setFormatOptions = function(chart, options, chartType) {
+ var formatOptions = {
+ prefix: chart.options.prefix,
+ suffix: chart.options.suffix,
+ thousands: chart.options.thousands,
+ decimal: chart.options.decimal,
+ precision: chart.options.precision,
+ round: chart.options.round,
+ zeros: chart.options.zeros
+ };
+
+ if (chart.options.bytes) {
+ var series = chart.data;
+ if (chartType === "pie") {
+ series = [{data: series}];
+ }
+
+ // calculate max
+ var max = 0;
+ for (var i = 0; i < series.length; i++) {
+ var s = series[i];
+ for (var j = 0; j < s.data.length; j++) {
+ if (s.data[j][1] > max) {
+ max = s.data[j][1];
}
+ }
+ }
+
+ // calculate scale
+ var scale = 1;
+ while (max >= 1024) {
+ scale *= 1024;
+ max /= 1024;
+ }
+
+ // set step size
+ formatOptions.byteScale = scale;
+ }
+
+ if (chartType !== "pie") {
+ var myAxes = options.scales.yAxes;
+ if (chartType === "bar") {
+ myAxes = options.scales.xAxes;
+ }
+
+ if (formatOptions.byteScale) {
+ if (!myAxes[0].ticks.stepSize) {
+ myAxes[0].ticks.stepSize = formatOptions.byteScale / 2;
+ }
+ if (!myAxes[0].ticks.maxTicksLimit) {
+ myAxes[0].ticks.maxTicksLimit = 4;
+ }
+ }
+
+ if (!myAxes[0].ticks.callback) {
+ myAxes[0].ticks.callback = function (value) {
+ return formatValue("", value, formatOptions, true);
};
+ }
+ }
- var hideLegend = function (options, legend, hideLegend) {
- if (legend !== undefined) {
- options.legend.enabled = !!legend;
- if (legend && legend !== true) {
- if (legend === "top" || legend === "bottom") {
- options.legend.verticalAlign = legend;
- } else {
- options.legend.layout = "vertical";
- options.legend.verticalAlign = "middle";
- options.legend.align = legend;
- }
- }
- } else if (hideLegend) {
- options.legend.enabled = false;
+ if (!options.tooltips.callbacks.label) {
+ if (chartType === "scatter") {
+ options.tooltips.callbacks.label = function (item, data) {
+ var label = data.datasets[item.datasetIndex].label || '';
+ if (label) {
+ label += ': ';
}
+ return label + '(' + item.xLabel + ', ' + item.yLabel + ')';
};
-
- var setTitle = function (options, title) {
- options.title.text = title;
+ } else if (chartType === "bubble") {
+ options.tooltips.callbacks.label = function (item, data) {
+ var label = data.datasets[item.datasetIndex].label || '';
+ if (label) {
+ label += ': ';
+ }
+ var dataPoint = data.datasets[item.datasetIndex].data[item.index];
+ return label + '(' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.v + ')';
};
+ } else if (chartType === "pie") {
+ // need to use separate label for pie charts
+ options.tooltips.callbacks.label = function (tooltipItem, data) {
+ var dataLabel = data.labels[tooltipItem.index];
+ var value = ': ';
- var setMin = function (options, min) {
- options.yAxis.min = min;
- };
+ if (isArray(dataLabel)) {
+ // show value on first line of multiline label
+ // need to clone because we are changing the value
+ dataLabel = dataLabel.slice();
+ dataLabel[0] += value;
+ } else {
+ dataLabel += value;
+ }
- var setMax = function (options, max) {
- options.yAxis.max = max;
+ return formatValue(dataLabel, data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index], formatOptions);
};
-
- var setStacked = function (options, stacked) {
- options.plotOptions.series.stacking = stacked ? "normal" : null;
+ } else {
+ var valueLabel = chartType === "bar" ? "xLabel" : "yLabel";
+ options.tooltips.callbacks.label = function (tooltipItem, data) {
+ var label = data.datasets[tooltipItem.datasetIndex].label || '';
+ if (label) {
+ label += ': ';
+ }
+ return formatValue(label, tooltipItem[valueLabel], formatOptions);
};
+ }
+ }
+ };
- var setXtitle = function (options, title) {
- options.xAxis.title.text = title;
- };
+ var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
- var setYtitle = function (options, title) {
- options.yAxis.title.text = title;
- };
+ var createDataTable = function (chart, options, chartType, library) {
+ var datasets = [];
+ var labels = [];
- var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
+ var colors = chart.options.colors || defaultColors;
- this.renderLineChart = function (chart, chartType) {
- chartType = chartType || "spline";
- var chartOptions = {};
- if (chartType === "areaspline") {
- chartOptions = {
- plotOptions: {
- areaspline: {
- stacking: "normal"
- },
- area: {
- stacking: "normal"
- },
- series: {
- marker: {
- enabled: false
- }
- }
- }
- };
- }
+ var day = true;
+ var week = true;
+ var dayOfWeek;
+ var month = true;
+ var year = true;
+ var hour = true;
+ var minute = true;
- if (chart.options.curve === false) {
- if (chartType === "areaspline") {
- chartType = "area";
- } else if (chartType === "spline") {
- chartType = "line";
- }
- }
+ var series = chart.data;
- var options = jsOptions(chart, chart.options, chartOptions), data, i, j;
- options.xAxis.type = chart.discrete ? "category" : "datetime";
- if (!options.chart.type) {
- options.chart.type = chartType;
+ var max = 0;
+ if (chartType === "bubble") {
+ for (var i$1 = 0; i$1 < series.length; i$1++) {
+ var s$1 = series[i$1];
+ for (var j$1 = 0; j$1 < s$1.data.length; j$1++) {
+ if (s$1.data[j$1][2] > max) {
+ max = s$1.data[j$1][2];
}
- options.chart.renderTo = chart.element.id;
+ }
+ }
+ }
- var series = chart.data;
- for (i = 0; i < series.length; i++) {
- data = series[i].data;
- if (!chart.discrete) {
- for (j = 0; j < data.length; j++) {
- data[j][0] = data[j][0].getTime();
- }
- }
- series[i].marker = {symbol: "circle"};
- if (chart.options.points === false) {
- series[i].marker.enabled = false;
- }
- }
- options.series = series;
- chart.chart = new Highcharts.Chart(options);
- };
+ var i, j, s, d, key, rows = [], rows2 = [];
- this.renderScatterChart = function (chart) {
- var chartOptions = {};
- var options = jsOptions(chart, chart.options, chartOptions);
- options.chart.type = "scatter";
- options.chart.renderTo = chart.element.id;
- options.series = chart.data;
- chart.chart = new Highcharts.Chart(options);
- };
+ if (chartType === "bar" || chartType === "column" || (chart.xtype !== "number" && chart.xtype !== "bubble")) {
+ var sortedLabels = [];
- this.renderPieChart = function (chart) {
- var chartOptions = merge(defaultOptions, {});
+ for (i = 0; i < series.length; i++) {
+ s = series[i];
- if (chart.options.colors) {
- chartOptions.colors = chart.options.colors;
+ for (j = 0; j < s.data.length; j++) {
+ d = s.data[j];
+ key = chart.xtype == "datetime" ? d[0].getTime() : d[0];
+ if (!rows[key]) {
+ rows[key] = new Array(series.length);
}
- if (chart.options.donut) {
- chartOptions.plotOptions = {pie: {innerSize: "50%"}};
+ rows[key][i] = toFloat(d[1]);
+ if (sortedLabels.indexOf(key) === -1) {
+ sortedLabels.push(key);
}
+ }
+ }
- if ("legend" in chart.options) {
- hideLegend(chartOptions, chart.options.legend);
- }
+ if (chart.xtype === "datetime" || chart.xtype === "number") {
+ sortedLabels.sort(sortByNumber);
+ }
- if (chart.options.title) {
- setTitle(chartOptions, chart.options.title);
+ for (j = 0; j < series.length; j++) {
+ rows2.push([]);
+ }
+
+ var value;
+ var k;
+ for (k = 0; k < sortedLabels.length; k++) {
+ i = sortedLabels[k];
+ if (chart.xtype === "datetime") {
+ value = new Date(toFloat(i));
+ // TODO make this efficient
+ day = day && isDay(value);
+ if (!dayOfWeek) {
+ dayOfWeek = value.getDay();
}
+ week = week && isWeek(value, dayOfWeek);
+ month = month && isMonth(value);
+ year = year && isYear(value);
+ hour = hour && isHour(value);
+ minute = minute && isMinute(value);
+ } else {
+ value = i;
+ }
+ labels.push(value);
+ for (j = 0; j < series.length; j++) {
+ // Chart.js doesn't like undefined
+ rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
+ }
+ }
+ } else {
+ for (var i$2 = 0; i$2 < series.length; i$2++) {
+ var s$2 = series[i$2];
+ var d$1 = [];
+ for (var j$2 = 0; j$2 < s$2.data.length; j$2++) {
+ var point = {
+ x: toFloat(s$2.data[j$2][0]),
+ y: toFloat(s$2.data[j$2][1])
+ };
+ if (chartType === "bubble") {
+ point.r = toFloat(s$2.data[j$2][2]) * 20 / max;
+ // custom attribute, for tooltip
+ point.v = s$2.data[j$2][2];
+ }
+ d$1.push(point);
+ }
+ rows2.push(d$1);
+ }
+ }
- var options = merge(chartOptions, chart.options.library || {});
- options.chart.renderTo = chart.element.id;
- options.series = [{
- type: "pie",
- name: chart.options.label || "Value",
- data: chart.data
- }];
- chart.chart = new Highcharts.Chart(options);
- };
+ for (i = 0; i < series.length; i++) {
+ s = series[i];
- this.renderColumnChart = function (chart, chartType) {
- chartType = chartType || "column";
- var series = chart.data;
- var options = jsOptions(chart, chart.options), i, j, s, d, rows = [], categories = [];
- options.chart.type = chartType;
- options.chart.renderTo = chart.element.id;
+ var color = s.color || colors[i];
+ var backgroundColor = chartType !== "line" ? addOpacity(color, 0.5) : color;
- for (i = 0; i < series.length; i++) {
- s = series[i];
+ var dataset = {
+ label: s.name || "",
+ data: rows2[i],
+ fill: chartType === "area",
+ borderColor: color,
+ backgroundColor: backgroundColor,
+ pointBackgroundColor: color,
+ borderWidth: 2,
+ pointHoverBackgroundColor: color
+ };
- for (j = 0; j < s.data.length; j++) {
- d = s.data[j];
- if (!rows[d[0]]) {
- rows[d[0]] = new Array(series.length);
- categories.push(d[0]);
- }
- rows[d[0]][i] = d[1];
- }
- }
+ if (s.stack) {
+ dataset.stack = s.stack;
+ }
- if (chart.options.xtype === "number") {
- categories.sort(sortByNumber);
- }
+ var curve = seriesOption(chart, s, "curve");
+ if (curve === false) {
+ dataset.lineTension = 0;
+ }
- options.xAxis.categories = categories;
+ var points = seriesOption(chart, s, "points");
+ if (points === false) {
+ dataset.pointRadius = 0;
+ dataset.pointHitRadius = 5;
+ }
- var newSeries = [];
- for (i = 0; i < series.length; i++) {
- d = [];
- for (j = 0; j < categories.length; j++) {
- d.push(rows[categories[j]][i] || 0);
- }
+ dataset = merge(dataset, chart.options.dataset || {});
+ dataset = merge(dataset, s.library || {});
+ dataset = merge(dataset, s.dataset || {});
- newSeries.push({
- name: series[i].name,
- data: d
- });
+ datasets.push(dataset);
+ }
+
+ var xmin = chart.options.xmin;
+ var xmax = chart.options.xmax;
+
+ if (chart.xtype === "datetime") {
+ // hacky check for Chart.js >= 2.9.0
+ // https://github.com/chartjs/Chart.js/compare/v2.8.0...v2.9.0
+ var gte29 = "math" in library.helpers;
+ var ticksKey = gte29 ? "ticks" : "time";
+ if (notnull(xmin)) {
+ options.scales.xAxes[0][ticksKey].min = toDate(xmin).getTime();
+ }
+ if (notnull(xmax)) {
+ options.scales.xAxes[0][ticksKey].max = toDate(xmax).getTime();
+ }
+ } else if (chart.xtype === "number") {
+ if (notnull(xmin)) {
+ options.scales.xAxes[0].ticks.min = xmin;
+ }
+ if (notnull(xmax)) {
+ options.scales.xAxes[0].ticks.max = xmax;
+ }
+ }
+
+ if (chart.xtype === "datetime" && labels.length > 0) {
+ var minTime = (notnull(xmin) ? toDate(xmin) : labels[0]).getTime();
+ var maxTime = (notnull(xmax) ? toDate(xmax) : labels[0]).getTime();
+
+ for (i = 1; i < labels.length; i++) {
+ var value$1 = labels[i].getTime();
+ if (value$1 < minTime) {
+ minTime = value$1;
+ }
+ if (value$1 > maxTime) {
+ maxTime = value$1;
+ }
+ }
+
+ var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
+
+ if (!options.scales.xAxes[0].time.unit) {
+ var step;
+ if (year || timeDiff > 365 * 10) {
+ options.scales.xAxes[0].time.unit = "year";
+ step = 365;
+ } else if (month || timeDiff > 30 * 10) {
+ options.scales.xAxes[0].time.unit = "month";
+ step = 30;
+ } else if (day || timeDiff > 10) {
+ options.scales.xAxes[0].time.unit = "day";
+ step = 1;
+ } else if (hour || timeDiff > 0.5) {
+ options.scales.xAxes[0].time.displayFormats = {hour: "MMM D, h a"};
+ options.scales.xAxes[0].time.unit = "hour";
+ step = 1 / 24.0;
+ } else if (minute) {
+ options.scales.xAxes[0].time.displayFormats = {minute: "h:mm a"};
+ options.scales.xAxes[0].time.unit = "minute";
+ step = 1 / 24.0 / 60.0;
+ }
+
+ if (step && timeDiff > 0) {
+ var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
+ if (week && step === 1) {
+ unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
}
- options.series = newSeries;
+ options.scales.xAxes[0].time.unitStepSize = unitStepSize;
+ }
+ }
- chart.chart = new Highcharts.Chart(options);
- };
+ if (!options.scales.xAxes[0].time.tooltipFormat) {
+ if (day) {
+ options.scales.xAxes[0].time.tooltipFormat = "ll";
+ } else if (hour) {
+ options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
+ } else if (minute) {
+ options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
+ }
+ }
+ }
- var self = this;
+ var data = {
+ labels: labels,
+ datasets: datasets
+ };
- this.renderBarChart = function (chart) {
- self.renderColumnChart(chart, "bar");
- };
+ return data;
+ };
- this.renderAreaChart = function (chart) {
- self.renderLineChart(chart, "areaspline");
- };
- };
- adapters.push(HighchartsAdapter);
+ var defaultExport = function defaultExport(library) {
+ this.name = "chartjs";
+ this.library = library;
+ };
+
+ defaultExport.prototype.renderLineChart = function renderLineChart (chart, chartType) {
+ var chartOptions = {};
+ // fix for https://github.com/chartjs/Chart.js/issues/2441
+ if (!chart.options.max && allZeros(chart.data)) {
+ chartOptions.max = 1;
}
- if (!GoogleChartsAdapter && window.google && (window.google.setOnLoadCallback || window.google.charts)) {
- GoogleChartsAdapter = new function () {
- var google = window.google;
- this.name = "google";
+ var options = jsOptions(chart, merge(chartOptions, chart.options));
+ setFormatOptions(chart, options, chartType);
- var loaded = {};
- var callbacks = [];
+ var data = createDataTable(chart, options, chartType || "line", this.library);
- var runCallbacks = function () {
- var cb, call;
- for (var i = 0; i < callbacks.length; i++) {
- cb = callbacks[i];
- call = google.visualization && ((cb.pack === "corechart" && google.visualization.LineChart) || (cb.pack === "timeline" && google.visualization.Timeline));
- if (call) {
- cb.callback();
- callbacks.splice(i, 1);
- i--;
- }
- }
- };
+ if (chart.xtype === "number") {
+ options.scales.xAxes[0].type = "linear";
+ options.scales.xAxes[0].position = "bottom";
+ } else {
+ options.scales.xAxes[0].type = chart.xtype === "string" ? "category" : "time";
+ }
- var waitForLoaded = function (pack, callback) {
- if (!callback) {
- callback = pack;
- pack = "corechart";
- }
+ this.drawChart(chart, "line", data, options);
+ };
- callbacks.push({pack: pack, callback: callback});
+ defaultExport.prototype.renderPieChart = function renderPieChart (chart) {
+ var options = merge({}, baseOptions);
+ if (chart.options.donut) {
+ options.cutoutPercentage = 50;
+ }
- if (loaded[pack]) {
- runCallbacks();
- } else {
- loaded[pack] = true;
+ if ("legend" in chart.options) {
+ hideLegend(options, chart.options.legend);
+ }
- // https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
- var loadOptions = {
- packages: [pack],
- callback: runCallbacks
- };
- if (config.language) {
- loadOptions.language = config.language;
- }
+ if (chart.options.title) {
+ setTitle(options, chart.options.title);
+ }
- if (window.google.setOnLoadCallback) {
- google.load("visualization", "1", loadOptions);
- } else {
- google.charts.load("current", loadOptions);
- }
- }
- };
+ options = merge(options, chart.options.library || {});
+ setFormatOptions(chart, options, "pie");
- // Set chart options
- var defaultOptions = {
- chartArea: {},
- fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
- pointSize: 6,
- legend: {
- textStyle: {
- fontSize: 12,
- color: "#444"
- },
- alignment: "center",
- position: "right"
+ var labels = [];
+ var values = [];
+ for (var i = 0; i < chart.data.length; i++) {
+ var point = chart.data[i];
+ labels.push(point[0]);
+ values.push(point[1]);
+ }
+
+ var dataset = {
+ data: values,
+ backgroundColor: chart.options.colors || defaultColors
+ };
+ dataset = merge(dataset, chart.options.dataset || {});
+
+ var data = {
+ labels: labels,
+ datasets: [dataset]
+ };
+
+ this.drawChart(chart, "pie", data, options);
+ };
+
+ defaultExport.prototype.renderColumnChart = function renderColumnChart (chart, chartType) {
+ var options;
+ if (chartType === "bar") {
+ var barOptions = merge(baseOptions, defaultOptions);
+ delete barOptions.scales.yAxes[0].ticks.maxTicksLimit;
+ options = jsOptionsFunc(barOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options);
+ } else {
+ options = jsOptions(chart, chart.options);
+ }
+ setFormatOptions(chart, options, chartType);
+ var data = createDataTable(chart, options, "column", this.library);
+ if (chartType !== "bar") {
+ setLabelSize(chart, data, options);
+ }
+ this.drawChart(chart, (chartType === "bar" ? "horizontalBar" : "bar"), data, options);
+ };
+
+ defaultExport.prototype.renderAreaChart = function renderAreaChart (chart) {
+ this.renderLineChart(chart, "area");
+ };
+
+ defaultExport.prototype.renderBarChart = function renderBarChart (chart) {
+ this.renderColumnChart(chart, "bar");
+ };
+
+ defaultExport.prototype.renderScatterChart = function renderScatterChart (chart, chartType) {
+ chartType = chartType || "scatter";
+
+ var options = jsOptions(chart, chart.options);
+ setFormatOptions(chart, options, chartType);
+
+ if (!("showLines" in options)) {
+ options.showLines = false;
+ }
+
+ var data = createDataTable(chart, options, chartType, this.library);
+
+ options.scales.xAxes[0].type = "linear";
+ options.scales.xAxes[0].position = "bottom";
+
+ this.drawChart(chart, chartType, data, options);
+ };
+
+ defaultExport.prototype.renderBubbleChart = function renderBubbleChart (chart) {
+ this.renderScatterChart(chart, "bubble");
+ };
+
+ defaultExport.prototype.destroy = function destroy (chart) {
+ if (chart.chart) {
+ chart.chart.destroy();
+ }
+ };
+
+ defaultExport.prototype.drawChart = function drawChart (chart, type, data, options) {
+ this.destroy(chart);
+
+ var chartOptions = {
+ type: type,
+ data: data,
+ options: options
+ };
+
+ if (chart.options.code) {
+ window.console.log("new Chart(ctx, " + JSON.stringify(chartOptions) + ");");
+ }
+
+ chart.element.innerHTML = "<canvas></canvas>";
+ var ctx = chart.element.getElementsByTagName("CANVAS")[0];
+ chart.chart = new this.library(ctx, chartOptions);
+ };
+
+ var defaultOptions$1 = {
+ chart: {},
+ xAxis: {
+ title: {
+ text: null
+ },
+ labels: {
+ style: {
+ fontSize: "12px"
+ }
+ }
+ },
+ yAxis: {
+ title: {
+ text: null
+ },
+ labels: {
+ style: {
+ fontSize: "12px"
+ }
+ }
+ },
+ title: {
+ text: null
+ },
+ credits: {
+ enabled: false
+ },
+ legend: {
+ borderWidth: 0
+ },
+ tooltip: {
+ style: {
+ fontSize: "12px"
+ }
+ },
+ plotOptions: {
+ areaspline: {},
+ area: {},
+ series: {
+ marker: {}
+ }
+ }
+ };
+
+ var hideLegend$1 = function (options, legend, hideLegend) {
+ if (legend !== undefined) {
+ options.legend.enabled = !!legend;
+ if (legend && legend !== true) {
+ if (legend === "top" || legend === "bottom") {
+ options.legend.verticalAlign = legend;
+ } else {
+ options.legend.layout = "vertical";
+ options.legend.verticalAlign = "middle";
+ options.legend.align = legend;
+ }
+ }
+ } else if (hideLegend) {
+ options.legend.enabled = false;
+ }
+ };
+
+ var setTitle$1 = function (options, title) {
+ options.title.text = title;
+ };
+
+ var setMin$1 = function (options, min) {
+ options.yAxis.min = min;
+ };
+
+ var setMax$1 = function (options, max) {
+ options.yAxis.max = max;
+ };
+
+ var setStacked$1 = function (options, stacked) {
+ var stackedValue = stacked ? (stacked === true ? "normal" : stacked) : null;
+ options.plotOptions.series.stacking = stackedValue;
+ options.plotOptions.area.stacking = stackedValue;
+ options.plotOptions.areaspline.stacking = stackedValue;
+ };
+
+ var setXtitle$1 = function (options, title) {
+ options.xAxis.title.text = title;
+ };
+
+ var setYtitle$1 = function (options, title) {
+ options.yAxis.title.text = title;
+ };
+
+ var jsOptions$1 = jsOptionsFunc(defaultOptions$1, hideLegend$1, setTitle$1, setMin$1, setMax$1, setStacked$1, setXtitle$1, setYtitle$1);
+
+ var setFormatOptions$1 = function(chart, options, chartType) {
+ var formatOptions = {
+ prefix: chart.options.prefix,
+ suffix: chart.options.suffix,
+ thousands: chart.options.thousands,
+ decimal: chart.options.decimal,
+ precision: chart.options.precision,
+ round: chart.options.round,
+ zeros: chart.options.zeros
+ };
+
+ if (chartType !== "pie" && !options.yAxis.labels.formatter) {
+ options.yAxis.labels.formatter = function () {
+ return formatValue("", this.value, formatOptions);
+ };
+ }
+
+ if (!options.tooltip.pointFormatter) {
+ options.tooltip.pointFormatter = function () {
+ return '<span style="color:' + this.color + '">\u25CF</span> ' + formatValue(this.series.name + ': <b>', this.y, formatOptions) + '</b><br/>';
+ };
+ }
+ };
+
+ var defaultExport$1 = function defaultExport(library) {
+ this.name = "highcharts";
+ this.library = library;
+ };
+
+ defaultExport$1.prototype.renderLineChart = function renderLineChart (chart, chartType) {
+ chartType = chartType || "spline";
+ var chartOptions = {};
+ if (chartType === "areaspline") {
+ chartOptions = {
+ plotOptions: {
+ areaspline: {
+ stacking: "normal"
},
- curveType: "function",
- hAxis: {
- textStyle: {
- color: "#666",
- fontSize: 12
- },
- titleTextStyle: {},
- gridlines: {
- color: "transparent"
- },
- baselineColor: "#ccc",
- viewWindow: {}
+ area: {
+ stacking: "normal"
},
- vAxis: {
- textStyle: {
- color: "#666",
- fontSize: 12
- },
- titleTextStyle: {},
- baselineColor: "#ccc",
- viewWindow: {}
- },
- tooltip: {
- textStyle: {
- color: "#666",
- fontSize: 12
+ series: {
+ marker: {
+ enabled: false
}
}
- };
+ }
+ };
+ }
- var hideLegend = function (options, legend, hideLegend) {
- if (legend !== undefined) {
- var position;
- if (!legend) {
- position = "none";
- } else if (legend === true) {
- position = "right";
- } else {
- position = legend;
- }
- options.legend.position = position;
- } else if (hideLegend) {
- options.legend.position = "none";
- }
- };
+ if (chart.options.curve === false) {
+ if (chartType === "areaspline") {
+ chartType = "area";
+ } else if (chartType === "spline") {
+ chartType = "line";
+ }
+ }
- var setTitle = function (options, title) {
- options.title = title;
- options.titleTextStyle = {color: "#333", fontSize: "20px"};
- };
+ var options = jsOptions$1(chart, chart.options, chartOptions), data, i, j;
+ options.xAxis.type = chart.xtype === "string" ? "category" : (chart.xtype === "number" ? "linear" : "datetime");
+ if (!options.chart.type) {
+ options.chart.type = chartType;
+ }
+ setFormatOptions$1(chart, options, chartType);
- var setMin = function (options, min) {
- options.vAxis.viewWindow.min = min;
- };
+ var series = chart.data;
+ for (i = 0; i < series.length; i++) {
+ series[i].name = series[i].name || "Value";
+ data = series[i].data;
+ if (chart.xtype === "datetime") {
+ for (j = 0; j < data.length; j++) {
+ data[j][0] = data[j][0].getTime();
+ }
+ }
+ series[i].marker = {symbol: "circle"};
+ if (chart.options.points === false) {
+ series[i].marker.enabled = false;
+ }
+ }
- var setMax = function (options, max) {
- options.vAxis.viewWindow.max = max;
- };
+ this.drawChart(chart, series, options);
+ };
- var setBarMin = function (options, min) {
- options.hAxis.viewWindow.min = min;
- };
+ defaultExport$1.prototype.renderScatterChart = function renderScatterChart (chart) {
+ var options = jsOptions$1(chart, chart.options, {});
+ options.chart.type = "scatter";
+ this.drawChart(chart, chart.data, options);
+ };
- var setBarMax = function (options, max) {
- options.hAxis.viewWindow.max = max;
- };
+ defaultExport$1.prototype.renderPieChart = function renderPieChart (chart) {
+ var chartOptions = merge(defaultOptions$1, {});
- var setStacked = function (options, stacked) {
- options.isStacked = !!stacked;
- };
+ if (chart.options.colors) {
+ chartOptions.colors = chart.options.colors;
+ }
+ if (chart.options.donut) {
+ chartOptions.plotOptions = {pie: {innerSize: "50%"}};
+ }
- var setXtitle = function (options, title) {
- options.hAxis.title = title;
- options.hAxis.titleTextStyle.italic = false;
- };
+ if ("legend" in chart.options) {
+ hideLegend$1(chartOptions, chart.options.legend);
+ }
- var setYtitle = function (options, title) {
- options.vAxis.title = title;
- options.vAxis.titleTextStyle.italic = false;
- };
+ if (chart.options.title) {
+ setTitle$1(chartOptions, chart.options.title);
+ }
- var jsOptions = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
+ var options = merge(chartOptions, chart.options.library || {});
+ setFormatOptions$1(chart, options, "pie");
+ var series = [{
+ type: "pie",
+ name: chart.options.label || "Value",
+ data: chart.data
+ }];
- // cant use object as key
- var createDataTable = function (series, columnType, xtype) {
- var i, j, s, d, key, rows = [], sortedLabels = [];
- for (i = 0; i < series.length; i++) {
- s = series[i];
+ this.drawChart(chart, series, options);
+ };
- for (j = 0; j < s.data.length; j++) {
- d = s.data[j];
- key = (columnType === "datetime") ? d[0].getTime() : d[0];
- if (!rows[key]) {
- rows[key] = new Array(series.length);
- sortedLabels.push(key);
- }
- rows[key][i] = toFloat(d[1]);
- }
- }
+ defaultExport$1.prototype.renderColumnChart = function renderColumnChart (chart, chartType) {
+ chartType = chartType || "column";
+ var series = chart.data;
+ var options = jsOptions$1(chart, chart.options), i, j, s, d, rows = [], categories = [];
+ options.chart.type = chartType;
+ setFormatOptions$1(chart, options, chartType);
- var rows2 = [];
- var day = true;
- var value;
- for (var j = 0; j < sortedLabels.length; j++) {
- var i = sortedLabels[j];
- if (columnType === "datetime") {
- value = new Date(toFloat(i));
- day = day && isDay(value);
- } else if (columnType === "number") {
- value = toFloat(i);
- } else {
- value = i;
- }
- rows2.push([value].concat(rows[i]));
- }
- if (columnType === "datetime") {
- rows2.sort(sortByTime);
- } else if (columnType === "number") {
- rows2.sort(sortByNumberSeries);
- }
+ for (i = 0; i < series.length; i++) {
+ s = series[i];
- if (xtype === "number") {
- rows2.sort(sortByNumberSeries);
+ for (j = 0; j < s.data.length; j++) {
+ d = s.data[j];
+ if (!rows[d[0]]) {
+ rows[d[0]] = new Array(series.length);
+ categories.push(d[0]);
+ }
+ rows[d[0]][i] = d[1];
+ }
+ }
- for (var i = 0; i < rows2.length; i++) {
- rows2[i][0] = toStr(rows2[i][0]);
- }
- }
+ if (chart.xtype === "number") {
+ categories.sort(sortByNumber);
+ }
- // create datatable
- var data = new google.visualization.DataTable();
- columnType = columnType === "datetime" && day ? "date" : columnType;
- data.addColumn(columnType, "");
- for (i = 0; i < series.length; i++) {
- data.addColumn("number", series[i].name);
- }
- data.addRows(rows2);
+ options.xAxis.categories = categories;
- return data;
- };
+ var newSeries = [], d2;
+ for (i = 0; i < series.length; i++) {
+ d = [];
+ for (j = 0; j < categories.length; j++) {
+ d.push(rows[categories[j]][i] || 0);
+ }
- var resize = function (callback) {
- if (window.attachEvent) {
- window.attachEvent("onresize", callback);
- } else if (window.addEventListener) {
- window.addEventListener("resize", callback, true);
- }
- callback();
- };
+ d2 = {
+ name: series[i].name || "Value",
+ data: d
+ };
+ if (series[i].stack) {
+ d2.stack = series[i].stack;
+ }
- this.renderLineChart = function (chart) {
- waitForLoaded(function () {
- var chartOptions = {};
+ newSeries.push(d2);
+ }
- if (chart.options.curve === false) {
- chartOptions.curveType = "none";
- }
+ this.drawChart(chart, newSeries, options);
+ };
- if (chart.options.points === false) {
- chartOptions.pointSize = 0;
- }
+ defaultExport$1.prototype.renderBarChart = function renderBarChart (chart) {
+ this.renderColumnChart(chart, "bar");
+ };
- var options = jsOptions(chart, chart.options, chartOptions);
- var columnType = chart.discrete ? "string" : "datetime";
- if (chart.options.xtype === "number") {
- columnType = "number";
- }
- var data = createDataTable(chart.data, columnType);
- chart.chart = new google.visualization.LineChart(chart.element);
- resize(function () {
- chart.chart.draw(data, options);
- });
- });
- };
+ defaultExport$1.prototype.renderAreaChart = function renderAreaChart (chart) {
+ this.renderLineChart(chart, "areaspline");
+ };
- this.renderPieChart = function (chart) {
- waitForLoaded(function () {
- var chartOptions = {
- chartArea: {
- top: "10%",
- height: "80%"
- },
- legend: {}
- };
- if (chart.options.colors) {
- chartOptions.colors = chart.options.colors;
- }
- if (chart.options.donut) {
- chartOptions.pieHole = 0.5;
- }
- if ("legend" in chart.options) {
- hideLegend(chartOptions, chart.options.legend);
- }
- if (chart.options.title) {
- setTitle(chartOptions, chart.options.title);
- }
- var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
+ defaultExport$1.prototype.destroy = function destroy (chart) {
+ if (chart.chart) {
+ chart.chart.destroy();
+ }
+ };
- var data = new google.visualization.DataTable();
- data.addColumn("string", "");
- data.addColumn("number", "Value");
- data.addRows(chart.data);
+ defaultExport$1.prototype.drawChart = function drawChart (chart, data, options) {
+ this.destroy(chart);
- chart.chart = new google.visualization.PieChart(chart.element);
- resize(function () {
- chart.chart.draw(data, options);
- });
- });
- };
+ options.chart.renderTo = chart.element.id;
+ options.series = data;
- this.renderColumnChart = function (chart) {
- waitForLoaded(function () {
- var options = jsOptions(chart, chart.options);
- var data = createDataTable(chart.data, "string", chart.options.xtype);
- chart.chart = new google.visualization.ColumnChart(chart.element);
- resize(function () {
- chart.chart.draw(data, options);
- });
- });
- };
+ if (chart.options.code) {
+ window.console.log("new Highcharts.Chart(" + JSON.stringify(options) + ");");
+ }
- this.renderBarChart = function (chart) {
- waitForLoaded(function () {
- var chartOptions = {
- hAxis: {
- gridlines: {
- color: "#ccc"
- }
- }
- };
- var options = jsOptionsFunc(defaultOptions, hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options, chartOptions);
- var data = createDataTable(chart.data, "string", chart.options.xtype);
- chart.chart = new google.visualization.BarChart(chart.element);
- resize(function () {
- chart.chart.draw(data, options);
- });
- });
- };
+ chart.chart = new this.library.Chart(options);
+ };
- this.renderAreaChart = function (chart) {
- waitForLoaded(function () {
- var chartOptions = {
- isStacked: true,
- pointSize: 0,
- areaOpacity: 0.5
- };
+ var loaded = {};
+ var callbacks = [];
- var options = jsOptions(chart, chart.options, chartOptions);
- var columnType = chart.discrete ? "string" : "datetime";
- if (chart.options.xtype === "number") {
- columnType = "number";
- }
- var data = createDataTable(chart.data, columnType);
- chart.chart = new google.visualization.AreaChart(chart.element);
- resize(function () {
- chart.chart.draw(data, options);
- });
- });
- };
+ // Set chart options
+ var defaultOptions$2 = {
+ chartArea: {},
+ fontName: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif",
+ pointSize: 6,
+ legend: {
+ textStyle: {
+ fontSize: 12,
+ color: "#444"
+ },
+ alignment: "center",
+ position: "right"
+ },
+ curveType: "function",
+ hAxis: {
+ textStyle: {
+ color: "#666",
+ fontSize: 12
+ },
+ titleTextStyle: {},
+ gridlines: {
+ color: "transparent"
+ },
+ baselineColor: "#ccc",
+ viewWindow: {}
+ },
+ vAxis: {
+ textStyle: {
+ color: "#666",
+ fontSize: 12
+ },
+ titleTextStyle: {},
+ baselineColor: "#ccc",
+ viewWindow: {}
+ },
+ tooltip: {
+ textStyle: {
+ color: "#666",
+ fontSize: 12
+ }
+ }
+ };
- this.renderGeoChart = function (chart) {
- waitForLoaded(function () {
- var chartOptions = {
- legend: "none",
- colorAxis: {
- colors: chart.options.colors || ["#f6c7b6", "#ce502d"]
- }
- };
- var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
+ var hideLegend$2 = function (options, legend, hideLegend) {
+ if (legend !== undefined) {
+ var position;
+ if (!legend) {
+ position = "none";
+ } else if (legend === true) {
+ position = "right";
+ } else {
+ position = legend;
+ }
+ options.legend.position = position;
+ } else if (hideLegend) {
+ options.legend.position = "none";
+ }
+ };
- var data = new google.visualization.DataTable();
- data.addColumn("string", "");
- data.addColumn("number", chart.options.label || "Value");
- data.addRows(chart.data);
+ var setTitle$2 = function (options, title) {
+ options.title = title;
+ options.titleTextStyle = {color: "#333", fontSize: "20px"};
+ };
- chart.chart = new google.visualization.GeoChart(chart.element);
- resize(function () {
- chart.chart.draw(data, options);
- });
- });
- };
+ var setMin$2 = function (options, min) {
+ options.vAxis.viewWindow.min = min;
+ };
- this.renderScatterChart = function (chart) {
- waitForLoaded(function () {
- var chartOptions = {};
- var options = jsOptions(chart, chart.options, chartOptions);
+ var setMax$2 = function (options, max) {
+ options.vAxis.viewWindow.max = max;
+ };
- var series = chart.data, rows2 = [], i, j, data, d;
- for (i = 0; i < series.length; i++) {
- d = series[i].data;
- for (j = 0; j < d.length; j++) {
- var row = new Array(series.length + 1);
- row[0] = d[j][0];
- row[i + 1] = d[j][1];
- rows2.push(row);
- }
- }
+ var setBarMin$1 = function (options, min) {
+ options.hAxis.viewWindow.min = min;
+ };
- var data = new google.visualization.DataTable();
- data.addColumn("number", "");
- for (i = 0; i < series.length; i++) {
- data.addColumn("number", series[i].name);
- }
- data.addRows(rows2);
+ var setBarMax$1 = function (options, max) {
+ options.hAxis.viewWindow.max = max;
+ };
- chart.chart = new google.visualization.ScatterChart(chart.element);
- resize(function () {
- chart.chart.draw(data, options);
- });
- });
- };
+ var setStacked$2 = function (options, stacked) {
+ options.isStacked = stacked ? stacked : false;
+ };
- this.renderTimeline = function (chart) {
- waitForLoaded("timeline", function () {
- var chartOptions = {
- legend: "none"
- };
+ var setXtitle$2 = function (options, title) {
+ options.hAxis.title = title;
+ options.hAxis.titleTextStyle.italic = false;
+ };
- if (chart.options.colors) {
- chartOptions.colors = chart.options.colors;
- }
- var options = merge(merge(defaultOptions, chartOptions), chart.options.library || {});
+ var setYtitle$2 = function (options, title) {
+ options.vAxis.title = title;
+ options.vAxis.titleTextStyle.italic = false;
+ };
- var data = new google.visualization.DataTable();
- data.addColumn({type: "string", id: "Name"});
- data.addColumn({type: "date", id: "Start"});
- data.addColumn({type: "date", id: "End"});
- data.addRows(chart.data);
+ var jsOptions$2 = jsOptionsFunc(defaultOptions$2, hideLegend$2, setTitle$2, setMin$2, setMax$2, setStacked$2, setXtitle$2, setYtitle$2);
- chart.element.style.lineHeight = "normal";
- chart.chart = new google.visualization.Timeline(chart.element);
+ var resize = function (callback) {
+ if (window.attachEvent) {
+ window.attachEvent("onresize", callback);
+ } else if (window.addEventListener) {
+ window.addEventListener("resize", callback, true);
+ }
+ callback();
+ };
- resize(function () {
- chart.chart.draw(data, options);
- });
- });
- };
- };
+ var defaultExport$2 = function defaultExport(library) {
+ this.name = "google";
+ this.library = library;
+ };
- adapters.push(GoogleChartsAdapter);
- }
- if (!ChartjsAdapter && "Chart" in window) {
- ChartjsAdapter = new function () {
- var Chart = window.Chart;
+ defaultExport$2.prototype.renderLineChart = function renderLineChart (chart) {
+ var this$1 = this;
- this.name = "chartjs";
+ this.waitForLoaded(chart, function () {
+ var chartOptions = {};
- var baseOptions = {
- maintainAspectRatio: false,
- animation: false,
- tooltips: {
- displayColors: false
- },
- legend: {},
- title: {fontSize: 20, fontColor: "#333"}
- };
+ if (chart.options.curve === false) {
+ chartOptions.curveType = "none";
+ }
- var defaultOptions = {
- scales: {
- yAxes: [
- {
- ticks: {
- maxTicksLimit: 4
- },
- scaleLabel: {
- fontSize: 16,
- // fontStyle: "bold",
- fontColor: "#333"
- }
- }
- ],
- xAxes: [
- {
- gridLines: {
- drawOnChartArea: false
- },
- scaleLabel: {
- fontSize: 16,
- // fontStyle: "bold",
- fontColor: "#333"
- },
- time: {},
- ticks: {}
- }
- ]
- }
- };
+ if (chart.options.points === false) {
+ chartOptions.pointSize = 0;
+ }
- // http://there4.io/2012/05/02/google-chart-color-list/
- var defaultColors = [
- "#3366CC", "#DC3912", "#FF9900", "#109618", "#990099", "#3B3EAC", "#0099C6",
- "#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11",
- "#6633CC", "#E67300", "#8B0707", "#329262", "#5574A6", "#3B3EAC"
- ];
+ var options = jsOptions$2(chart, chart.options, chartOptions);
+ var data = this$1.createDataTable(chart.data, chart.xtype);
- var hideLegend = function (options, legend, hideLegend) {
- if (legend !== undefined) {
- options.legend.display = !!legend;
- if (legend && legend !== true) {
- options.legend.position = legend;
- }
- } else if (hideLegend) {
- options.legend.display = false;
- }
- };
+ this$1.drawChart(chart, "LineChart", data, options);
+ });
+ };
- var setTitle = function (options, title) {
- options.title.display = true;
- options.title.text = title;
- };
+ defaultExport$2.prototype.renderPieChart = function renderPieChart (chart) {
+ var this$1 = this;
- var setMin = function (options, min) {
- if (min !== null) {
- options.scales.yAxes[0].ticks.min = toFloat(min);
- }
- };
+ this.waitForLoaded(chart, function () {
+ var chartOptions = {
+ chartArea: {
+ top: "10%",
+ height: "80%"
+ },
+ legend: {}
+ };
+ if (chart.options.colors) {
+ chartOptions.colors = chart.options.colors;
+ }
+ if (chart.options.donut) {
+ chartOptions.pieHole = 0.5;
+ }
+ if ("legend" in chart.options) {
+ hideLegend$2(chartOptions, chart.options.legend);
+ }
+ if (chart.options.title) {
+ setTitle$2(chartOptions, chart.options.title);
+ }
+ var options = merge(merge(defaultOptions$2, chartOptions), chart.options.library || {});
- var setMax = function (options, max) {
- options.scales.yAxes[0].ticks.max = toFloat(max);
- };
+ var data = new this$1.library.visualization.DataTable();
+ data.addColumn("string", "");
+ data.addColumn("number", "Value");
+ data.addRows(chart.data);
- var setBarMin = function (options, min) {
- if (min !== null) {
- options.scales.xAxes[0].ticks.min = toFloat(min);
- }
- };
+ this$1.drawChart(chart, "PieChart", data, options);
+ });
+ };
- var setBarMax = function (options, max) {
- options.scales.xAxes[0].ticks.max = toFloat(max);
- };
+ defaultExport$2.prototype.renderColumnChart = function renderColumnChart (chart) {
+ var this$1 = this;
- var setStacked = function (options, stacked) {
- options.scales.xAxes[0].stacked = !!stacked;
- options.scales.yAxes[0].stacked = !!stacked;
- };
+ this.waitForLoaded(chart, function () {
+ var options = jsOptions$2(chart, chart.options);
+ var data = this$1.createDataTable(chart.data, chart.xtype);
- var setXtitle = function (options, title) {
- options.scales.xAxes[0].scaleLabel.display = true;
- options.scales.xAxes[0].scaleLabel.labelString = title;
- };
+ this$1.drawChart(chart, "ColumnChart", data, options);
+ });
+ };
- var setYtitle = function (options, title) {
- options.scales.yAxes[0].scaleLabel.display = true;
- options.scales.yAxes[0].scaleLabel.labelString = title;
- };
+ defaultExport$2.prototype.renderBarChart = function renderBarChart (chart) {
+ var this$1 = this;
- var drawChart = function(chart, type, data, options) {
- if (chart.chart) {
- chart.chart.destroy();
- } else {
- chart.element.innerHTML = "<canvas></canvas>";
+ this.waitForLoaded(chart, function () {
+ var chartOptions = {
+ hAxis: {
+ gridlines: {
+ color: "#ccc"
}
+ }
+ };
+ var options = jsOptionsFunc(defaultOptions$2, hideLegend$2, setTitle$2, setBarMin$1, setBarMax$1, setStacked$2, setXtitle$2, setYtitle$2)(chart, chart.options, chartOptions);
+ var data = this$1.createDataTable(chart.data, chart.xtype);
- var ctx = chart.element.getElementsByTagName("CANVAS")[0];
- chart.chart = new Chart(ctx, {
- type: type,
- data: data,
- options: options
- });
- };
+ this$1.drawChart(chart, "BarChart", data, options);
+ });
+ };
- // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
- var addOpacity = function(hex, opacity) {
- var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
- return result ? "rgba(" + parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16) + ", " + opacity + ")" : hex;
- };
+ defaultExport$2.prototype.renderAreaChart = function renderAreaChart (chart) {
+ var this$1 = this;
- var setLabelSize = function (chart, data, options) {
- var maxLabelSize = Math.ceil(chart.element.offsetWidth / 4.0 / data.labels.length);
- if (maxLabelSize > 25) {
- maxLabelSize = 25;
- }
- options.scales.xAxes[0].ticks.callback = function (value) {
- value = toStr(value);
- if (value.length > maxLabelSize) {
- return value.substring(0, maxLabelSize - 2) + "...";
- } else {
- return value;
- }
- };
- };
+ this.waitForLoaded(chart, function () {
+ var chartOptions = {
+ isStacked: true,
+ pointSize: 0,
+ areaOpacity: 0.5
+ };
- var jsOptions = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setMin, setMax, setStacked, setXtitle, setYtitle);
+ var options = jsOptions$2(chart, chart.options, chartOptions);
+ var data = this$1.createDataTable(chart.data, chart.xtype);
- var createDataTable = function (chart, options, chartType) {
- var datasets = [];
- var labels = [];
+ this$1.drawChart(chart, "AreaChart", data, options);
+ });
+ };
- var colors = chart.options.colors || defaultColors;
+ defaultExport$2.prototype.renderGeoChart = function renderGeoChart (chart) {
+ var this$1 = this;
- var day = true;
- var week = true;
- var dayOfWeek;
- var month = true;
- var year = true;
- var hour = true;
- var minute = true;
- var detectType = (chartType === "line" || chartType === "area") && !chart.discrete;
+ this.waitForLoaded(chart, function () {
+ var chartOptions = {
+ legend: "none",
+ colorAxis: {
+ colors: chart.options.colors || ["#f6c7b6", "#ce502d"]
+ }
+ };
+ var options = merge(merge(defaultOptions$2, chartOptions), chart.options.library || {});
- var series = chart.data;
+ var data = new this$1.library.visualization.DataTable();
+ data.addColumn("string", "");
+ data.addColumn("number", chart.options.label || "Value");
+ data.addRows(chart.data);
- var sortedLabels = [];
+ this$1.drawChart(chart, "GeoChart", data, options);
+ });
+ };
- var i, j, s, d, key, rows = [];
- for (i = 0; i < series.length; i++) {
- s = series[i];
+ defaultExport$2.prototype.renderScatterChart = function renderScatterChart (chart) {
+ var this$1 = this;
- for (j = 0; j < s.data.length; j++) {
- d = s.data[j];
- key = detectType ? d[0].getTime() : d[0];
- if (!rows[key]) {
- rows[key] = new Array(series.length);
- }
- rows[key][i] = toFloat(d[1]);
- if (sortedLabels.indexOf(key) === -1) {
- sortedLabels.push(key);
- }
- }
- }
+ this.waitForLoaded(chart, function () {
+ var chartOptions = {};
+ var options = jsOptions$2(chart, chart.options, chartOptions);
- if (detectType || chart.options.xtype === "number") {
- sortedLabels.sort(sortByNumber);
- }
+ var series = chart.data, rows2 = [], i, j, data, d;
+ for (i = 0; i < series.length; i++) {
+ series[i].name = series[i].name || "Value";
+ d = series[i].data;
+ for (j = 0; j < d.length; j++) {
+ var row = new Array(series.length + 1);
+ row[0] = d[j][0];
+ row[i + 1] = d[j][1];
+ rows2.push(row);
+ }
+ }
- var rows2 = [];
- for (j = 0; j < series.length; j++) {
- rows2.push([]);
- }
+ data = new this$1.library.visualization.DataTable();
+ data.addColumn("number", "");
+ for (i = 0; i < series.length; i++) {
+ data.addColumn("number", series[i].name);
+ }
+ data.addRows(rows2);
- var value;
- var k;
- for (k = 0; k < sortedLabels.length; k++) {
- i = sortedLabels[k];
- if (detectType) {
- value = new Date(toFloat(i));
- // TODO make this efficient
- day = day && isDay(value);
- if (!dayOfWeek) {
- dayOfWeek = value.getDay();
- }
- week = week && isWeek(value, dayOfWeek);
- month = month && isMonth(value);
- year = year && isYear(value);
- hour = hour && isHour(value);
- minute = minute && isMinute(value);
- } else {
- value = i;
- }
- labels.push(value);
- for (j = 0; j < series.length; j++) {
- // Chart.js doesn't like undefined
- rows2[j].push(rows[i][j] === undefined ? null : rows[i][j]);
- }
- }
+ this$1.drawChart(chart, "ScatterChart", data, options);
+ });
+ };
- for (i = 0; i < series.length; i++) {
- s = series[i];
+ defaultExport$2.prototype.renderTimeline = function renderTimeline (chart) {
+ var this$1 = this;
- var color = s.color || colors[i];
- var backgroundColor = chartType !== "line" ? addOpacity(color, 0.5) : color;
+ this.waitForLoaded(chart, "timeline", function () {
+ var chartOptions = {
+ legend: "none"
+ };
- var dataset = {
- label: s.name,
- data: rows2[i],
- fill: chartType === "area",
- borderColor: color,
- backgroundColor: backgroundColor,
- pointBackgroundColor: color,
- borderWidth: 2
- };
+ if (chart.options.colors) {
+ chartOptions.colors = chart.options.colors;
+ }
+ var options = merge(merge(defaultOptions$2, chartOptions), chart.options.library || {});
- if (chart.options.curve === false) {
- dataset.lineTension = 0;
- }
+ var data = new this$1.library.visualization.DataTable();
+ data.addColumn({type: "string", id: "Name"});
+ data.addColumn({type: "date", id: "Start"});
+ data.addColumn({type: "date", id: "End"});
+ data.addRows(chart.data);
- if (chart.options.points === false) {
- dataset.pointRadius = 0;
- dataset.pointHitRadius = 5;
- }
+ chart.element.style.lineHeight = "normal";
- datasets.push(merge(dataset, s.library || {}));
- }
+ this$1.drawChart(chart, "Timeline", data, options);
+ });
+ };
- if (detectType && labels.length > 0) {
- var minTime = labels[0].getTime();
- var maxTime = labels[0].getTime();
- for (i = 1; i < labels.length; i++) {
- value = labels[i].getTime();
- if (value < minTime) {
- minTime = value;
- }
- if (value > maxTime) {
- maxTime = value;
- }
- }
+ defaultExport$2.prototype.destroy = function destroy (chart) {
+ if (chart.chart) {
+ chart.chart.clearChart();
+ }
+ };
- var timeDiff = (maxTime - minTime) / (86400 * 1000.0);
+ defaultExport$2.prototype.drawChart = function drawChart (chart, type, data, options) {
+ this.destroy(chart);
- if (!options.scales.xAxes[0].time.unit) {
- var step;
- if (year || timeDiff > 365 * 10) {
- options.scales.xAxes[0].time.unit = "year";
- step = 365;
- } else if (month || timeDiff > 30 * 10) {
- options.scales.xAxes[0].time.unit = "month";
- step = 30;
- } else if (day || timeDiff > 10) {
- options.scales.xAxes[0].time.unit = "day";
- step = 1;
- } else if (hour || timeDiff > 0.5) {
- options.scales.xAxes[0].time.displayFormats = {hour: "MMM D, h a"};
- options.scales.xAxes[0].time.unit = "hour";
- step = 1 / 24.0;
- } else if (minute) {
- options.scales.xAxes[0].time.displayFormats = {minute: "h:mm a"};
- options.scales.xAxes[0].time.unit = "minute";
- step = 1 / 24.0 / 60.0;
- }
+ if (chart.options.code) {
+ window.console.log("var data = new google.visualization.DataTable(" + data.toJSON() + ");\nvar chart = new google.visualization." + type + "(element);\nchart.draw(data, " + JSON.stringify(options) + ");");
+ }
- if (step && timeDiff > 0) {
- var unitStepSize = Math.ceil(timeDiff / step / (chart.element.offsetWidth / 100.0));
- if (week && step === 1) {
- unitStepSize = Math.ceil(unitStepSize / 7.0) * 7;
- }
- options.scales.xAxes[0].time.unitStepSize = unitStepSize;
- }
- }
+ chart.chart = new this.library.visualization[type](chart.element);
+ resize(function () {
+ chart.chart.draw(data, options);
+ });
+ };
- if (!options.scales.xAxes[0].time.tooltipFormat) {
- if (day) {
- options.scales.xAxes[0].time.tooltipFormat = "ll";
- } else if (hour) {
- options.scales.xAxes[0].time.tooltipFormat = "MMM D, h a";
- } else if (minute) {
- options.scales.xAxes[0].time.tooltipFormat = "h:mm a";
- }
- }
- }
+ defaultExport$2.prototype.waitForLoaded = function waitForLoaded (chart, pack, callback) {
+ var this$1 = this;
- var data = {
- labels: labels,
- datasets: datasets
- };
+ if (!callback) {
+ callback = pack;
+ pack = "corechart";
+ }
- return data;
- };
+ callbacks.push({pack: pack, callback: callback});
- this.renderLineChart = function (chart, chartType) {
- if (chart.options.xtype === "number") {
- return self.renderScatterChart(chart, chartType, true);
- }
+ if (loaded[pack]) {
+ this.runCallbacks();
+ } else {
+ loaded[pack] = true;
- var chartOptions = {};
- if (chartType === "area") {
- // TODO fix area stacked
- // chartOptions.stacked = true;
- }
- // fix for https://github.com/chartjs/Chart.js/issues/2441
- if (!chart.options.max && allZeros(chart.data)) {
- chartOptions.max = 1;
- }
+ // https://groups.google.com/forum/#!topic/google-visualization-api/fMKJcyA2yyI
+ var loadOptions = {
+ packages: [pack],
+ callback: function () { this$1.runCallbacks(); }
+ };
+ var config = chart.__config();
+ if (config.language) {
+ loadOptions.language = config.language;
+ }
+ if (pack === "corechart" && config.mapsApiKey) {
+ loadOptions.mapsApiKey = config.mapsApiKey;
+ }
- var options = jsOptions(chart, merge(chartOptions, chart.options));
+ this.library.charts.load("current", loadOptions);
+ }
+ };
- var data = createDataTable(chart, options, chartType || "line");
+ defaultExport$2.prototype.runCallbacks = function runCallbacks () {
+ var cb, call;
+ for (var i = 0; i < callbacks.length; i++) {
+ cb = callbacks[i];
+ call = this.library.visualization && ((cb.pack === "corechart" && this.library.visualization.LineChart) || (cb.pack === "timeline" && this.library.visualization.Timeline));
+ if (call) {
+ cb.callback();
+ callbacks.splice(i, 1);
+ i--;
+ }
+ }
+ };
- options.scales.xAxes[0].type = chart.discrete ? "category" : "time";
+ // cant use object as key
+ defaultExport$2.prototype.createDataTable = function createDataTable (series, columnType) {
+ var i, j, s, d, key, rows = [], sortedLabels = [];
+ for (i = 0; i < series.length; i++) {
+ s = series[i];
+ series[i].name = series[i].name || "Value";
- drawChart(chart, "line", data, options);
- };
+ for (j = 0; j < s.data.length; j++) {
+ d = s.data[j];
+ key = (columnType === "datetime") ? d[0].getTime() : d[0];
+ if (!rows[key]) {
+ rows[key] = new Array(series.length);
+ sortedLabels.push(key);
+ }
+ rows[key][i] = toFloat(d[1]);
+ }
+ }
- this.renderPieChart = function (chart) {
- var options = merge({}, baseOptions);
- if (chart.options.donut) {
- options.cutoutPercentage = 50;
- }
+ var rows2 = [];
+ var day = true;
+ var value;
+ for (j = 0; j < sortedLabels.length; j++) {
+ i = sortedLabels[j];
+ if (columnType === "datetime") {
+ value = new Date(toFloat(i));
+ day = day && isDay(value);
+ } else if (columnType === "number") {
+ value = toFloat(i);
+ } else {
+ value = i;
+ }
+ rows2.push([value].concat(rows[i]));
+ }
+ if (columnType === "datetime") {
+ rows2.sort(sortByTime);
+ } else if (columnType === "number") {
+ rows2.sort(sortByNumberSeries);
- if ("legend" in chart.options) {
- hideLegend(options, chart.options.legend);
- }
+ for (i = 0; i < rows2.length; i++) {
+ rows2[i][0] = toStr(rows2[i][0]);
+ }
- if (chart.options.title) {
- setTitle(options, chart.options.title);
- }
+ columnType = "string";
+ }
- options = merge(options, chart.options.library || {});
+ // create datatable
+ var data = new this.library.visualization.DataTable();
+ columnType = columnType === "datetime" && day ? "date" : columnType;
+ data.addColumn(columnType, "");
+ for (i = 0; i < series.length; i++) {
+ data.addColumn("number", series[i].name);
+ }
+ data.addRows(rows2);
- var labels = [];
- var values = [];
- for (var i = 0; i < chart.data.length; i++) {
- var point = chart.data[i];
- labels.push(point[0]);
- values.push(point[1]);
- }
+ return data;
+ };
- var data = {
- labels: labels,
- datasets: [
- {
- data: values,
- backgroundColor: chart.options.colors || defaultColors
- }
- ]
- };
+ var pendingRequests = [], runningRequests = 0, maxRequests = 4;
- drawChart(chart, "pie", data, options);
- };
+ function pushRequest(url, success, error) {
+ pendingRequests.push([url, success, error]);
+ runNext();
+ }
- this.renderColumnChart = function (chart, chartType) {
- var options;
- if (chartType === "bar") {
- options = jsOptionsFunc(merge(baseOptions, defaultOptions), hideLegend, setTitle, setBarMin, setBarMax, setStacked, setXtitle, setYtitle)(chart, chart.options);
- } else {
- options = jsOptions(chart, chart.options);
- }
- var data = createDataTable(chart, options, "column");
- setLabelSize(chart, data, options);
- drawChart(chart, (chartType === "bar" ? "horizontalBar" : "bar"), data, options);
- };
+ function runNext() {
+ if (runningRequests < maxRequests) {
+ var request = pendingRequests.shift();
+ if (request) {
+ runningRequests++;
+ getJSON(request[0], request[1], request[2]);
+ runNext();
+ }
+ }
+ }
- var self = this;
+ function requestComplete() {
+ runningRequests--;
+ runNext();
+ }
- this.renderAreaChart = function (chart) {
- self.renderLineChart(chart, "area");
- };
+ function getJSON(url, success, error) {
+ ajaxCall(url, success, function (jqXHR, textStatus, errorThrown) {
+ var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
+ error(message);
+ });
+ }
- this.renderBarChart = function (chart) {
- self.renderColumnChart(chart, "bar");
- };
+ function ajaxCall(url, success, error) {
+ var $ = window.jQuery || window.Zepto || window.$;
- this.renderScatterChart = function (chart, chartType, lineChart) {
- chartType = chartType || "line";
+ if ($ && $.ajax) {
+ $.ajax({
+ dataType: "json",
+ url: url,
+ success: success,
+ error: error,
+ complete: requestComplete
+ });
+ } else {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url, true);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ xhr.onload = function () {
+ requestComplete();
+ if (xhr.status === 200) {
+ success(JSON.parse(xhr.responseText), xhr.statusText, xhr);
+ } else {
+ error(xhr, "error", xhr.statusText);
+ }
+ };
+ xhr.send();
+ }
+ }
- var options = jsOptions(chart, chart.options);
+ var config = {};
+ var adapters = [];
- var colors = chart.options.colors || defaultColors;
+ // helpers
- var datasets = [];
- var series = chart.data;
- for (var i = 0; i < series.length; i++) {
- var s = series[i];
- var d = [];
- for (var j = 0; j < s.data.length; j++) {
- var point = {
- x: toFloat(s.data[j][0]),
- y: toFloat(s.data[j][1])
- };
- if (chartType === "bubble") {
- point.r = toFloat(s.data[j][2]);
- }
- d.push(point);
- }
+ function setText(element, text) {
+ if (document.body.innerText) {
+ element.innerText = text;
+ } else {
+ element.textContent = text;
+ }
+ }
- var color = s.color || colors[i];
- var backgroundColor = chartType === "area" ? addOpacity(color, 0.5) : color;
+ // TODO remove prefix for all messages
+ function chartError(element, message, noPrefix) {
+ if (!noPrefix) {
+ message = "Error Loading Chart: " + message;
+ }
+ setText(element, message);
+ element.style.color = "#ff0000";
+ }
- datasets.push({
- label: s.name,
- showLine: lineChart || false,
- data: d,
- borderColor: color,
- backgroundColor: backgroundColor,
- pointBackgroundColor: color,
- fill: chartType === "area"
- })
- }
+ function errorCatcher(chart) {
+ try {
+ chart.__render();
+ } catch (err) {
+ chartError(chart.element, err.message);
+ throw err;
+ }
+ }
- if (chartType === "area") {
- chartType = "line";
- }
+ function fetchDataSource(chart, dataSource) {
+ if (typeof dataSource === "string") {
+ pushRequest(dataSource, function (data) {
+ chart.rawData = data;
+ errorCatcher(chart);
+ }, function (message) {
+ chartError(chart.element, message);
+ });
+ } else if (typeof dataSource === "function") {
+ try {
+ dataSource(function (data) {
+ chart.rawData = data;
+ errorCatcher(chart);
+ }, function (message) {
+ chartError(chart.element, message, true);
+ });
+ } catch (err) {
+ chartError(chart.element, err, true);
+ }
+ } else {
+ chart.rawData = dataSource;
+ errorCatcher(chart);
+ }
+ }
- var data = {datasets: datasets};
+ function addDownloadButton(chart) {
+ var element = chart.element;
+ var link = document.createElement("a");
- options.scales.xAxes[0].type = "linear";
- options.scales.xAxes[0].position = "bottom";
+ var download = chart.options.download;
+ if (download === true) {
+ download = {};
+ } else if (typeof download === "string") {
+ download = {filename: download};
+ }
+ link.download = download.filename || "chart.png"; // https://caniuse.com/download
- drawChart(chart, chartType, data, options);
- };
+ link.style.position = "absolute";
+ link.style.top = "20px";
+ link.style.right = "20px";
+ link.style.zIndex = 1000;
+ link.style.lineHeight = "20px";
+ link.target = "_blank"; // for safari
+ var image = document.createElement("img");
+ image.alt = "Download";
+ image.style.border = "none";
+ // icon from font-awesome
+ // http://fa2png.io/
+ image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAABCFBMVEUAAADMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMywEsqxAAAAV3RSTlMAAQIDBggJCgsMDQ4PERQaHB0eISIjJCouLzE0OTo/QUJHSUpLTU5PUllhYmltcHh5foWLjI+SlaCio6atr7S1t7m6vsHHyM7R2tze5Obo7fHz9ff5+/1hlxK2AAAA30lEQVQYGUXBhVYCQQBA0TdYWAt2d3d3YWAHyur7/z9xgD16Lw0DW+XKx+1GgX+FRzM3HWQWrHl5N/oapW5RPe0PkBu+UYeICvozTWZVK23Ao04B79oJrOsJDOoxkZoQPWgX29pHpCZEk7rEvQYiNSFq1UMqvlCjJkRBS1R8hb00Vb/TajtBL7nTHE1X1vyMQF732dQhyF2o6SAwrzP06iUQzvwsArlnzcOdrgBhJyHa1QOgO9U1GsKuvjUTjavliZYQ8nNPapG6sap/3nrIdJ6bOWzmX/fy0XVpfzZP3S8OJT3g9EEiJwAAAABJRU5ErkJggg==";
+ link.appendChild(image);
+ element.style.position = "relative";
- this.renderBubbleChart = function (chart) {
- this.renderScatterChart(chart, "bubble");
- };
+ chart.__downloadAttached = true;
+
+ // mouseenter
+ chart.__enterEvent = addEvent(element, "mouseover", function(e) {
+ var related = e.relatedTarget;
+ // check download option again to ensure it wasn't changed
+ if ((!related || (related !== this && !childOf(this, related))) && chart.options.download) {
+ link.href = chart.toImage(download);
+ element.appendChild(link);
+ }
+ });
+
+ // mouseleave
+ chart.__leaveEvent = addEvent(element, "mouseout", function(e) {
+ var related = e.relatedTarget;
+ if (!related || (related !== this && !childOf(this, related))) {
+ if (link.parentNode) {
+ link.parentNode.removeChild(link);
+ }
+ }
+ });
+ }
+
+ // https://stackoverflow.com/questions/10149963/adding-event-listener-cross-browser
+ function addEvent(elem, event, fn) {
+ if (elem.addEventListener) {
+ elem.addEventListener(event, fn, false);
+ return fn;
+ } else {
+ var fn2 = function() {
+ // set the this pointer same as addEventListener when fn is called
+ return(fn.call(elem, window.event));
};
+ elem.attachEvent("on" + event, fn2);
+ return fn2;
+ }
+ }
- adapters.unshift(ChartjsAdapter);
+ function removeEvent(elem, event, fn) {
+ if (elem.removeEventListener) {
+ elem.removeEventListener(event, fn, false);
+ } else {
+ elem.detachEvent("on" + event, fn);
}
}
+ // https://gist.github.com/shawnbot/4166283
+ function childOf(p, c) {
+ if (p === c) { return false; }
+ while (c && c !== p) { c = c.parentNode; }
+ return c === p;
+ }
+
+ function getAdapterType(library) {
+ if (library) {
+ if (library.product === "Highcharts") {
+ return defaultExport$1;
+ } else if (library.charts) {
+ return defaultExport$2;
+ } else if (isFunction(library)) {
+ return defaultExport;
+ }
+ }
+ throw new Error("Unknown adapter");
+ }
+
+ function addAdapter(library) {
+ var adapterType = getAdapterType(library);
+ var adapter = new adapterType(library);
+
+ if (adapters.indexOf(adapter) === -1) {
+ adapters.push(adapter);
+ }
+ }
+
+ function loadAdapters() {
+ if ("Chart" in window) {
+ addAdapter(window.Chart);
+ }
+
+ if ("Highcharts" in window) {
+ addAdapter(window.Highcharts);
+ }
+
+ if (window.google && window.google.charts) {
+ addAdapter(window.google);
+ }
+ }
+
+ function dataEmpty(data, chartType) {
+ if (chartType === "PieChart" || chartType === "GeoChart" || chartType === "Timeline") {
+ return data.length === 0;
+ } else {
+ for (var i = 0; i < data.length; i++) {
+ if (data[i].data.length > 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
function renderChart(chartType, chart) {
- callAdapter(chartType, chart);
- if (chart.options.download && !chart.downloadAttached && chart.adapter === "chartjs") {
- addDownloadButton(chart);
+ if (chart.options.messages && chart.options.messages.empty && dataEmpty(chart.data, chartType)) {
+ setText(chart.element, chart.options.messages.empty);
+ } else {
+ callAdapter(chartType, chart);
+ if (chart.options.download && !chart.__downloadAttached && chart.adapter === "chartjs") {
+ addDownloadButton(chart);
+ }
}
}
// TODO remove chartType if cross-browser way
// to get the name of the chart class
@@ -1469,14 +1924,20 @@
for (i = 0; i < adapters.length; i++) {
adapter = adapters[i];
if ((!adapterName || adapterName === adapter.name) && isFunction(adapter[fnName])) {
chart.adapter = adapter.name;
+ chart.__adapterObject = adapter;
return adapter[fnName](chart);
}
}
- throw new Error("No adapter found");
+
+ if (adapters.length > 0) {
+ throw new Error("No charting library found for " + chartType);
+ } else {
+ throw new Error("No charting libraries found - be sure to include one before your charts");
+ }
}
// process data
var toFormattedKey = function (key, keyType) {
@@ -1506,92 +1967,69 @@
r.sort(sortByNumberSeries);
}
return r;
};
- function isMinute(d) {
- return d.getMilliseconds() === 0 && d.getSeconds() === 0;
+ function detectXType(series, noDatetime) {
+ if (detectXTypeWithFunction(series, isNumber)) {
+ return "number";
+ } else if (!noDatetime && detectXTypeWithFunction(series, isDate)) {
+ return "datetime";
+ } else {
+ return "string";
+ }
}
- function isHour(d) {
- return isMinute(d) && d.getMinutes() === 0;
- }
-
- function isDay(d) {
- return isHour(d) && d.getHours() === 0;
- }
-
- function isWeek(d, dayOfWeek) {
- return isDay(d) && d.getDay() === dayOfWeek;
- }
-
- function isMonth(d) {
- return isDay(d) && d.getDate() === 1;
- }
-
- function isYear(d) {
- return isMonth(d) && d.getMonth() === 0;
- }
-
- function isDate(obj) {
- return !isNaN(toDate(obj)) && toStr(obj).length >= 6;
- }
-
- function allZeros(data) {
- var i, j, d;
- for (i = 0; i < data.length; i++) {
- d = data[i].data;
- for (j = 0; j < d.length; j++) {
- if (d[j][1] != 0) {
+ function detectXTypeWithFunction(series, func) {
+ var i, j, data;
+ for (i = 0; i < series.length; i++) {
+ data = toArr(series[i].data);
+ for (j = 0; j < data.length; j++) {
+ if (!func(data[j][0])) {
return false;
}
}
}
return true;
}
- function detectDiscrete(series) {
- var i, j, data;
+ // creates a shallow copy of each element of the array
+ // elements are expected to be objects
+ function copySeries(series) {
+ var newSeries = [], i, j;
for (i = 0; i < series.length; i++) {
- data = toArr(series[i].data);
- for (j = 0; j < data.length; j++) {
- if (!isDate(data[j][0])) {
- return true;
+ var copy = {};
+ for (j in series[i]) {
+ if (series[i].hasOwnProperty(j)) {
+ copy[j] = series[i][j];
}
}
+ newSeries.push(copy);
}
- return false;
+ return newSeries;
}
- function processSeries(chart, keyType) {
+ function processSeries(chart, keyType, noDatetime) {
var i;
var opts = chart.options;
var series = chart.rawData;
// see if one series or multiple
if (!isArray(series) || typeof series[0] !== "object" || isArray(series[0])) {
- series = [{name: opts.label || "Value", data: series}];
+ series = [{name: opts.label, data: series}];
chart.hideLegend = true;
} else {
chart.hideLegend = false;
}
- if ((opts.discrete === null || opts.discrete === undefined) && keyType !== "bubble" && keyType !== "number") {
- chart.discrete = detectDiscrete(series);
- } else {
- chart.discrete = opts.discrete;
- }
- if (chart.discrete) {
- keyType = "string";
- }
- if (chart.options.xtype) {
- keyType = chart.options.xtype;
- }
+ chart.xtype = keyType ? keyType : (opts.discrete ? "string" : detectXType(series, noDatetime));
+
// right format
+ series = copySeries(series);
for (i = 0; i < series.length; i++) {
- series[i].data = formatSeriesData(toArr(series[i].data), keyType);
+ series[i].data = formatSeriesData(toArr(series[i].data), chart.xtype);
}
return series;
}
@@ -1601,188 +2039,398 @@
perfectData[i] = [toStr(perfectData[i][0]), toFloat(perfectData[i][1])];
}
return perfectData;
}
- function processTime(chart)
- {
- var i, data = chart.rawData;
- for (i = 0; i < data.length; i++) {
- data[i][1] = toDate(data[i][1]);
- data[i][2] = toDate(data[i][2]);
+ // define classes
+
+ var Chart = function Chart(element, dataSource, options) {
+ var elementId;
+ if (typeof element === "string") {
+ elementId = element;
+ element = document.getElementById(element);
+ if (!element) {
+ throw new Error("No element with id " + elementId);
+ }
}
- return data;
- }
+ this.element = element;
+ this.options = merge(Chartkick.options, options || {});
+ this.dataSource = dataSource;
- function processLineData(chart) {
- return processSeries(chart, "datetime");
- }
+ Chartkick.charts[element.id] = this;
- function processColumnData(chart) {
- return processSeries(chart, "string");
- }
+ fetchDataSource(this, dataSource);
- function processBarData(chart) {
- return processSeries(chart, "string");
- }
+ if (this.options.refresh) {
+ this.startRefresh();
+ }
+ };
- function processAreaData(chart) {
- return processSeries(chart, "datetime");
- }
+ Chart.prototype.getElement = function getElement () {
+ return this.element;
+ };
- function processScatterData(chart) {
- return processSeries(chart, "number");
- }
+ Chart.prototype.getDataSource = function getDataSource () {
+ return this.dataSource;
+ };
- function processBubbleData(chart) {
- return processSeries(chart, "bubble");
- }
+ Chart.prototype.getData = function getData () {
+ return this.data;
+ };
- function createChart(chartType, chart, element, dataSource, opts, processData) {
- var elementId;
- if (typeof element === "string") {
- elementId = element;
- element = document.getElementById(element);
- if (!element) {
- throw new Error("No element with id " + elementId);
+ Chart.prototype.getOptions = function getOptions () {
+ return this.options;
+ };
+
+ Chart.prototype.getChartObject = function getChartObject () {
+ return this.chart;
+ };
+
+ Chart.prototype.getAdapter = function getAdapter () {
+ return this.adapter;
+ };
+
+ Chart.prototype.updateData = function updateData (dataSource, options) {
+ this.dataSource = dataSource;
+ if (options) {
+ this.__updateOptions(options);
+ }
+ fetchDataSource(this, dataSource);
+ };
+
+ Chart.prototype.setOptions = function setOptions (options) {
+ this.__updateOptions(options);
+ this.redraw();
+ };
+
+ Chart.prototype.redraw = function redraw () {
+ fetchDataSource(this, this.rawData);
+ };
+
+ Chart.prototype.refreshData = function refreshData () {
+ if (typeof this.dataSource === "string") {
+ // prevent browser from caching
+ var sep = this.dataSource.indexOf("?") === -1 ? "?" : "&";
+ var url = this.dataSource + sep + "_=" + (new Date()).getTime();
+ fetchDataSource(this, url);
+ } else if (typeof this.dataSource === "function") {
+ fetchDataSource(this, this.dataSource);
+ }
+ };
+
+ Chart.prototype.startRefresh = function startRefresh () {
+ var this$1 = this;
+
+ var refresh = this.options.refresh;
+
+ if (refresh && typeof this.dataSource !== "string" && typeof this.dataSource !== "function") {
+ throw new Error("Data source must be a URL or callback for refresh");
+ }
+
+ if (!this.intervalId) {
+ if (refresh) {
+ this.intervalId = setInterval( function () {
+ this$1.refreshData();
+ }, refresh * 1000);
+ } else {
+ throw new Error("No refresh interval");
}
}
+ };
- chart.element = element;
- opts = merge(Chartkick.options, opts || {});
- chart.options = opts;
- chart.dataSource = dataSource;
+ Chart.prototype.stopRefresh = function stopRefresh () {
+ if (this.intervalId) {
+ clearInterval(this.intervalId);
+ this.intervalId = null;
+ }
+ };
- if (!processData) {
- processData = function (chart) {
- return chart.rawData;
+ Chart.prototype.toImage = function toImage (download) {
+ if (this.adapter === "chartjs") {
+ if (download && download.background && download.background !== "transparent") {
+ // https://stackoverflow.com/questions/30464750/chartjs-line-chart-set-background-color
+ var canvas = this.chart.chart.canvas;
+ var ctx = this.chart.chart.ctx;
+ var tmpCanvas = document.createElement("canvas");
+ var tmpCtx = tmpCanvas.getContext("2d");
+ tmpCanvas.width = ctx.canvas.width;
+ tmpCanvas.height = ctx.canvas.height;
+ tmpCtx.fillStyle = download.background;
+ tmpCtx.fillRect(0, 0, tmpCanvas.width, tmpCanvas.height);
+ tmpCtx.drawImage(canvas, 0, 0);
+ return tmpCanvas.toDataURL("image/png");
+ } else {
+ return this.chart.toBase64Image();
}
+ } else {
+ // TODO throw error in next major version
+ // throw new Error("Feature only available for Chart.js");
+ return null;
}
+ };
- // getters
- chart.getElement = function () {
- return element;
+ Chart.prototype.destroy = function destroy () {
+ if (this.__adapterObject) {
+ this.__adapterObject.destroy(this);
+ }
+
+ if (this.__enterEvent) {
+ removeEvent(this.element, "mouseover", this.__enterEvent);
+ }
+
+ if (this.__leaveEvent) {
+ removeEvent(this.element, "mouseout", this.__leaveEvent);
+ }
+ };
+
+ Chart.prototype.__updateOptions = function __updateOptions (options) {
+ var updateRefresh = options.refresh && options.refresh !== this.options.refresh;
+ this.options = merge(Chartkick.options, options);
+ if (updateRefresh) {
+ this.stopRefresh();
+ this.startRefresh();
+ }
+ };
+
+ Chart.prototype.__render = function __render () {
+ this.data = this.__processData();
+ renderChart(this.__chartName(), this);
+ };
+
+ Chart.prototype.__config = function __config () {
+ return config;
+ };
+
+ var LineChart = /*@__PURE__*/(function (Chart) {
+ function LineChart () {
+ Chart.apply(this, arguments);
+ }
+
+ if ( Chart ) LineChart.__proto__ = Chart;
+ LineChart.prototype = Object.create( Chart && Chart.prototype );
+ LineChart.prototype.constructor = LineChart;
+
+ LineChart.prototype.__processData = function __processData () {
+ return processSeries(this);
};
- chart.getDataSource = function () {
- return chart.dataSource;
+
+ LineChart.prototype.__chartName = function __chartName () {
+ return "LineChart";
};
- chart.getData = function () {
- return chart.data;
+
+ return LineChart;
+ }(Chart));
+
+ var PieChart = /*@__PURE__*/(function (Chart) {
+ function PieChart () {
+ Chart.apply(this, arguments);
+ }
+
+ if ( Chart ) PieChart.__proto__ = Chart;
+ PieChart.prototype = Object.create( Chart && Chart.prototype );
+ PieChart.prototype.constructor = PieChart;
+
+ PieChart.prototype.__processData = function __processData () {
+ return processSimple(this);
};
- chart.getOptions = function () {
- return chart.options;
+
+ PieChart.prototype.__chartName = function __chartName () {
+ return "PieChart";
};
- chart.getChartObject = function () {
- return chart.chart;
+
+ return PieChart;
+ }(Chart));
+
+ var ColumnChart = /*@__PURE__*/(function (Chart) {
+ function ColumnChart () {
+ Chart.apply(this, arguments);
+ }
+
+ if ( Chart ) ColumnChart.__proto__ = Chart;
+ ColumnChart.prototype = Object.create( Chart && Chart.prototype );
+ ColumnChart.prototype.constructor = ColumnChart;
+
+ ColumnChart.prototype.__processData = function __processData () {
+ return processSeries(this, null, true);
};
- chart.getAdapter = function () {
- return chart.adapter;
+
+ ColumnChart.prototype.__chartName = function __chartName () {
+ return "ColumnChart";
};
- var callback = function () {
- chart.data = processData(chart);
- renderChart(chartType, chart);
+ return ColumnChart;
+ }(Chart));
+
+ var BarChart = /*@__PURE__*/(function (Chart) {
+ function BarChart () {
+ Chart.apply(this, arguments);
+ }
+
+ if ( Chart ) BarChart.__proto__ = Chart;
+ BarChart.prototype = Object.create( Chart && Chart.prototype );
+ BarChart.prototype.constructor = BarChart;
+
+ BarChart.prototype.__processData = function __processData () {
+ return processSeries(this, null, true);
};
- // functions
- chart.updateData = function (dataSource, options) {
- chart.dataSource = dataSource;
- if (options) {
- chart.options = merge(Chartkick.options, options);
- }
- fetchDataSource(chart, callback, dataSource);
+ BarChart.prototype.__chartName = function __chartName () {
+ return "BarChart";
};
- chart.setOptions = function (options) {
- chart.options = merge(Chartkick.options, options);
- chart.redraw();
+
+ return BarChart;
+ }(Chart));
+
+ var AreaChart = /*@__PURE__*/(function (Chart) {
+ function AreaChart () {
+ Chart.apply(this, arguments);
+ }
+
+ if ( Chart ) AreaChart.__proto__ = Chart;
+ AreaChart.prototype = Object.create( Chart && Chart.prototype );
+ AreaChart.prototype.constructor = AreaChart;
+
+ AreaChart.prototype.__processData = function __processData () {
+ return processSeries(this);
};
- chart.redraw = function() {
- fetchDataSource(chart, callback, chart.rawData);
+
+ AreaChart.prototype.__chartName = function __chartName () {
+ return "AreaChart";
};
- chart.refreshData = function () {
- if (typeof dataSource === "string") {
- // prevent browser from caching
- var sep = dataSource.indexOf("?") === -1 ? "?" : "&";
- var url = dataSource + sep + "_=" + (new Date()).getTime();
- fetchDataSource(chart, callback, url);
- }
+
+ return AreaChart;
+ }(Chart));
+
+ var GeoChart = /*@__PURE__*/(function (Chart) {
+ function GeoChart () {
+ Chart.apply(this, arguments);
+ }
+
+ if ( Chart ) GeoChart.__proto__ = Chart;
+ GeoChart.prototype = Object.create( Chart && Chart.prototype );
+ GeoChart.prototype.constructor = GeoChart;
+
+ GeoChart.prototype.__processData = function __processData () {
+ return processSimple(this);
};
- chart.stopRefresh = function () {
- if (chart.intervalId) {
- clearInterval(chart.intervalId);
- }
+
+ GeoChart.prototype.__chartName = function __chartName () {
+ return "GeoChart";
};
- chart.toImage = function () {
- if (chart.adapter === "chartjs") {
- return chart.chart.toBase64Image();
- } else {
- return null;
- }
+
+ return GeoChart;
+ }(Chart));
+
+ var ScatterChart = /*@__PURE__*/(function (Chart) {
+ function ScatterChart () {
+ Chart.apply(this, arguments);
}
- Chartkick.charts[element.id] = chart;
+ if ( Chart ) ScatterChart.__proto__ = Chart;
+ ScatterChart.prototype = Object.create( Chart && Chart.prototype );
+ ScatterChart.prototype.constructor = ScatterChart;
- fetchDataSource(chart, callback, dataSource);
+ ScatterChart.prototype.__processData = function __processData () {
+ return processSeries(this, "number");
+ };
- if (opts.refresh) {
- chart.intervalId = setInterval( function () {
- chart.refreshData();
- }, opts.refresh * 1000);
+ ScatterChart.prototype.__chartName = function __chartName () {
+ return "ScatterChart";
+ };
+
+ return ScatterChart;
+ }(Chart));
+
+ var BubbleChart = /*@__PURE__*/(function (Chart) {
+ function BubbleChart () {
+ Chart.apply(this, arguments);
}
- }
- // define classes
+ if ( Chart ) BubbleChart.__proto__ = Chart;
+ BubbleChart.prototype = Object.create( Chart && Chart.prototype );
+ BubbleChart.prototype.constructor = BubbleChart;
- Chartkick = {
- LineChart: function (element, dataSource, options) {
- createChart("LineChart", this, element, dataSource, options, processLineData);
- },
- PieChart: function (element, dataSource, options) {
- createChart("PieChart", this, element, dataSource, options, processSimple);
- },
- ColumnChart: function (element, dataSource, options) {
- createChart("ColumnChart", this, element, dataSource, options, processColumnData);
- },
- BarChart: function (element, dataSource, options) {
- createChart("BarChart", this, element, dataSource, options, processBarData);
- },
- AreaChart: function (element, dataSource, options) {
- createChart("AreaChart", this, element, dataSource, options, processAreaData);
- },
- GeoChart: function (element, dataSource, options) {
- createChart("GeoChart", this, element, dataSource, options, processSimple);
- },
- ScatterChart: function (element, dataSource, options) {
- createChart("ScatterChart", this, element, dataSource, options, processScatterData);
- },
- BubbleChart: function (element, dataSource, options) {
- createChart("BubbleChart", this, element, dataSource, options, processBubbleData);
- },
- Timeline: function (element, dataSource, options) {
- createChart("Timeline", this, element, dataSource, options, processTime);
- },
+ BubbleChart.prototype.__processData = function __processData () {
+ return processSeries(this, "bubble");
+ };
+
+ BubbleChart.prototype.__chartName = function __chartName () {
+ return "BubbleChart";
+ };
+
+ return BubbleChart;
+ }(Chart));
+
+ var Timeline = /*@__PURE__*/(function (Chart) {
+ function Timeline () {
+ Chart.apply(this, arguments);
+ }
+
+ if ( Chart ) Timeline.__proto__ = Chart;
+ Timeline.prototype = Object.create( Chart && Chart.prototype );
+ Timeline.prototype.constructor = Timeline;
+
+ Timeline.prototype.__processData = function __processData () {
+ var i, data = this.rawData;
+ for (i = 0; i < data.length; i++) {
+ data[i][1] = toDate(data[i][1]);
+ data[i][2] = toDate(data[i][2]);
+ }
+ return data;
+ };
+
+ Timeline.prototype.__chartName = function __chartName () {
+ return "Timeline";
+ };
+
+ return Timeline;
+ }(Chart));
+
+ var Chartkick = {
+ LineChart: LineChart,
+ PieChart: PieChart,
+ ColumnChart: ColumnChart,
+ BarChart: BarChart,
+ AreaChart: AreaChart,
+ GeoChart: GeoChart,
+ ScatterChart: ScatterChart,
+ BubbleChart: BubbleChart,
+ Timeline: Timeline,
charts: {},
configure: function (options) {
for (var key in options) {
if (options.hasOwnProperty(key)) {
config[key] = options[key];
}
}
},
+ setDefaultOptions: function (opts) {
+ Chartkick.options = opts;
+ },
eachChart: function (callback) {
for (var chartId in Chartkick.charts) {
if (Chartkick.charts.hasOwnProperty(chartId)) {
callback(Chartkick.charts[chartId]);
}
}
},
+ config: config,
options: {},
adapters: adapters,
- createChart: createChart
+ addAdapter: addAdapter,
+ use: function(adapter) {
+ addAdapter(adapter);
+ return Chartkick;
+ }
};
- if (typeof module === "object" && typeof module.exports === "object") {
- module.exports = Chartkick;
- } else {
+ // not ideal, but allows for simpler integration
+ if (typeof window !== "undefined" && !window.Chartkick) {
window.Chartkick = Chartkick;
}
-}(window));
+
+ // backwards compatibility for esm require
+ Chartkick.default = Chartkick;
+
+ return Chartkick;
+
+})));