Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EventTarget interface in safari

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

like image 433
PaulCo Avatar asked Apr 17 '16 11:04

PaulCo


People also ask

What is EventTarget?

The EventTarget interface is implemented by objects that can receive events and may have listeners for them. In other words, any target of events implements the three methods associated with this interface.

What is E target JS?

The read-only target property of the Event interface is a reference to the object onto which the event was dispatched. It is different from Event. currentTarget when the event handler is called during the bubbling or capturing phase of the event.

Why is event target undefined?

You're likely getting this error because you're trying to get a name attribute on elements that don't have a name attribute. For example; input, textarea, and form elements are naturally able to get a name attribute. But elements like div, span doesn't.

What will event target refer to inside the event listener?

The target event property returns the element that triggered the event. The target property gets the element on which the event originally occurred, opposed to the currentTarget property, which always refers to the element whose event listener triggered the event.


2 Answers

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
    }
}
like image 162
Jam Zhang Avatar answered Oct 16 '22 14:10

Jam Zhang


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)

like image 23
PaulCo Avatar answered Oct 16 '22 15:10

PaulCo