/** * A class to use in notebooks where you want to hold state that is modified by user actions. * * E.g. * * mySetting = new SettingView('abc'); * * html`${mySetting.value}` * * toggleBtn = { * var btn = DOM.element('button') * * btn.addEventListener('click', () => (viewof mySetting).value = 'def'); * return btn * } * * Clicking on toggleBtn will change the displayed html to 'def' * * See https://beta.observablehq.com/@mbostock/synchronized-views */ class SettingView { 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({type: "input", 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)); } }