apexcharter/inst/htmlwidgets/apexcharter.js

357 lines
11 KiB
JavaScript
Raw Normal View History

2020-03-18 18:28:51 +01:00
/*!
*
* htmlwidgets bindings for ApexCharts
* https://github.com/dreamRs/apexcharter
*
*/
2021-02-11 21:52:55 +01:00
2020-10-01 14:13:03 +02:00
/*global HTMLWidgets, ApexCharts, Shiny */
2020-03-18 18:28:51 +01:00
/// Functions
// From Friss tuto (https://github.com/FrissAnalytics/shinyJsTutorials/blob/master/tutorials/tutorial_03.Rmd)
2020-11-11 10:21:28 +01:00
var apexcharter = {
getWidget: function(id) {
var htmlWidgetsObj = HTMLWidgets.find("#" + id);
var widgetObj;
if (typeof htmlWidgetsObj !== "undefined") {
widgetObj = htmlWidgetsObj.getChart();
}
return widgetObj;
},
2021-02-11 21:52:55 +01:00
2020-11-11 10:21:28 +01:00
isSingleSerie: function(options) {
var typeLabels = ["pie", "radialBar", "donut"];
var lab = typeLabels.indexOf(options.w.config.chart.type) > -1;
var single = options.w.config.series.length === 1;
return lab | single;
},
2021-02-11 21:52:55 +01:00
2020-11-11 10:21:28 +01:00
isDatetimeAxis: function(chartContext) {
if (
chartContext.hasOwnProperty("w") &&
chartContext.w.hasOwnProperty("config") &&
chartContext.w.config.hasOwnProperty("xaxis") &&
chartContext.w.config.xaxis.hasOwnProperty("type")
) {
return chartContext.w.config.xaxis.type == "datetime";
} else {
return false;
}
},
2021-02-11 21:52:55 +01:00
2020-11-11 10:21:28 +01:00
getSelection: function(chartContext, selectedDataPoints, serieIndex) {
var typeLabels = ["pie", "radialBar", "donut"];
var typeXY = ["scatter", "bubble"];
var selected;
if (typeLabels.indexOf(chartContext.opts.chart.type) > -1) {
var labels = chartContext.opts.labels;
selected = selectedDataPoints[serieIndex].map(function(index) {
return labels[index];
});
2020-03-18 18:28:51 +01:00
} else {
2020-11-11 10:21:28 +01:00
var data = chartContext.opts.series[serieIndex].data;
selected = selectedDataPoints[serieIndex].map(function(index) {
var val = data[index];
if (typeXY.indexOf(chartContext.opts.chart.type) < 0) {
if (val.hasOwnProperty("x")) {
val = val.x;
} else {
val = val[0];
}
}
return val;
});
2020-03-18 18:28:51 +01:00
}
2020-11-11 10:21:28 +01:00
//console.log(selected);
if (typeXY.indexOf(chartContext.opts.chart.type) > -1) {
selected = {
x: selected.map(function(obj) {
return obj.x;
}),
y: selected.map(function(obj) {
return obj.y;
})
};
2020-03-18 18:28:51 +01:00
}
2020-11-11 10:21:28 +01:00
if (typeof selected == "undefined") {
selected = null;
2020-03-18 18:28:51 +01:00
}
2020-11-11 10:21:28 +01:00
return selected;
},
2021-02-11 21:52:55 +01:00
2020-11-11 10:21:28 +01:00
getYaxis: function(axis) {
var yzoom = { min: null, max: null };
if (typeof axis.yaxis !== "undefined" && axis.yaxis !== null) {
var y_axis;
if (axis.yaxis.hasOwnProperty("min")) {
y_axis = axis.yaxis;
} else {
y_axis = axis.yaxis[0];
}
if (y_axis.hasOwnProperty("min") && typeof y_axis.min !== "undefined") {
yzoom.min = y_axis.min;
}
if (y_axis.hasOwnProperty("max") && typeof y_axis.max !== "undefined") {
yzoom.max = y_axis.max;
}
2020-03-18 18:28:51 +01:00
}
2020-11-11 10:21:28 +01:00
return yzoom;
},
2021-02-11 21:52:55 +01:00
2020-11-11 10:21:28 +01:00
getXaxis: function(axis) {
var xzoom = { min: null, max: null };
if (typeof axis.xaxis !== "undefined") {
var x_axis = axis.xaxis;
if (x_axis.hasOwnProperty("min") && typeof x_axis.min !== "undefined") {
xzoom.min = x_axis.min;
}
if (x_axis.hasOwnProperty("max") && typeof x_axis.max !== "undefined") {
xzoom.max = x_axis.max;
}
2020-03-18 18:28:51 +01:00
}
2020-11-11 10:21:28 +01:00
return xzoom;
},
2021-02-11 21:52:55 +01:00
2020-11-11 10:21:28 +01:00
exportChart: function(x, chart) {
if (x.hasOwnProperty("shinyEvents") & HTMLWidgets.shinyMode) {
if (x.shinyEvents.hasOwnProperty("export")) {
setTimeout(function() {
chart.dataURI().then(function(imgURI) {
Shiny.setInputValue(x.shinyEvents.export.inputId, imgURI);
});
}, 1000);
}
2020-07-27 18:55:31 +02:00
}
}
2020-11-11 10:21:28 +01:00
};
2020-07-27 18:55:31 +02:00
2020-03-18 18:28:51 +01:00
/// Widget
2018-07-30 22:54:39 +02:00
HTMLWidgets.widget({
2020-03-04 15:14:02 +01:00
name: "apexcharter",
2018-07-30 22:54:39 +02:00
2020-03-04 15:14:02 +01:00
type: "output",
2018-07-30 22:54:39 +02:00
factory: function(el, width, height) {
2020-03-18 18:28:51 +01:00
var axOpts;
2019-02-14 17:17:30 +01:00
var apexchart = null;
2018-07-30 22:54:39 +02:00
return {
renderValue: function(x) {
// Global options
2020-03-18 18:28:51 +01:00
axOpts = x.ax_opts;
2020-07-27 18:55:31 +02:00
2020-04-16 16:42:34 +02:00
if (x.sparkbox) {
el.style.background = x.sparkbox.background;
el.classList.add("apexcharter-spark-box");
}
2018-07-30 22:54:39 +02:00
// Sizing
2020-03-18 18:28:51 +01:00
if (typeof axOpts.chart === "undefined") {
axOpts.chart = {};
2018-08-01 23:02:29 +02:00
}
axOpts.chart.width = el.clientWidth;
axOpts.chart.height = el.clientHeight;
2020-04-15 19:32:15 +02:00
if (!axOpts.chart.hasOwnProperty("id")) {
axOpts.chart.id = el.id;
}
2020-03-18 18:28:51 +01:00
if (!axOpts.chart.hasOwnProperty("parentHeightOffset")) {
axOpts.chart.parentHeightOffset = 0;
2019-08-20 14:27:40 +02:00
}
2020-07-27 18:55:31 +02:00
2020-04-15 14:41:15 +02:00
// added events to remove minheight container
if (!axOpts.chart.hasOwnProperty("events")) {
axOpts.chart.events = {};
}
if (!axOpts.chart.events.hasOwnProperty("mounted")) {
axOpts.chart.events.mounted = function(chartContext, config) {
el.style.minHeight = 0;
};
}
if (!axOpts.chart.events.hasOwnProperty("updated")) {
axOpts.chart.events.updated = function(chartContext, config) {
el.style.minHeight = 0;
};
}
2020-03-04 15:14:02 +01:00
2020-03-04 22:52:13 +01:00
if (x.hasOwnProperty("shinyEvents") & HTMLWidgets.shinyMode) {
2020-03-18 18:28:51 +01:00
if (!axOpts.hasOwnProperty("chart")) {
axOpts.chart = {};
2020-03-03 20:05:03 +01:00
}
2020-03-18 18:28:51 +01:00
if (!axOpts.chart.hasOwnProperty("events")) {
axOpts.chart.events = {};
2020-03-03 20:05:03 +01:00
}
2020-03-04 22:52:13 +01:00
if (x.shinyEvents.hasOwnProperty("click")) {
2020-03-18 18:28:51 +01:00
axOpts.chart.events.dataPointSelection = function(
2020-03-04 15:14:02 +01:00
event,
chartContext,
opts
) {
2020-03-04 23:49:50 +01:00
var options = opts;
2020-03-14 20:41:41 +01:00
var nonEmpty = opts.selectedDataPoints.filter(function(el) {
2020-03-04 23:49:50 +01:00
return el !== null && el.length > 0;
});
if (nonEmpty.length > 0) {
var select = {};
for (var i = 0; i < opts.selectedDataPoints.length; i++) {
if (typeof opts.selectedDataPoints[i] === "undefined") {
continue;
}
2020-11-11 10:21:28 +01:00
var selection = apexcharter.getSelection(
2020-03-18 18:28:51 +01:00
chartContext,
options.selectedDataPoints,
i
);
2020-03-04 23:49:50 +01:00
if (selection !== null) {
if (opts.w.config.series[i].hasOwnProperty("name")) {
var name = opts.w.config.series[i].name;
select[name] = selection;
} else {
select[i] = selection;
}
}
2020-03-04 15:14:02 +01:00
}
2020-11-11 10:21:28 +01:00
if (apexcharter.isSingleSerie(options)) {
2020-03-04 23:49:50 +01:00
select = select[Object.keys(select)[0]];
2020-03-04 15:14:02 +01:00
}
2020-03-14 20:41:41 +01:00
Shiny.setInputValue(
x.shinyEvents.click.inputId + ":apex_click",
2020-11-11 10:21:28 +01:00
{ value: select, datetime: apexcharter.isDatetimeAxis(chartContext) }
2020-03-14 20:41:41 +01:00
);
2020-03-04 23:49:50 +01:00
} else {
Shiny.setInputValue(x.shinyEvents.click.inputId, null);
2020-03-04 10:42:10 +01:00
}
2020-03-03 20:05:03 +01:00
};
}
2020-03-04 23:49:50 +01:00
if (x.shinyEvents.hasOwnProperty("zoomed")) {
2020-03-18 18:28:51 +01:00
axOpts.chart.events.zoomed = function(chartContext, xaxis, yaxis) {
2020-03-04 23:49:50 +01:00
var id = x.shinyEvents.zoomed.inputId;
2020-11-11 10:21:28 +01:00
if (apexcharter.isDatetimeAxis(chartContext)) {
2020-03-04 19:02:01 +01:00
id = id + ":apex_datetime";
}
Shiny.setInputValue(id, {
2020-11-11 10:21:28 +01:00
x: apexcharter.getXaxis(xaxis),
y: apexcharter.getYaxis(xaxis)
2020-03-04 19:02:01 +01:00
});
};
}
2020-03-18 12:30:48 +01:00
if (x.shinyEvents.hasOwnProperty("selection")) {
2020-03-18 18:28:51 +01:00
axOpts.chart.events.selection = function(
chartContext,
xaxis,
yaxis
) {
2020-03-18 12:30:48 +01:00
var id = x.shinyEvents.selection.inputId;
2020-11-11 10:21:28 +01:00
if (apexcharter.isDatetimeAxis(chartContext)) {
2020-03-18 12:30:48 +01:00
id = id + ":apex_datetime";
}
var selectionValue;
2020-03-18 18:28:51 +01:00
if (x.shinyEvents.selection.type === "x") {
selectionValue = { x: xaxis.xaxis };
} else if (x.shinyEvents.selection.type === "xy") {
2020-11-11 10:21:28 +01:00
selectionValue = { x: xaxis.xaxis, y: apexcharter.getYaxis(xaxis) };
2020-03-18 18:28:51 +01:00
} else if (x.shinyEvents.selection.type === "y") {
2020-11-11 10:21:28 +01:00
selectionValue = { y: apexcharter.getYaxis(xaxis) };
2020-03-18 12:30:48 +01:00
}
Shiny.setInputValue(id, selectionValue);
};
}
2020-03-03 20:05:03 +01:00
}
2018-07-30 22:54:39 +02:00
2019-02-14 17:17:30 +01:00
// Generate or update chart
if (apexchart === null) {
2020-03-18 18:28:51 +01:00
apexchart = new ApexCharts(el, axOpts);
2020-07-27 18:55:31 +02:00
apexchart.render().then(function() {
2020-11-11 10:21:28 +01:00
apexcharter.exportChart(x, apexchart);
2020-07-27 18:55:31 +02:00
});
2019-02-14 17:17:30 +01:00
} else {
2019-02-15 23:33:40 +01:00
if (x.auto_update) {
2020-04-15 14:41:15 +02:00
//console.log(x.auto_update);
2020-02-12 18:21:40 +01:00
if (x.auto_update.update_options) {
var options = Object.assign({}, axOpts);
delete options.series;
delete options.chart.width;
delete options.chart.height;
2020-07-27 18:55:31 +02:00
apexchart
.updateOptions(
options,
2020-07-27 18:55:31 +02:00
x.auto_update.options_redrawPaths,
x.auto_update.options_animate,
x.auto_update.update_synced_charts
);
2020-02-12 11:57:24 +01:00
}
apexchart
.updateSeries(axOpts.series, x.auto_update.series_animate)
.then(function(chart) {
2020-11-11 10:21:28 +01:00
apexcharter.exportChart(x, chart);
});
2019-02-15 23:33:40 +01:00
} else {
apexchart.destroy();
2020-03-18 18:28:51 +01:00
apexchart = new ApexCharts(el, axOpts);
2020-07-27 18:55:31 +02:00
apexchart.render().then(function() {
2020-11-11 10:21:28 +01:00
apexcharter.exportChart(x, apexchart);
2020-07-27 18:55:31 +02:00
});
2019-02-15 23:33:40 +01:00
}
2019-02-14 17:17:30 +01:00
}
2018-07-30 22:54:39 +02:00
},
2020-03-04 15:14:02 +01:00
getChart: function() {
2019-02-14 17:40:03 +01:00
return apexchart;
2018-09-07 18:06:41 +02:00
},
2018-07-30 22:54:39 +02:00
resize: function(width, height) {
2019-02-14 17:40:03 +01:00
apexchart.updateOptions({
2018-07-30 22:54:39 +02:00
chart: {
width: width,
height: height
}
});
}
};
}
});
2018-09-07 18:06:41 +02:00
if (HTMLWidgets.shinyMode) {
2019-07-19 16:00:10 +02:00
// update serie
2020-03-04 15:14:02 +01:00
Shiny.addCustomMessageHandler("update-apexchart-series", function(obj) {
2020-11-11 10:21:28 +01:00
var chart = apexcharter.getWidget(obj.id);
2020-03-04 15:14:02 +01:00
if (typeof chart != "undefined") {
chart.updateSeries(
[
{
data: obj.data.newSeries
}
],
obj.data.animate
);
}
2019-07-19 16:00:10 +02:00
});
2020-03-04 15:14:02 +01:00
2019-07-19 16:00:10 +02:00
// update options
2020-03-04 15:14:02 +01:00
Shiny.addCustomMessageHandler("update-apexchart-options", function(obj) {
2020-11-11 10:21:28 +01:00
var chart = apexcharter.getWidget(obj.id);
2020-03-04 15:14:02 +01:00
if (typeof chart != "undefined") {
2021-02-11 21:52:55 +01:00
var options = obj.data.options;
var evals = obj.data.evals;
if (!(evals instanceof Array)) evals = [evals];
for (var k = 0; evals && k < evals.length; k++) {
window.HTMLWidgets.evaluateStringMember(options, evals[k]);
}
chart.updateOptions(options);
2020-03-04 15:14:02 +01:00
}
2018-09-07 18:06:41 +02:00
});
2021-02-11 21:52:55 +01:00
2020-10-01 14:13:03 +02:00
// toggle series
Shiny.addCustomMessageHandler("update-apexchart-toggle-series", function(obj) {
2020-11-11 10:21:28 +01:00
var chart = apexcharter.getWidget(obj.id);
2020-10-01 14:13:03 +02:00
if (typeof chart != "undefined") {
var seriesName = obj.data.seriesName;
for(var i = 0; i < seriesName.length; i++) {
chart.toggleSeries(seriesName[i]);
}
}
});
2018-09-07 18:06:41 +02:00
}