HTMLWidgets.widget({
name: "plotly",
type: "output",
initialize: function(el, width, height) {
return {};
},
resize: function(el, width, height, instance) {
if (instance.autosize) {
Plotly.relayout(el.id, {width: width, height: height});
}
},
renderValue: function(el, x, instance) {
var shinyMode;
if (typeof(window) !== "undefined") {
// make sure plots don't get created outside the network
window.PLOTLYENV = window.PLOTLYENV || {};
window.PLOTLYENV.BASE_URL = x.base_url;
shinyMode = !!window.Shiny;
}
var graphDiv = document.getElementById(el.id);
// if no plot exists yet, create one with a particular configuration
if (!instance.plotly) {
Plotly.plot(graphDiv, x.data, x.layout, x.config);
instance.plotly = true;
instance.autosize = x.layout.autosize;
} else {
Plotly.newPlot(graphDiv, x.data, x.layout);
}
sendEventData = function(eventType) {
return function(eventData) {
if (eventData === undefined || !eventData.hasOwnProperty("points")) {
return null;
}
var d = eventData.points.map(function(pt) {
var obj = {
curveNumber: pt.curveNumber,
pointNumber: pt.pointNumber,
x: pt.x,
y: pt.y
};
// grab the trace corresponding to this point
var tr = x.data[pt.curveNumber];
// add on additional trace info, if it exists
attachKey = function(keyName) {
if (tr.hasOwnProperty(keyName) && tr[keyName] !== null) {
if (typeof pt.pointNumber === "number") {
obj[keyName] = tr[keyName][pt.pointNumber];
} else {
obj[keyName] = tr[keyName][pt.pointNumber[0]][pt.pointNumber[1]];
}// TODO: can pointNumber be 3D?
}
};
attachKey("z");
attachKey("key");
return obj;
});
Shiny.onInputChange(
".clientValue-" + eventType + "-" + x.source,
JSON.stringify(d)
);
};
};
// send user input event data to shiny
if (shinyMode) {
// https://plot.ly/javascript/zoom-events/
graphDiv.on('plotly_relayout', function(d) {
Shiny.onInputChange(
".clientValue-" + "plotly_relayout" + "-" + x.source,
JSON.stringify(d)
);
});
graphDiv.on('plotly_hover', sendEventData('plotly_hover'));
graphDiv.on('plotly_click', sendEventData('plotly_click'));
graphDiv.on('plotly_selected', sendEventData('plotly_selected'));
graphDiv.on('plotly_unhover', function(eventData) {
Shiny.onInputChange(".clientValue-plotly_hover-" + x.source, null);
});
graphDiv.on('plotly_doubleclick', function(eventData) {
Shiny.onInputChange(".clientValue-plotly_click-" + x.source, null);
});
// 'plotly_deselect' is code for doubleclick when in select mode
graphDiv.on('plotly_deselect', function(eventData) {
Shiny.onInputChange(".clientValue-plotly_selected-" + x.source, null);
Shiny.onInputChange(".clientValue-plotly_click-" + x.source, null);
});
}
}
});