Widget that handles bi-directional communication between user-defined JavaScript and the Jupyter kernel via a sandboxed iframe and postMessage.
It is very difficult to get kernel comms directly working across local and cloud environments without pushing users to install custom Jupyter widgets or extensions for each project. For restricted environments (corporate / medical) this isn't always achievable. stitch
alleviates that by acting as general-purpose library where user-defined JavaScript can be rendered in Jupyter without the boilerplate.
Below is an example of a message being rendered in Jupyter passed from JavaScript and relayed back.
import stitch
w = stitch.StitchWidget()
w.srcdoc = """
<html>
<script>
// Ping 'kernelmsg' back to kernel as 'clientmsg'
window.addEventListener("message", function(event) {
if (event.source === window.parent && event.data.type === "kernelmsg") {
document.getElementById("msgview").innerHTML = event.data.content;
window.parent.postMessage({type: "clientmsg", content: event.data.content}, "*");
}
});
// Handle iframe resizing to fit content
window.addEventListener("load", function(){
var prevHeight = 0;
var prevWidth = 0;
setInterval(function() {
var body = document.body, html = document.documentElement;
var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
var width = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth);
if (height !== prevHeight || prevWidth !== width) {
msg = {type: 'resize', content: {height: height + 'px', width: width + 'px'}};
window.parent.postMessage(msg, "*");
prevHeight = height;
prevWidth = width;
}
}, 100);
});
</script>
<body>
<div style="white-space:nowrap">
MESSAGE: <span id="msgview"></span>
</div>
</body>
</html>
"""
w
Send a kernel message to the client
# This will update all rendered widgets within Jupyter (including above)
w.kernelmsg = "Houston, we have a problem."
w
Our example sends pings the kernel message back to client.
assert w.clientmsg == "Houston, we have a problem."
stitch
uses a custom DOMWidget
, so you can monitor changes too.
w.observe(lambda x: print(x['new']), 'kernelmsg')
w.kernelmsg = "Wow, a change!"
The StitchWidget
used throughout has the following state:
srcdoc
- HTML to be rendered (in a sandboxed iframe) as the frontendkernelmsg
- Message sent via Jupyter kernelclientmsg
- Message sent from frontendinitial_height
- Initial height of the sandboxed iframeinitial_width
- Initial width of the sandboxed iframeinitial_border
- Initial border of the sandboxed iframe
You can install using pip
:
pip install stitch
If you are using Jupyter Notebook 5.2 or earlier, you may also need to enable the nbextension:
jupyter nbextension enable --py [--sys-prefix|--user|--system] stitch