Public
Edited
Nov 24, 2022
37 stars
Insert cell
Insert cell
Insert cell
[{name: "one"}, {name: "and two ..."}, {name: "and three!"}]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
html`<button>OK!</button>`
Insert cell
Insert cell
my_element = {
// The element (only created once, then passed around by reference).
const element = html`<b>I'm here!</b>`;
// An infinite loop.
while(true) {
// Detach the element from whereever in the DOM it currently is.
element.remove();
// Output the element, which attaches it to the DOM.
yield element;
// Wait two seconds.
await Promises.tick(2000);
}
}
Insert cell
Insert cell
{
// Wait a second.
await Promises.tick(1000);
// Detach the element from wherever in the DOM it currently is.
if(remove_element) my_element.remove();
// Output the element, which attaches it to the DOM.
yield my_element;
}
Insert cell
Insert cell
Insert cell
Insert cell
<span class="observablehq--inspect"><span class="observablehq--cellname">my_var = </span><span class="observablehq--string">"my value"</span></span>
Insert cell
Insert cell
Inspector = (await require('@observablehq/inspector')).Inspector
Insert cell
function inspect(value, name = null) {
// Create an empty element to attach the Inspector's HTML to.
const container = html`<div>`;
// Create a new Inspector instance and attach it to the container.
const inspector = new Inspector(container);
// Let the instance know that this is the new value that it should render.
inspector.fulfilled(value, name);

return container;
}
Insert cell
inspect('my value', 'my_name')
Insert cell
Insert cell
my_inspection = inspect('my value', 'my_name')
Insert cell
my_inspection
Insert cell
Insert cell
viewof my_other_inspection = {
// Note that we have to pass in the name manually here.
const element = inspect('my value', 'my_other_inspection');
element.value = 'Hey, that\'s not my value!';
return element;
}
Insert cell
my_other_inspection
Insert cell
Insert cell
Insert cell
Insert cell
viewof my_counter = Inputs.button('Count up')
Insert cell
Insert cell
my_counter
Insert cell
Insert cell
viewof my_counter
Insert cell
Insert cell
viewof my_counter.value
Insert cell
Insert cell
viewof my_2nd_counter = Inputs.button('Count up', {required: true})
Insert cell
viewof my_2nd_counter.value
Insert cell
my_2nd_counter
Insert cell
Insert cell
Insert cell
my_3rd_counter = Inputs.button('Count up')
Insert cell
Generators.input(my_3rd_counter)
Insert cell
Insert cell
viewof my_4th_counter = Inputs.button('Count up')
Insert cell
my_4th_counter
Insert cell
{
const output = html`<output>`;
yield output;
for await(const value of Generators.input(viewof my_4th_counter)) {
output.value = value;
}
}
Insert cell
Insert cell
viewof button_undefined = {
const element = html`<button>Click me!`;
Object.defineProperty(element, 'value', {value: undefined});
return element;
}
Insert cell
Insert cell
button_undefined
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof example_value = Inputs.range([0, 100], {value: 0, step: 1})
Insert cell
viewof filtered_value = {
// Create the view's DOM element. Later on we'll attach the value
// to the <div> element.
const element = html`<div><code><em>Further to the right!`;
// Create an Inspector instance for the element.
const inspector = new Inspector(element);
// Mark the output as "pending" (the gray bar to the left). Note that this will
// only set a class on the element, but *not* replace its contents.
inspector.pending();

// We haven't defined element.value yet, so it's still undefined.
// We'll only set it if our threshold of 50 is passed.
if(example_value >= 50) {
// Set the element's value property. This is what will be seen
// when we reference "filtered_value" (without the viewof prefix).
element.value = example_value;
// Have the inspector show the value. This replaces the element's current
// contents (i.e., the <code> element).
// Note that we must set the cell's name explicitely.
inspector.fulfilled(element.value, 'filtered_value');
}
return element;
}
Insert cell
Insert cell
filtered_value * 2
Insert cell
Insert cell
throbber(['wait', 'w a i t', 'w a i t', 'w a i t'], 500, invalidation)
Insert cell
function throbber(steps, delay, invalidation) {
let step = 0, id;
const text = htl.html`<span style="white-space: pre">`;
const animate = () => {
text.textContent = steps[step++ % steps.length];
id = setTimeout(animate, delay);
};
animate();
invalidation.then(() => clearTimeout(id));
return text;
}
Insert cell
Insert cell
function inspectorPrompt(value, options = {}) {
const {
name,
prompt,
empty = value => value == null,
throbberSteps = ['', '.', '..', '...', ' ..', ' .'],
throbberDelay = 350,
invalidated = invalidation
} = options;

const view = html`<div>`;
const inspector = new Inspector(view);
if(!empty(value)) {
inspector.fulfilled(value, name);
view.value = value;
return view;
}

const placeholder = htl.html`<div style="font: var(--monospace-font); padding: 4px 0">
${prompt}
${throbber(throbberSteps, throbberDelay, invalidated)}
`;

view.appendChild(placeholder);
inspector.pending();
return view;
}
Insert cell
Insert cell
viewof text = Inputs.text({submit: true})
Insert cell
viewof processed = inspectorPrompt(text, {
name: 'processed',
prompt: 'Please enter a value above',
empty: value => value == '',
throbberSteps: ['👆', ' 👆', ' 👆', ' 👆'],
})
Insert cell
processed
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