Skip to content

Instantly share code, notes, and snippets.

@choegyumin
Last active April 27, 2021 11:07
Show Gist options
  • Save choegyumin/fdd690d609990e695dd6c80ced60a6ee to your computer and use it in GitHub Desktop.
Save choegyumin/fdd690d609990e695dd6c80ced60a6ee to your computer and use it in GitHub Desktop.
Namespacing Event Listener in Vanilla Javascript (:see_no_evil: Monkey Patch)
(function () {
'use strict';
EventTarget.prototype.on = function (event, listener, options) {
if (arguments.length < 2)
throw new TypeError("Failed to execute 'on' on 'EventTarget': 2 arguments required, but only " + arguments.length + " present.");
var typeOfListener = typeof listener;
if (typeOfListener !== 'function' && typeOfListener !== 'object')
throw new TypeError("Failed to execute 'on' on 'EventTarget': The callback provided as parameter 2 is not an object.");
if (!this.hasOwnProperty('listeners'))
Object.defineProperty(this, 'listeners', {
value: [],
configurable: false,
enumerable: true,
writable: false
});
event = String(event).trim();
var eventStruct = event.split('.');
this.listeners.push({event: event, listener: listener});
this.addEventListener(eventStruct[0], listener, options);
return this;
};
EventTarget.prototype.off = function (event, options) {
if (arguments.length < 1)
throw new TypeError("Failed to execute 'off' on 'EventTarget': 1 arguments required, but only " + arguments.length + " present.");
if (!this.hasOwnProperty('listeners')) return this;
event = String(event).trim();
var eventStruct = event.split('.');
var type = eventStruct[0];
var namespace = eventStruct[1];
var isTypeOnly = eventStruct.length === 1;
var isNamespaceOnly = eventStruct.length > 1 && type.length === 0;
var _idx = this.listeners.length;
while (_idx--) {
var _obj = this.listeners[_idx], _event = _obj.event, _listener = _obj.listener;
if (event === _event) {
this.removeEventListener(type, _listener, options);
this.listeners.splice(_idx, 1);
} else if (isTypeOnly || isNamespaceOnly) {
var _eventStruct = _event.split('.'), _type = _eventStruct[0], _namespace = _eventStruct[1];
if (isTypeOnly
? (type !== _type)
: (namespace !== _namespace)) continue;
this.removeEventListener(_type, _listener, options);
this.listeners.splice(_idx, 1);
}
}
return this;
};
})();
@choegyumin
Copy link
Author

choegyumin commented Nov 7, 2018

for Typescript

// index.d.ts

interface EventTarget {
  listeners?: {
    event: string,
    listener: EventListenerOrEventListenerObject
  }[];
  on(event: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): this;
  off(event: string, options?: EventListenerOptions | boolean): this;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment