PubSub
by onejdc
HTML
<fieldset>
<legend>
Input
</legend>
<button id="btn1" name="btn1">
One Listener
</button>
<button id="btn2" name="btn2">
Second Listener
</button>
<button id="btn3" name="btn3">
Both Listeners
</button>
</fieldset>
<fieldset id='subs'>
<legend>
Subs
</legend>
<div>
<label for="ear1">First Listener:</label><input name="ear1" id="ear1"/>
</div>
<div>
<label for="ear2">Second Listener:</label><input name="ear2" id="ear2"/>
</div>
<div>
<label for="ear3">Third Listener:</label><input name="ear3" id="ear3"/>
</div>
</fieldset>
CSS
button {
padding: 15px;
margin: 15px;
}
#subs {
display:flex;
flex-direction:column;
}
JavaScript
/**
* A basic Publisher Subscriber library
* with topic support
**/
class PubSub {
constructor() {
this.topics = {};
}
// return the topics list as an array
getTopics() {
return Object.keys(this.topics);
}
// send a msg object to all subscribers of the topic(s)
pub(topics,msg) {
// if user gave a single string for topic, convert to array for iteration
if (typeof topics === 'string') {
topics = [topics];
}
topics.forEach(function(topic) {
this.topics[topic].forEach(function(itemObject) {
itemObject.subfn(msg != undefined ? msg : {});
}.bind(this));
}.bind(this));
}
// caller passes in topic and callback
sub(topic, subscriber) {
let appendObject = {id: this.getUUID(), subfn: subscriber};
if (!this.topics.hasOwnProperty(topic)) {
this.topics[topic] = [];
}
//TODO: add error handler to ensure subscriber is a function
this.topics[topic] = [...this.topics[topic], appendObject];
return appendObject.id;
}
// simple unsub
unsub(topic, subscriber) {
if (typeof subscriber === 'undefined') {}
this.topics[topic] = this.topics[topic].filter( sub => sub !== subscriber)
}
// use the subscription ID to remove from the given topic
unsubById(topic,id) {
this.topics[topic] = this.topics[topic].filter( obj => obj.id !== id);
}
/* Small helper function from https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid
*/
getUUID() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
}
/*********** Implementation ***********/
const PS = new PubSub();
class Ex {
constructor(div,type) {
this.input = div;
this.val = 1;
this.type = type;
}
update(data) {
this.val += data.payload;
this.input.value = this.val;
/* if (data.targets.includes(this.type)) {
this.val +=...