Skip to content

Instantly share code, notes, and snippets.

@dfkaye
Created August 5, 2023 05:01
Show Gist options
  • Save dfkaye/f773b85fabf661108ed4ff7a2cdfc61d to your computer and use it in GitHub Desktop.
Save dfkaye/f773b85fabf661108ed4ff7a2cdfc61d to your computer and use it in GitHub Desktop.
Control is a constructor with an EventTarget field that manages events and listeners of different types (so we don't have to).
// 4 August 2023
// control.target.js
// Control is a constructor with an EventTarget field that manages events and
// listeners of different types (so we don't have to).
// Compare with control.signal.js at https://gist.github.com/dfkaye/8701a2d416556aab68da7519b2c5429a
// Prototype adds decorator API for adding, removing, and dispatching events.
// Dispatches CustomEvents containing `detail` as { data, source } where `data`
// is the param passed to dispatch() and `source` points back to the control
// instance.
function Control(data) {
console.log(data);
return Object.assign(Object.create(CP), {
target: new EventTarget,
data: Object(data)
});
}
var CP = Control.prototype;
CP.addListener = function (name, fn) {
this.target.addEventListener(name, fn);
}
CP.removeListener = function (name, fn) {
this.target.removeEventListener(name, fn);
}
CP.dispatch = function (name, data) {
var event = new CustomEvent(name, { detail: { data, source: this } });
this.target.dispatchEvent(event);
}
/* test it out */
/* constructors */
Control({name: 'test'});
// Object { name: "test" }
Control(['a', 'b', 'c']);
// Array(3) [ "a", "b", "c" ]
Control(9);
// 9
Control(new Set([1,2,3]));
// Set []
Control(new Map([
['a', 'x']
]));
// Map(0)
/* instance */
var c = Control('x');
// Object { target: EventTarget, data: "x" }
/* no 'a' listener yet */
console.log('****');
c.dispatch('a', { value: "won't dispatch this"});
console.log('****');
/* add an 'a' listener */
c.addListener('a', function (e) {
console.group("a");
console.log(e.detail.data);
console.log(e.detail.source);
console.groupEnd("a");
});
c.dispatch('a', { value: "retest"});
// a
// Object { value: "retest" }
// Object { target: EventTarget, data: "x" }
/* add another 'a' listener */
c.addListener('a', function (e) {
console.group("another 'a'");
console.log(e.detail.data);
console.log(e.detail.source);
console.groupEnd("another 'a'");
});
c.dispatch('a', { value: "again"});
// a
// Object { value: "retest" }
// Object { target: EventTarget, data: "x" }
// another 'a'
// Object { value: "again" }
// Object { target: EventTarget, data: "x" }
/* use event data and source values together */
var d = Control(12);
d.addListener('inspect', function (e) {
console.group("inspect");
console.log("send", e.detail.data.value);
console.log("read ", +e.detail.source.data);
console.log("adds up to", e.detail.data.value + e.detail.source.data);
console.groupEnd("inspect");
});
d.dispatch('inspect', { value: 34});
// inspect
// send 34
// read 12
// adds up to 46
/* extend the prototype with an add utility */
CP.add = function (n) {
this.dispatch("add", { n, plus: this.data, sum: n + this.data })
};
var s = Control(12);
// 12
s.addListener('add', function (e) {
console.group("add");
console.log("n:", e.detail.data.n);
console.log("plus:", e.detail.data.plus);
console.log("sum:", e.detail.data.sum);
console.groupEnd("add");
});
s.add(1000);
// add
// n: 1000
// plus: 12
// sum: 1012
/* supports the handleEvent approach */
var h = Control(100);
h.addListener('add', {
handleEvent(e) {
console.group("handleEvent");
console.log("n:", e.detail.data.n);
console.log("plus:", e.detail.data.plus);
console.log("sum:", e.detail.data.sum);
console.log("value from listener:", this.value);
console.log("all together:", e.detail.data.sum + this.value);
console.groupEnd("handleEvent");
},
value: 1234
});
h.add(9876);
// handleEvent
// n: 9876
// plus: Number { 100 }
// sum: 9976
// value from listener: 1234
// all together: 11210
/* handleEvent when handler object is also a function */
var j = Control(9);
var H = function (e) {
console.group("handleEvent attached to a function");
console.assert(e.detail.data.action === "A", "data.action");
console.assert(e.detail.data.value === "V", "data.value");
console.assert(!('value' in this), "should not have this.value");
console.log(e.detail.data.action, e.detail.data.value, H.value);
console.groupEnd("handleEvent attached to a function");
};
H.handleEvent = function (e) {
throw new Error("should not call handleEvent", H);
};
H.value = "H";
j.addListener('what', H);
j.dispatch("what", { action: "A", value: "V" });
// handleEvent attached to a function
// A V H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment