Last active
May 13, 2017 09:43
-
-
Save w3core/8274e90d81a2720f93db11f1bac676a3 to your computer and use it in GitHub Desktop.
This file contains 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
/* Lightweight ultrafast and powerful EventEmitter that built on the native JavaScript emitter. | |
* | |
* @param this (Object) An optional parameter that allows to extend any object | |
* @returns Object (EventBus|this) | |
*/ | |
function EventBus (that) { | |
var that = that || this, | |
id = (new Date).getTime() + "" + Math.random(), | |
node = document.createElement("EventBus"), | |
recent = {}; | |
that.on = on; | |
that.off = off; | |
that.emit = emit; | |
/* | |
* The method registers the specified listener on single or multiple space or comma separated events. | |
* Multiple calls passing the same combination of event and listener will not result in the listener being added. | |
* Any event that passed as argument can contain any combination of pseudo-prefixes `:ready` and/or `:once`. | |
* `:ready` - Indicates that the listener should be called even if the event has been emitted before the listener was added. | |
* `:once` - Indicates that the listener should be unsubscribed at once event will emitted. | |
* | |
* @param event (String) Single or multiple space or comma separated events that can contain of pseudo-prefixes `:ready` and/or `:once` | |
* @param listener (Function) The function that receives a notification when an event of the specified type occurs | |
* @returns (EventBus|this) | |
*/ | |
function on (event, handler) { | |
var event = unify(event); | |
if (typeof event == "string" && typeof handler == "function") { | |
var event = event.replace(/(([\w._\-~\[\]$#&^]+)(:ready|:once)(:ready|:once)?)/ig, function ($0, $1, $e, $3, $4) { | |
var ready = /:ready/i.test($3 + $4), | |
once = /:once/i.test($3 + $4), | |
last = recent[$e], | |
done; | |
if (!once) listener("on", $e, node, handler, false); | |
if (ready && last) { | |
if (once) done = true; | |
setTimeout(function(){handler(last)}, 0); | |
} | |
if (once && !done) { | |
var fn = function (e) { | |
listener("off", $e, node, fn, false); | |
handler(e); | |
}; | |
listener("on", $e, node, fn, false); | |
} | |
return ""; | |
}); | |
listener("on", cleanPseudo(event), node, handler, false); | |
} | |
return that; | |
} | |
/* | |
* The method removes single or multiple space or comma separated events listener previously registered with EventBus.on(). | |
* | |
* @param event (String) Single or multiple space or comma separated events | |
* @param listener (Function) The function that receives a notification when an event of the specified type occurs | |
* @returns (EventBus|this) | |
*/ | |
function off (event, handler) { | |
var event = unify(cleanPseudo(event)); | |
if (!event) return that; | |
listener("off", event, node, handler, false); | |
return that; | |
} | |
/* | |
* Asynchronously calls each of the listeners registered for the event named eventName, passing the supplied data to each. | |
* | |
* @param event (String) Single event name | |
* @param data (Object) An optional data object | |
* @param target (Any) Event.target | |
* @param preventDefault (Function) Event.preventDefault handler | |
* @param stopPropagation (Function) Event.stopPropagation handler | |
* @returns (EventBus|this) | |
*/ | |
function emit (event, data, target, preventDefault, stopPropagation) { | |
var event = unify(cleanPseudo(event)); | |
if (!event) return that; | |
recent[event] = dispatch(node, event, data, target, preventDefault, stopPropagation); | |
return that; | |
} | |
function unify (event) { | |
if (event && typeof event == "string") return event.toLowerCase(); | |
} | |
function cleanPseudo (events) { | |
return typeof events == "string" ? events.replace(/:ready|:once/ig, '') : events; | |
} | |
function eventHandlerStatus (handler, event, status) { | |
if (!handler[id]) handler[id] = {}; | |
if (typeof status == "boolean") handler[id][event] = status; | |
return !!handler[id][event]; | |
} | |
function listener (type, event, node, fn, sign) { | |
if (typeof type != "string" || typeof event != "string" || !event.length || !node || typeof fn != "function") return; | |
if (typeof node == "object" && typeof node.length == "number" && !node.nodeName && node != window) { | |
for (var i=0; i<node.length; i++) listener(type, event, node[i], fn, sign); | |
return; | |
} | |
var add = !!(type == "on"); | |
var method = add ? "addEventListener" : "removeEventListener"; | |
var e = event.replace(/^\s+|\s+$/img, '').split(/[ ,]+/); | |
if (e.length == 1) { | |
if (e[0].length) { | |
var status = eventHandlerStatus(fn, e[0]); | |
if ((add && !status) || !add) { | |
node[method](e[0], fn, !!sign); | |
eventHandlerStatus(fn, e[0], add); | |
} | |
} | |
return; | |
} | |
for(var i=0; i<e.length; i++) listener(type, e[i], node, fn, sign); | |
} | |
function dispatch (node, event, data, target, prevent, stop) { | |
var e = document.createEvent("HTMLEvents"); | |
var _prevent = e.preventDefault; | |
var _stop = e.stopImmediatePropagation; | |
function stopPropagation () { | |
e.propagationStopped = true; | |
_stop.call(e); | |
if (typeof stop == "function") stop(e); | |
} | |
function preventDefault () { | |
_prevent.call(e); | |
if (typeof prevent == "function") prevent(e); | |
return false; | |
} | |
e.data = data; | |
if (target) { | |
var descriptor = {value: target}; | |
Object.defineProperties(e, { | |
target: descriptor, | |
currentTarget: descriptor, | |
srcElement: descriptor | |
}); | |
} | |
e.preventDefault = preventDefault; | |
e.stopPropagation = stopPropagation; | |
e.stopImmediatePropagation = stopPropagation; | |
e.initEvent(event, true, true); | |
node.dispatchEvent(e); | |
return e; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Reference API
Usage