Published
Edited
Feb 4, 2021
7 forks
Importers
79 stars
Insert cell
Insert cell
viewof x = html`<input type=range>`
Insert cell
x
Insert cell
Insert cell
class View {
constructor(value) {
Object.defineProperties(this, {
_list: {value: [], writable: true},
_value: {value, writable: true}
});
}
get value() {
return this._value;
}
set value(value) {
this._value = value;
this.dispatchEvent(new CustomEvent("input", {detail: value}));
}
addEventListener(type, listener) {
if (type != "input" || this._list.includes(listener)) return;
this._list = [listener].concat(this._list);
}
removeEventListener(type, listener) {
if (type != "input") return;
this._list = this._list.filter(l => l !== listener);
}
dispatchEvent(event) {
const p = Promise.resolve(event);
this._list.forEach(l => p.then(l));
}
bind(input, invalidation) {
return bind(input, this, invalidation);
}
}
Insert cell
Insert cell
viewof y = new View(42)
Insert cell
Insert cell
y
Insert cell
Insert cell
viewof y.bind(html`<input type=range min=0 max=100 step=1>`)
Insert cell
Insert cell
viewof y.bind(html`<input type=range min=0 max=100 step=1>`)
Insert cell
viewof y.bind(html`<input type=number min=0 max=100 step=1>`)
Insert cell
y
Insert cell
Insert cell
viewof name = new View("fred")
Insert cell
viewof name.bind(html`<input type=text>`)
Insert cell
viewof name.bind(html`<input type=text>`)
Insert cell
name
Insert cell
viewof toggled = new View(true)
Insert cell
viewof toggled.bind(html`<input type=checkbox>`)
Insert cell
viewof toggled.bind(html`<input type=checkbox>`)
Insert cell
toggled
Insert cell
Insert cell
function bind(input, view, invalidation = disposal(input)) {
set(input, view.value);
input[`on${eventof(input)}`] = () => view.value = get(input);
const update = ({detail: value}) => get(input) === value || set(input, value);
view.addEventListener("input", update);
invalidation.then(() => view.removeEventListener("input", update));
return input;
}
Insert cell
function get(input) {
switch (input.type) {
case "range":
case "number": return input.valueAsNumber;
case "date": return input.valueAsDate;
case "checkbox": return input.checked;
case "file": return input.multiple ? input.files : input.files[0];
default: return input.value;
}
}
Insert cell
function set(input, value) {
switch (input.type) {
case "range":
case "number": input.valueAsNumber = value; break;
case "date": input.valueAsDate = value; break;
case "checkbox": input.checked = value; break;
case "file": input.multiple ? (input.files = value) : (input.files = [value]); break;
default: input.value = value;
}
}
Insert cell
function eventof(input) {
switch (input.type) {
case "button":
case "submit": return "click";
case "file": return "change";
default: return "input";
}
}
Insert cell
import {disposal} from "@mbostock/disposal"
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