Published
Edited
Apr 20, 2020
Importers
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
async function cache(options) {
const notebookId = safeNotebookName()
if (options && options.inplace) { cacheReadInplace(notebookId) }
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
const runningCellCount = $(".observablehq--running").length + $(".observablehq--changed").length
// console.log("running cells", runningCellCount)
if (runningCellCount == 0) { cacheWrite(notebookId) }
});
});
$(".observablehq").each(function(i,e) { observer.observe(e, { attributeFilter: ['class'] }); })
return "html caching enabled"
}
Insert cell
async function cacheWrite(notebookId) {
// console.log('writing to db')
const allCells = $(".observablehq")
const boundaryCell = allCells.filter(function() {return $(this).text() === "Implementation"}).first()
const boundary = allCells.index(boundaryCell)
const titleCell = allCells.eq(0)
const cells = allCells.slice(1, boundary)
const heights = cells.map(function() { return $(this).height() }).get()
const contentHeight = heights.reduce((a,c)=>a+c)
const elts = cells.map(function() { return this.innerHTML }).get()
const rendered = {
title: titleCell.text(),
contentHeight: contentHeight,
elements: elts,
heights: heights
}
// console.log("rendered", rendered)
db.collection("html-cache").doc(notebookId).set({
title: rendered.title,
contentHeight: rendered.contentHeight,
elements: rendered.elements,
heights: rendered.heights
})
}
Insert cell
async function cacheRead(notebookId) {
const rendered = await renderedNotebook(notebookId)
console.log("reading", notebookId, rendered)
const spacer = $(".observablehq").eq(1)
$(".observablehq h1").eq(0).text(rendered.title + " (static)")
$(".obs-cache-static-render").remove()
rendered.elements.forEach(e => {
spacer.before(
$(`<div dir="auto" class="observablehq obs-cache-static-render" style="margin-bottom: 17px;">${e}</div>`)
)
})
return html`<div style="height: ${rendered.contentHeight+(rendered.elements.length-1)*17}px"></div>`
}
Insert cell
async function cacheReadInplace(notebookId) {
const rendered = await renderedNotebook(notebookId)
if (rendered && rendered.elements && rendered.heights) {
for (let i = 0; i < rendered.elements.length; i++) {
$('.observablehq').eq(i+1).css("height", rendered.heights[i]).html(rendered.elements[i])
}
}
return rendered
}
Insert cell
async function renderedNotebook(notebookId) {
return (await db.collection("html-cache").doc(notebookId).get()).data()
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more