From ca600401ed7c0d2a6bc1f8f6293be2744210e2c8 Mon Sep 17 00:00:00 2001
From: DarkWiiPlayer
+ Like a normal object, except you can register callbacks for property changes.
+
+ Listener
+ Code Sample:
+
diff --git a/listener.md b/listener.md index 08aee40..ebb11a3 100644 --- a/listener.md +++ b/listener.md @@ -5,53 +5,28 @@ A generator for proxy objects that run callbacks when properties are changed. ## Interface ```js -listener(target={}) -// Creates a new proxy for target +listener() +// Creates a new listener object +listener(some_object) +// Creates a new listener object that acts as a proxy for some_object listener.listen(prop, callback) -// Adds a callback on a property change -listener.listen([prop, ...], callback) -// Adds a callback to several properties at once -listener.listen(prop) -// Removes all callbacks from a given property +// Adds a callback on a specific property change +listener.listen(null, callback) +// Adds a callback on any property change +listener.listen(prop, callback, {once: true}) +// Adds a one-time callback ``` ```js -text(listener, "property") -// Returns a text node bound to listener.property -text(listener) -// Returns a text node proxy for the listener -text(listener).property -// Same as first example +listener.forget(prop, callback) +// Removes a specific callback on a specific property +listener.forget(prop, null) +// Removes all callbacks from a property +// Note that undefined won't work, to avoid accidents +// it really has to be null +listener.forget(null, callback) +// This is not a special case, it simply removes a +// callback that was registered with lisetner.listen(null, callback) ``` -When called with two arguments, this function returns a new text node that will -automatically update to reflect the given property on the listener. - -When called with only the listener, it creates a proxy object that, when -indexed, returns the result of calling `text` on the listener and the indexed -property name. - -Note that repeatedly indexing the proxy will return a new text node each time. - -## Example - -```js -import Listener from 'listener.js' -const listener = Listener({}) - -// Listen for any changed property -listener.listen("*", (value, prop) => console.log(`${prop} changed to ${value}`)) - -// Listen only for changes to the foo property -listener.listen("foo", prop => console.log("it was foo, by the way")) - -// Several listeners for one property are possible -// They will be executed in order of definition -listener.listen("foo", prop => do_something()) - -listener.foo = "New Value" -// Triggers 3 handlers - -listener.bar = "New Value" -// Triggers only the * handler -``` +Note: Forgetting one-time callbacks is not (yet) possible. diff --git a/page/listener.html b/page/listener.html new file mode 100644 index 0000000..954dd69 --- /dev/null +++ b/page/listener.html @@ -0,0 +1,125 @@ + + + + + +
+ Listeners are special proxy objects that can trigger (one or several) callbacks when any of its properties are set. +
+
+ - listener
+ - target ⟶ proxy
+ - nil ⟶ proxy
+
+ + This code uses a listener proxy to represent a User so it can respond whenever the user gets updated. +
+ ++ The proxy object will override the following two properties of the target object: +
listener.listen(<prop>, <callback>)
listener.listen(null, <callback>)
listener.listen(<prop>|null, <callback>, {once: true})
listener.forget(<prop>, <callback>)
listener.forget(<prop>)
listener.forget(null[, <callback>])
+ - callback
+ - new, old, prop ⟶ nil
+ - prop
+ - string
+
+ + Note that callbacks will run regardless of whether the new and old values are actually different. + It is up to the user to compare the new value to the old one and possibly only take action when there is a meaningful difference. +
+ ++ Callbacks are internally stored as a map from property name to a set of callbacks. + Therefore, registering the same callback on the same property more than once will have no effect; + the callback will only be called once for every property change. +
+ +
+ Note that one-time callbacks registered with {once: true}
will generate
+ a new wrapper function that removes itself before calling the actual callback.
+ This has two implications:
+
+ Additionally, the listener
factory itself has the following method:
+
+ - listener.raw
+ - proxy → target
+
+ + Note that callbacks will only trigger when the property is set via the proxy object. + Changing the raw object directly will not trigger any callbacks as javascript provides + no mechanism to detect such property changes on plain objects. +
+