Public
Edited
Dec 11, 2023
Importers
Plot: Quantitative groupsPlot: Coloring lines in wide untidy dataTable with linksClick a button to add to an arrayPlot: Stacked bars with totalsPlot: Click handler render transformSending notifications every week, two weeks, month, etc.See full stack trace with queueMicrotask
Normalize SVG elements to paths
Custom table, click to select rowPlot: Bar chart with label overlayCells, streaming, and side effectsNotes to self on error handlingMasking special namesRecursive Plot subtitlesTiming-safe and and orPlot: Simple render transformFetch CSV from private GitHub repoGeoJSON tableThe two kinds of Plot widthCould Plot.auto make the Simpsons cell heatmap? #1672Plot: Dual axis line chartImport from past versionFacet wrapConvert Plot.auto to explicit marksPlay button and mutationInteractive Plot legendRects in a tableAverage line in faceted plotHorizontal inputsUse Inputs.form with a templateFetch a local file from a notebookConvert JavaScript to Observable JavaScriptHow to respect version locking in an embedded notebookUpdate method on DOM nodeHello, AG GridBeware d3.select on ObservableRe-run cell when checkbox is clickedHow to fix Plot facet labels getting cut offGet JavaScript array from Markdown listInputs.select: Chaining and defaulting to no filterTable with serif fontSetting path length as CSS property variable with D3Read in CSV, define values as undefined/nullUsing a mutable cell to log stuffCombining Inputs with internal interactivity in a chartDrag (SVG), with scaleGive a user a persistent personal key for a notebookSetting @mootari/range-slider from another inputSynchronized slider and dropdownXML to radio button optionsFilter dates from JSONSurprising colors in PlotVega-Lite, JSON and JavaScript APIUse a different render function depending on widthTransition from previous value to new valueDon’t use ordinal scales for datesFormat years stored as numbers without commas in PlotDifferences between htl.html and htl.html.fragmentScrubber await visibilityDifferences between html and htl.htmlWolfram embed demoRe: Get multiple properties from the same object in one array of unique valuesD3 Tube MapRe: How to access data object from a nested arraySynchronized checkboxesGroup all rows by school_type, count and create a percentage of the totalDebug HTML cellsMake an array of PlotsHow to compose generators
Also listed in…
Utilities
Insert cell
Insert cell
svg = htl.svg`<svg style="background: #eeccee;" fill="none" stroke="black">
<polyline points="100,100 150,25 150,75 200,0" />
<polygon points="270,50 240,70 270,30" />
<line x1="140" y1="100" x2="270" y2="140" />
<rect x="20" y="50" width="200" height="20" />
<circle cx="80" cy="70" r="100" />
</svg>`
Insert cell
Insert cell
normalized = normalize(svg)
Insert cell
Insert cell
normalized.outerHTML.replaceAll("<path", "\n <path").replace("</svg>", "\n</svg>")
Insert cell
Insert cell
normalize = svg => {
const node = svg.cloneNode(); // shallow, just to get top-level attributes

for (const polyline of svg.querySelectorAll("polyline")) {
// really similar; just put an M in front of the points
node.appendChild(htl.svg`<path d="M ${polyline.getAttribute("points")}" />`);
}

for (const polygon of svg.querySelectorAll("polygon")) {
// just put an M before and a Z after!
node.appendChild(htl.svg`<path d="M ${polygon.getAttribute("points")} Z" />`);
}

for (const line of svg.querySelectorAll("line")) {
// just bundle up x1,y1 and x2,y2 into an array! the d attribute doesn’t really care about comma between coordinates
const points = ["x1", "y1", "x2", "y2"].map(attr => line.getAttribute(attr));
node.appendChild(htl.svg`<path d="M ${points}" />`);
}

for (const rect of svg.querySelectorAll("rect")) {
// over, down, across, down, back across, up
const [x, y, width, height] = ["x", "y", "width", "height"].map(attr => rect.getAttribute(attr));
node.appendChild(htl.svg`<path d="M ${x} ${y} h ${width} v ${height} h ${-width} z" />`);
}

for (const circle of svg.querySelectorAll("circle")) {
// tricky because drawing an arc from a point to itself collapses to nothing; we draw half a circle across and half a circle back
const [cx, cy, r] = ["cx", "cy", "r"].map(attr => circle.getAttribute(attr));
const x1 = cx - r, y1 = cy;
node.appendChild(htl.svg`<path d="M ${x1} ${y1} a ${r} ${r} 0 1 1 ${2 * r} 0 ${r} ${r} 0 1 1 ${-2 * r} 0 Z" />`);
}

for (const path of svg.querySelectorAll("path")) {
// almost forgot to pass these through too. note im stripping out all other attributes and styles bc that's my use case rn
node.appendChild(htl.svg`<path d="${path.getAttribute("d")}" />`)
}
return node;
}
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