Mathematica now has an official dynamic notebook renderer that enables us embedding notebooks inside a web page. With such renderer, what you can get is basically the style same as in the Wolfram online documentation center. This post describes how it is set up.
Basic usage
STEP 0: First of all, we need to publish our target notebook as a CloudObject. This can be done in various way, for example
CloudPublish[ Manipulate[Plot[x ^ n, {x, -3, 3}], {n, 0, 5, 1}], Permissions->"All"->{"Read", "Interact"} ]
Open Mathematica NotebookSTEP 1: Now let’s can install the required javascript file by npm:
npm install wolfram-notebook-embedder
STEP 2: Create container div for the notebook
<div id="mma-notebook-container"></div>
STEP 3: Include the downloaded js file wolfram-notebook-embedder.min.js in the target webpage. And then we invoke the dynamic rendering process by the following code. In the function WolframNotebookEmbedder.embed, the first argument is the target CloudObject to be embedded; the second argument is the DOM container; and the third argument is optional that specifies some properties of the rendering.
var container = document.querySelector("#mma-notebook-container") var embedding = WolframNotebookEmbedder.embed( 'https://www.wolframcloud.com/obj/10d6bb97-84b8-4a0d-8a3a-d210b7a3e783', container, { width: 640, maxHeight: 480, allowInteract: true, showRenderProgress: true } )
Create a toggler for user
Sometimes we don’t want the notebook to load when the page is loaded, since the rendering process takes some time. Let’s make a simple toggler that can let the user decide whether or not to trigger the rendering process. Just like this one:
<div class="mma-notebook" id="some-id" data-expand=false>
<div class="mma-notebook-trigger">
<img class="logo-img" src="/mma-logo.png">
<span class="trigger-text mma">
Open Mathematica Notebook
</span>
</div>
</div>
Here is the javascript code to handle all the notebooks togglers on a web page.
(function () {
var handles = {}
var currentEmbeddingId = 0
var expandNotebook = function (event) {
var notebook = document.getElementById(id)
var trigger = notebook.querySelector(".mma-notebook-trigger")
var container = document.createElement("div")
container.classList.add("mma-notebook-container")
notebook.appendChild(container)
if (container && notebook.getAttribute("data-expand") == "false") {
var embedding = WolframNotebookEmbedder.embed(
'https://www.wolframcloud.com/obj/' + id,
container,
{
width: container.parentNode.offsetWidth,
maxHeight: 640,
allowInteract: true,
showRenderProgress: true
}
)
handles[currentEmbeddingId] = embedding
embedding.then(function (nb) {
notebook.setAttribute("data-expand", "true")
notebook.setAttribute("data-handle", currentEmbeddingId)
currentEmbeddingId += 1
trigger.removeEventListener("click", expandNotebook)
trigger.addEventListener("click", collapseNotebook)
trigger.lastElementChild.innerHTML = "Close Mathematica Notebook"
})
} else {
console.log("Container with id: " + id + " does not exist.")
}
}
var collapseNotebook = function (event) {
var notebook = document.getElementById(id)
var trigger = notebook.querySelector(".mma-notebook-trigger")
var container = notebook.querySelector(".mma-notebook-container")
if (container && notebook.getAttribute("data-expand") == "true") {
var embedId = parseInt(notebook.getAttribute("data-handle"))
if (handles[embedId]) {
handles[embedId].then((nb) => {
nb.detach()
container.parentNode.removeChild(container)
notebook.setAttribute("data-expand", "false")
trigger.removeEventListener("click", collapseNotebook)
trigger.addEventListener("click", expandNotebook)
trigger.lastElementChild.innerHTML = "Open Mathematica Notebook"
delete handles[embedId]
})
} else {
notebook.querySelectorAll(".mma-notebook-container").forEach((e) => { e.parentNode.removeChild(e) })
trigger.removeEventListener("click", collapseNotebook)
trigger.addEventListener("click", expandNotebook)
trigger.lastElementChild.innerHTML = "Open Mathematica Notebook"
notebook.setAttribute("data-expand", "false")
}
} else {
notebook.setAttribute("data-expand", "false")
}
}
document.addEventListener('DOMContentLoaded', function (event) {
document.querySelectorAll(".mma-notebook-trigger").forEach((e) => {
e.addEventListener("click", expandNotebook)
})
})
})()
Here is the scss code for to make it a little bit more Wolfram-y.
.mma-notebook {
margin-top: 5px;
text-align: center;
.mma-notebook-trigger {
user-select: none;
transition-duration: 0.3s;
transition-property: background-color, color;
transition-timing-function: ease-out;
cursor: pointer;
border-radius: 20px;
border: 0;
padding: 0px 7px 1px 6px;
text-decoration: none;
display: inline-block;
margin-bottom: 5px;
&:hover {
background: #d21c0049;
}
.logo-img {
position: relative;
top: 3.5px;
left: 1px;
width: 15px;
}
.trigger-text {
margin-left: 1.5px;
font-size: 14px;
color: #d21c00;
&:hover {
color: rgb(216, 57, 32);
}
}
}
/* to hide the gray bar */
.mma-notebook-container {
& > div > div:nth-child(2) {
display: none;
}
}
}
Serving static notebook
Wolfram also provides an method for loading static notebook html. It is very easy to use: just replace the url with the form: https://www.wolframcloud.com/statichtml/id. Request the html from the that url and place it at desired place, or simply use iframe. The result will look like this:
More information can be found here.