Created
August 5, 2023 05:01
-
-
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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