Skip to content

Instantly share code, notes, and snippets.

@wiky
Last active December 17, 2015 12:29
Show Gist options
  • Save wiky/5610020 to your computer and use it in GitHub Desktop.
Save wiky/5610020 to your computer and use it in GitHub Desktop.
(function(exports) {
var idCounter = 0,
PREFIX = '_',
PREFIX_REG_EXP = new RegExp('^' + PREFIX + '+');
var uniqueId = function(prefix) {
var id = ++idCounter + '';
return prefix ? prefix + id : id;
};
var Event = {
on: function(events, callback, context) {
var src, uid, evt, tail, name;
this._events = this._events || {};
events = events.split(/\s+/);
while ((evt = events.shift())) {
evt = evt.replace(/^:+|:+$/g, '').replace(/:+/g, ':');
src = evt;
evt = evt.split(':');
if (typeof callback === 'function') {
uid = uniqueId(PREFIX);
tail = this._events;
while (typeof(name = evt.shift()) !== 'undefined') {
name = name.replace(PREFIX_REG_EXP, '');
if (name) {
tail[name] = tail[name] || {};
tail[name][uid] = {
_by: src,
fn: callback,
ctx: context || this
};
tail = tail[name];
} else {
continue;
}
}
}
}
return this;
},
off: function(events, callback) {
var evt, tail, name, src, k, last,
offNames = {};
if (!events) {
this._events = {};
return this;
}
this._events = this._events || {};
events = events.split(/\s+/);
while ((evt = events.shift())) {
evt = evt.replace(/^:+|:+$/g, '').replace(/:+/g, ':');
src = evt;
evt = evt.split(':');
tail = this._events;
head = tail[evt.shift()];
for (k in head) {
if (head.hasOwnProperty(k) && k.match(PREFIX_REG_EXP)) {
if (typeof callback === 'function') {
if (head[k].fn === callback && head[k]._by.indexOf(src + ':') === 0) {
offNames[k] = head[k]._by.split(':');
}
} else {
if (head[k]._by.indexOf(src) === 0) {
offNames[k] = head[k]._by.split(':');
}
}
}
}
for (k in offNames) {
if (offNames.hasOwnProperty(k)) {
tail = this._events;
last = offNames[k].pop();
while ((name = offNames[k].shift())) {
if (tail[name]) {
delete tail[name][k];
}
tail = tail[name];
}
if (tail) {
delete tail[last];
}
}
}
}
return this;
},
fire: function(events) {
var args = [].slice.call(arguments, 1),
contains = function(a, b) {
return a === b || a.indexOf(b + ':') === 0;
},
evt, tail, name, src, by, k;
this._events = this._events || {};
events = events.split(/\s+/);
while ((evt = events.shift())) {
evt = evt.replace(/^:+|:+$/g, '').replace(/:+/g, ':');
src = evt;
evt = evt.split(':');
tail = this._events;
while (typeof(name = evt.shift()) !== 'undefined') {
tail = (tail && tail[name]) || tail;
}
for (k in tail) {
if (tail.hasOwnProperty(k) && k.match(PREFIX_REG_EXP)) {
by = tail[k]._by;
if (contains(by, src) || contains(src, by)) {
tail[k].fn.apply(tail[k].ctx, args.concat({
type: src,
current: by
}));
}
}
}
}
return this;
}
};
exports.Event = Event;
})(this);
// for test
var Event = this.Event;
var fn = function() {
console.log(arguments);
};
Event.on('a:bb:ccc', fn);
Event.on('a:bb:ddd', function() {
console.log(arguments);
});
Event.on('a:bb:eee', fn);
Event.on('a:bb:eee:ffff', function() {
console.log(arguments);
});
Event.on('a:bb:eee:gggg', fn);
Event.on('a:xxx:yyy', fn);
Event.on('a:b:c', function() {
console.log(arguments);
});
Event.fire('a:bb:eee:ffff');
console.log(Event._events);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment