Public
Edited
Jun 15
Importers
28 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
fmt`c = ${299792458} m/s`
Insert cell
Insert cell
viewof c = fmt`c = ${299792458} m/s`
Insert cell
c
Insert cell
Insert cell
Insert cell
Insert cell
fmt`ρ = ${2700} kg/m³`
Insert cell
Insert cell
fmt`ρ = ${2700} ${tex`\mathrm{kg / m^3}`}`
Insert cell
Insert cell
Insert cell
fmt`object = ${{ foo: 'bar' }}`
Insert cell
Insert cell
fmt`boolean = ${true} ${{ foo: 'bar' }}`
Insert cell
Insert cell
Insert cell
fmt`area = ${tex`\displaystyle \int_0^\pi \sin x\,dx`} = ${2}`
Insert cell
Insert cell
viewof n = fmt`n = ${Tangle({ min: 0, max: 100, value: 48 })} cookies`
Insert cell
n
Insert cell
Insert cell
Insert cell
fmt(x => x.toExponential(2))`E = ${70e9} Pa`
Insert cell
fmt('.2e')`E = ${70e9} Pa`
Insert cell
Insert cell
fmt(sci())`E = ${70e9} Pa`
Insert cell
fmt(sci('.3f'))`E = ${70e9} Pa`
Insert cell
Insert cell
myFormatter = fmt(sci('.3f'))
Insert cell
myFormatter`E = ${70e9} Pa`
Insert cell
myFormatter('~f')`E = ${70e9} Pa`
Insert cell
Insert cell
Insert cell
Insert cell
fmt = {
// Create and extract the .observablehq--inspect element of an inspector
function bareInspector(value) {
const el = DOM.element("div");
new Inspector.Inspector(el).fulfilled(value);
const inspectSpan = el.querySelector(".observablehq--inspect");
if (inspectSpan) {
inspectSpan.parentElement.removeChild(inspectSpan);
}
return inspectSpan;
}

function constructOutput(format, strings) {
const id = `inspector-${Math.floor(1e9 * Math.random())}`;
let assignment = "";
const lhs = [];
const rhs = [];

// Locate the first non-HTML element
let valueIdx = Infinity;
for (let i = 2; i < arguments.length; i++) {
if (!isElement(arguments[i])) {
valueIdx = i;
break;
}
}

// No non-HTML value was found, at least try the first component with a `value` property
if (valueIdx === Infinity) {
for (let i = 2; i < arguments.length; i++) {
if (arguments[i].value !== undefined) {
valueIdx = i;
break;
}
}
}

// Otherwise just take the first html element
if (valueIdx === Infinity) {
valueIdx = 2;
}

let dst, klass, color;
const value = arguments[valueIdx];
let isNumber = format && typeof value === "number";

for (var i = 0; i < strings.length; i++) {
dst = i < valueIdx - 1 ? lhs : rhs;
klass = i < valueIdx - 1 ? "cellname" : "number";

// Swap for alternate coloring...
color = "";
//color = klass === 'number' ? 'style="color:#767676"' : '';

// Push the string, wrapped in cellname (lhs) or number (rhs)
dst.push(
html`<span class="observablehq--${klass}" ${color}>${strings[i]}</span>`
);

// Process expression arguments
// Is this expression the value?
if (i === valueIdx - 2 && i < arguments.length - 2) {
if (isNumber) {
const str = format
? (typeof format === "string" ? d3format(format) : format)(value)
: value;
dst.push(html`<span class="observablehq--number">${str}</span>`);
} else {
const inspector = bareInspector(value);
if (inspector) {
inspector.setAttribute("id", id);
inspector.style.display = "inline";
dst.push(inspector);
} else if (isElement(value)) {
const wrapper = document.createElement("div");
wrapper.className = "observablehq--number";
wrapper.style.display = "inline-block";
wrapper.appendChild(value);
dst.push(wrapper);
} else {
dst.push(value);
}
}
} else if (i < arguments.length - 2) {
// If it's not the value, it's just a stray rhs expression
dst.push(
html`<span class="observablehq--${klass}" ${color}>${
arguments[i + 2]
}</span>`
);
}
}

// Force this inspector to remain inline ?!?!
const css = html`<style>#${id} > .observablehq--inspect { display: inline !important }</style>`;

// Build the final output!
const el = html`<span class="observablehq--inspect fmt-inspector" id="${id}">${lhs}${rhs}</span>${css}`;

if (isElement(value)) {
value.addEventListener("input", (event) => {
el.value = value.value;
el.dispatchEvent(new CustomEvent("input"));
});
el.value = value.value;
} else {
el.value = value;
}

return el;
}

// Return a function that is either a tagged template *or* receives
// format and returns a tagged template.
const returnValue = function fmt(format = null) {
if (Array.isArray(arguments[0])) {
// In this case, strings were provided, proceed to templating
const args = [null];
for (let i = 0; i < arguments.length; i++) args.push(arguments[i]);
return constructOutput.apply(null, args);
} else {
// In this case, the first argument is a format
return function () {
// So that you may back up and override the formatting after the fact.
// This is useful for creating a helper which provides an overridable
// default.
if (!Array.isArray(arguments[0])) return fmt(arguments[0]);

// Otherwise, use the default and evaluate
const args = [format];
for (let i = 0; i < arguments.length; i++) args.push(arguments[i]);
return constructOutput.apply(null, args);
};
}
};

returnValue.sci = sci;

return returnValue;
}
Insert cell
Insert cell
Insert cell
Insert cell
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