I started to extend the EventTarget
interface by adding some useful prototypes
but then I tested it on Safari 8 and get :
[Error] ReferenceError: Can't find variable: EventTarget
I found on MDN that "window.EventTarget
does not exist" for Safari.
This question looks really interesting but it's about IE8.
So, I want to know if a reference to the EventTarget interface is accessible on Safari, or a workaround to use code like EventTarget.prototype.hasEventListener
and EventTarget.prototype.hasEventListener
without getting any errors on Safari ?
Edit
I found an interesting commit which says that it was implemented the 09/12/15 (from timestamp), but it sure doesn't work in Safari 9.1
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
)
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
}
}