EventTarget interface in safari
Safari just doesn't allow you to use the EventTarget
interface in your own objects other than DOM elements. So I simply replicated the class to do it.
class EventDispatcher {
constructor() {
this._listeners = [];
}
hasEventListener(type, listener) {
return this._listeners.some(item => item.type === type && item.listener === listener);
}
addEventListener(type, listener) {
if (!this.hasEventListener(type, listener)) {
this._listeners.push({type, listener, options: {once: false}});
}
// console.log(`${this}-listeners:`,this._listeners);
return this
}
removeEventListener(type, listener) {
let index = this._listeners.findIndex(item => item.type === type && item.listener === listener);
if (index >= 0) this._listeners.splice(index, 1);
// console.log(`${this}-listeners:`, this._listeners);
return this;
}
removeEventListeners() {
this._listeners = [];
return this;
}
dispatchEvent(evt) {
this._listeners
.filter(item => item.type === evt.type)
.forEach(item => {
const {type, listener, options: {once}} = item;
listener.call(this, evt);
if (once === true) this.removeEventListener(type, listener)
});
// console.log(`${this}-listeners:`,this._listeners);
return this
}
}
Workaround :
I simply used the Element
interface as a fallback for Safari
var EventTarget = EventTarget || Element;
EventTarget.prototype.addEventListener = function(){/*Some magic here*/};
I also checked that Element inherits prototypes
from the EventTarget interface and it does ! (document.body.addEventListener == EventTarget.prototype.addEventListener
returned true
)