Published
Edited
Nov 16, 2021
Importers
7 stars
Insert cell
Insert cell
Insert cell
Insert cell
viewof parameters1 = multiplexInputs({
a: Inputs.range([0, 10], { label: 'Parameter a' }),
b: Inputs.range([0, 10], { label: 'Parameter b' })
})
Insert cell
parameters1
Insert cell
Insert cell
viewof parameters2 = multiplexInputs(
{
a: Inputs.range([0, 10], { label: 'a' }),
b: Inputs.range([0, 10], { label: 'b' })
},
{ label: 'Parameters', open: true }
)
Insert cell
parameters2
Insert cell
Insert cell
Insert cell
viewof actions = multiplexInputs(
{
action1: Inputs.button('Increment 1'),
action2: Inputs.button('Increment 2')
},
{ inline: true }
)
Insert cell
output1 = {
// If we can ignore action1, then return the existing value
if (actions && viewof actions.canIgnore(this, 'action1')) return this;

// Return the existing value or instantiate a new counter
const returnValue = this ? { value1: this.value1 + 1 } : { value1: 0 };

// Store the state of the actions so we can figure out whether to respond next time…
return viewof actions.cacheState(returnValue);
}
Insert cell
Insert cell
Insert cell
multiplexInputs = {
let serialID = 0;

return function multiplexInputs(
inputs,
{ label = null, open = '', inline = false } = {}
) {
const params = {};
let container;
if (label) {
container = html`<details ${
open ? 'open' : ''
}><summary style="cursor:pointer;">${label}</summary></details>`;
} else {
container = DOM.element('div');
}
function update(e) {
if (e) e.stopPropagation();
for (const [key, input] of Object.entries(inputs)) {
params[key] = input.value;
}
container.dispatchEvent(new CustomEvent('input'));
}
update();
for (const input of Object.values(inputs)) {
const wrapper = DOM.element('div');
if (inline) {
wrapper.style.display = 'inline-block';
wrapper.style.marginRight = '0.5em';
input.style.display = 'inline';
}
container.appendChild(wrapper);
wrapper.appendChild(input);
input.addEventListener('input', update);
}
container.value = params;

const stateKey = `__state${serialID++}`;
Object.defineProperties(container, {
cacheState: {
value: function(object) {
return Object.defineProperty(object, stateKey, {
value: Object.assign({}, this.value),
enumerable: false,
configurable: true
});
}
},
canIgnore: {
value: function(object, properties) {
if (!object || !object[stateKey]) return false;
if (
JSON.stringify(object[stateKey]) === JSON.stringify(container.value)
) {
return false;
}

if (!Array.isArray(properties)) properties = [properties];
for (let property of properties) {
if (object[stateKey][property] !== container.value[property])
return false;
}
container.cacheState(object);
return true;
}
}
});
return container;
};
}
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