Public
Edited
Aug 11, 2024
Paused
Comments locked
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Object.assign(html`<iframe>`, sandbox ? { sandbox: "" } : {}, {
src: "javascript:'<!DOCTYPE html><p>Hello, World!</p>'",
style: "border: 1px solid;"
})
Insert cell
Insert cell
Insert cell
Insert cell
html`${message?.data || include.srcdoc}`
Insert cell
message?.data
Insert cell
message?.source.location
Insert cell
self.location
Insert cell
Insert cell
viewof svg = embed(
`<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg"><style>@keyframes fade{to{fill:transparent}}@keyframes spin{to{transform:rotateZ(.5turn)}}path{opacity:.75}path:last-of-type{animation:fade 3s .5s cubic-bezier(.35,-.14,.79,1.22) alternate infinite}</style><rect width="256" height="256" fill="#639" rx="50%"/><g style="animation:spin 12s 6s ease-in-out forwards;transform-origin:128px 128px"><path fill="#ff0" d="M128 40 52 172h152Z"/><path fill="red" d="M128 40 52 172l76-44Z"/><path fill="#0f0" d="M128 40v88l76 44Z"/><path fill="#00f" d="m128 128-76 44h152Z"/><path fill="#ff0" d="M128 40 52 172h152Z"/></g></svg>`,
{ loading: "eager" }
)
Insert cell
svg.loading
Insert cell
svg.srcdoc
Insert cell
svg.contentWindow.innerWidth
Insert cell
svg.contentDocument.body.scrollHeight
Insert cell
Insert cell
viewof include = embed`<!DOCTYPE html><p id="${+new Date()}">Hello, <b>World!</b></p>`
Insert cell
include.loading
Insert cell
include.srcdoc
Insert cell
include.contentWindow.location
Insert cell
include.contentWindow.location.href
Insert cell
include.contentWindow.innerWidth
Insert cell
include.contentDocument.body.scrollHeight
Insert cell
Insert cell
mutable message = null
Insert cell
{
const update = (event) => {
if (event.source !== self) return;
mutable message = event;
};

window.addEventListener("message", update, false);

invalidation.then(() => window.removeEventListener("message", update));
}
Insert cell
Insert cell
embed = {
/*!
* Many thanks to Fabian Iwand, Sylvain Lesage, Corey Goldfeder, Mike Pennisi, and Willem van der Veen! - mg
*/
const attr = "srcdoc";
const iframe = Object.assign(html`<iframe>`, {
frameBorder: 0,
sandbox: "allow-same-origin allow-scripts",
width
});
const src = "javascript:self.frameElement.getAttribute('" + attr + "')";
const polyfill = !(attr in iframe) ? { src } : {};

const dom = new DOMParser();
const xml = new XMLSerializer();

const swap = (
(apos) => (m, quote, attr) =>
apos + attr.replace(new RegExp(apos, "g"), quote) + apos
)("'");

return function (srcdoc, { display = true, loading = "lazy" } = {}) {
if (Array.isArray(srcdoc) && srcdoc.raw) {
srcdoc = /* handle tagged template literal */ interpolate(arguments);
}
srcdoc = xml
.serializeToString(
dom.parseFromString(
srcdoc
/* escape ampersands */ .replace(/&(?!amp;)/g, "&amp;")
/* drop comments */ .replace(/<!--[\s\S]*?-->/g, "")
/* drop empty tags */ .replace(/<(\S+)\s*>\s*<[/]\1\s*>/g, ""),
"text/xml"
)
)
.replace(/^\s+/gm, "")
.split(/\n/)
.join("")
.replace(/(")([^"\\]*(?:(?:\1|\\)\1[^"]*)*)\1/g, swap);

const node = Object.assign(
iframe.cloneNode(),
!!display ? {} : { height: 0 }
);

for (const [k, v] of Object.entries(
Object.assign({ loading, srcdoc }, polyfill)
)) {
node.setAttribute.call(node, k, v);
Object.defineProperty(node, k, {
value: /* future-proof!? */ node.getAttribute(k)
});
}

return Object.assign(node, {
value: node,
onload() {
node.contentWindow.parent.postMessage(node.srcdoc);
node.dispatchEvent(new CustomEvent("input"));
}
});
};
}
Insert cell
// @see {@link https://leanpub.com/understandinges6/read#leanpub-auto-tagged-templates}
function interpolate(args) {
/*
* Many thanks to Addy Osmani, Andrea Giammarchi, and Nicholas Zakas! - mg
*/
return args[0].map((x, i) => x + (args[1 + i] || "")).join("");
}
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more