Skip to content

Instantly share code, notes, and snippets.

@shimondoodkin
Forked from anonymous/ObserverPubSub.js
Last active December 10, 2015 02:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shimondoodkin/4369108 to your computer and use it in GitHub Desktop.
Save shimondoodkin/4369108 to your computer and use it in GitHub Desktop.
//licence: 2 clouse mit, by Shimon Doodkin
function ObserverPubSub(parent, key_of_myself) {
this._topics = {};
this.length = 0;
this._subUid = -1;
this._parent = parent;
this._name = key_of_myself;
}
ObserverPubSub.prototype = {
//pubsub
on: function(topic, func, token) {
var topics = this._topics;
if (!topics[topic]) {
topics[topic] = [];
}
if (arguments.length == 2) token = (++this._subUid).toString();
topics[topic].push({
token: token,
func: func
});
return token;
},
emit: function(topic) {
var topics = this._topics,
args = arguments;
if (!topics[topic]) {
return false;
}
setTimeout(function() {
var subscribers = topics[topic],
len = subscribers ? subscribers.length : 0;
while (len--) {
subscribers[len].func.apply(this, args);
}
}, 0);
return true;
},
unsub: function(token) {
var topics = this._topics;
for (var m in topics) {
if (topics[m]) {
for (var i = 0, j = topics[m].length; i < j; i++) {
if (topics[m][i].token === token) {
topics[m].splice(i, 1);
if (topics[m].length == 0) delete topics[m];
return token;
}
}
}
}
return false;
},
//observer
emit_recursive: function() {
this.emit.apply(this, arguments)
if (this._parent) this._parent.emit.apply(this._parent, arguments)
},
add: function(k, v) {
var objv = new ObserverPubSub(this, k);
this[k] = objv;
objv._set(v);
this.emit('add', k, v);
if (this._parent) this._parent.emit_recursive('childadd', this, this._name);
return k;
},
_remove: function(k) {
var deleted=this[k];
if(typeof k=='string')
{
delete this[k];
}
else
{
if(k<0) throw new Error('bad index to remove');
var deleted=this[k];
for(var i=k,l=this.length-1;i<this.length;i++)
{
this[i]=this[i+1]
}
delete this[i+1];
this.length--;
}
if(deleted instanceof ObserverPubSub) deleted.emit('remove', k, deleted);
return deleted;
},
indexOf: function(o) {
var k=-1;
for(var i=0,l=this.length;i<l;i++)
{
if(this[i]===o)k=i; break;
}
return k;
},
free(){// useless fn
for(var i=this.length-1;i>0;i--)
{
if(this[i] instanceof ObserverPubSub) this.remove(i);
}
/*
if(this._value)delete this._value;
for(var i=0,l=this.length;i<l;i++)
{
if(this[i] instanceof ObserverPubSub) this[i].remove();
delete this[i]
//delete this[i]._parent
//delete this[i]._name
}
var topics = this._topics;
for (var m in topics) {
if (topics[m]) {
for (var i = 0, j = topics[m].length; i < j; i++) {
delete topics[m]
}
}
delete topics[m];
}
delete this._topics;
delete this.length;
delete this._subUid;
delete this._parent;
delete this._name;*/
},
remove: function(k,free) {
free=free!==undefined?free:true;
if(k===true||k===false){free=k;k=undefined;}
if(k !== undefined)
{
var deleted;
deleted=this._remove(k);
deleted.emit('remove', k, deleted);
var from_Parent=this;
this.emit_recursive('childremove', deleted, k, from_Parent);
this.emit('change'); //watch this later
//this.emit('change', k, v);
if (this._parent) this._parent.emit_recursive('childchange', this, this._name);
if(free)if(deleted instanceof ObserverPubSub) deleted.free();
return deleted;
}
else
{
if(this._parent){ return _parent.remove(this._name);}
else { if(free)this.free();)}
}
},
push: function(v) {
var k = this.length++;
this.add(k, v);
this.emit('length', this.length);
return k;
},
_set: function(k, v) {
var isnew = this[k] === undefined;
if (arguments.length == 1) {
v = k;
k = '_value';
}
if (this[k] instanceof ObserverPubSub) return this[k].set(v);
this[k] = v;
this.emit('set', k, v);
if (this._parent) this._parent.emit_recursive('childset', this, this._name);
return isnew;
},
set: function(k, v) {
if (!this._set.apply(this, arguments)) {
this.emit('change', k, v);
if (this._parent) this._parent.emit_recursive('childchange', this, this._name);
}
},
get: function(k) {
if (arguments.length == 0) return this['_value'];
return this[k];
},
toArray: function() {
var arr=[];
for (var i = 0, j = this.length; i < j; i++) {
arr[i]=this[i];
}
return arr;
}
};
//var arr= new ObserverPubSub();
//pubsub:
//var token=arr.on('foo',function(){})//token='0'
//arr._topics
//arr.unsub('0')
//arr.on('set',function(eventname,key,value){console.log(eventname,key,value)})
//arr.on('add',function(eventname,key,value){console.log(eventname,key,value)})
//arr.on('change',function(eventname,key,value){console.log(eventname,key,value)})
//arr.on('length',function(eventname,key,value){console.log(eventname,key,value)})
//arr.on('childset',function(eventname,key,value){console.log(eventname,key,value)})
//arr.on('childadd',function(eventname,key,value){console.log(eventname,key,value)})
//arr.on('childremove',function(eventname,key,value){console.log(eventname,key,value)})
//arr.on('remove',function(eventname,key,value){console.log(eventname,key,value)})
//arr.on('childchange',function(eventname,key,value){console.log(eventname,key,value)})
//observer:
//arr.add('key',"value");
//arr.set('key',"value");
//arr.push("value");//add with key=length,length++
//arr.get('key');
//arr.get(); // key='_value'
//arr.set("value"); // key='_value'
//arr.remove(); // emit remove this and remove this from parent,also delete children
//arr.remove("value"); // remove a child ,also delete its children
//arr.remove(false); // emit remove this and remove this from parent,dont delete child children
//arr.remove("value",false); // remove a child ,dont delete its children
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment