From 6b97387630cedb2ef098659d65e77b1c790d62a0 Mon Sep 17 00:00:00 2001 From: Ruben Beltran del Rio Date: Wed, 8 May 2024 13:50:45 +0200 Subject: Make node components event emitters --- lib/serpentity/node_collection.js | 4 +++- lib/serpentity/observable.js | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 lib/serpentity/observable.js (limited to 'lib') diff --git a/lib/serpentity/node_collection.js b/lib/serpentity/node_collection.js index d2aa599..cb2f932 100644 --- a/lib/serpentity/node_collection.js +++ b/lib/serpentity/node_collection.js @@ -1,3 +1,5 @@ +import { makeObservable } from './observable.js'; + /* * Node Collections contain nodes, in order to keep the lists of nodes * that belong to each type. @@ -35,7 +37,7 @@ export class NodeCollection extends EventTarget { node.entity = entity; for (const typeName of typeNames) { - node[typeName] = entity.getComponent(types[typeName]); + node[typeName] = makeObservable(entity.getComponent(types[typeName])); } this.nodes.push(node); diff --git a/lib/serpentity/observable.js b/lib/serpentity/observable.js new file mode 100644 index 0000000..a75377d --- /dev/null +++ b/lib/serpentity/observable.js @@ -0,0 +1,38 @@ +/* + * Observable wrapper. Wraps objects so any property modifications emit + * a change event. Used internally for node collections, which make the + * components observable. + */ +class ObserverHandler extends EventTarget { + #emitChangeEvent({property, to, from}) { + const event = new Event('change'); + event.property = property; + event.to = to; + event.from = from; + this.dispatchEvent(event); + } + + get(target, property) { + if (property in this && typeof this[property] === 'function') { + return this[property].bind(this); + } + + return target[property] + } + + set(target, property, value) { + const oldValue = target[property]; + target[property] = value; + this.#emitChangeEvent({property, to: value, from: oldValue}); + return true; + } +} + +/** + * @param {Object} object the object to observe + * @return {tObserverProxy} the proxied object + */ +export function makeObservable(object) { + + return new Proxy(object, new ObserverHandler()); +}; -- cgit