Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can regular Javascript objects dispatch events or is this only possible for DOM nodes?

Tags:

javascript

dom

I've created a Javascript pseudoclass and I want it to be able to dispatch custom events. Unfortunately, it seems like only DOM nodes are able to dispatch events. So, I'm forced to associate a DOM node with every instance of my pseudoclass, so that the DOM node can dispatch events on behalf of my class.

I'd like to be able to add event listeners directly to instances of my pseudoclass. Unfortunately, because the pseudoclass isn't able to dispatch it's own events, I must add the event listeners to the associated DOM nodes instead.

When I do this, my event handler functions receive a reference to the DOM node instead of the pseudoclass instance. I must then determine which pseudoclass instance the DOM node belongs to, before I can call it's methods.

I'm trying to maintain a clean separation between my Javascript and the DOM, wherever possible. Of course there will be times when it will make sense to associate pseudoclass instances with DOM elements, but I don't want this to be an absolute requirement.

My boilerplate code:

jQuery(document).ready(function($){

    var cat = new Animal($('#cat'), 'Larry', 'Meow');

    cat.domElement.on('spoken', function(event){
        var classInstance = $(this).data('instance');
        console.log(classInstance.firstName + ' has spoken');
    });

    cat.speak();

});

My pseudoclass

(function(){

    window.Animal = Animal;

    function Animal(domElement, firstName, sound) {
        // Save a reference to the DOM node
        this.domElement = domElement;

        // Give the DOM node a reference to this class instance
        this.domElement.data('instance', this);

        this.firstName = firstName;
        this.sound = sound;
    }

    Animal.prototype.speak = function() {
        console.log(this.sound);
        this.domElement.trigger('spoken');
    };

}(window));

Side note: I need to support legacy browsers such as IE8. I tried very hard to use the proper Javascript event model, instead of having to rely on jQuery. Unfortunately, I wasn't able to find adequate polyfills for dispatchEvent, addEventListener, removeEventListener, Event, CustomEvent, etc. jQuery provides an excellent abstraction layer with familiar syntax, and my team uses it regularly anyway. However, please let me know if there's a clean, vanilla Javascript solution!

like image 629
MarkPlewis Avatar asked Oct 21 '22 08:10

MarkPlewis


1 Answers

You can emulate simple event handling relatively easy by yourself:

function Animal(domElement, firstName, sound) {
    this.$$handler = {};
}

Animal.prototype.on = function (eventType, callback) {
    if (!this.$$handler[eventType]) {
        this.$$handler[eventType] = [];
    }
    this.$$handler[eventType].push(callback);
};

Animal.prototype.trigger = function (eventType, args) {
    var i, max_i,
        handler = this.$$handler[eventType];

    if (!handler) {
        return;
    } 
    for (i = 0, max_i = handler.length; i < max_i; i++) {
        handler[i](args);
    }

};

Animal.prototype.speak = function() {
    this.trigger('spoken', {"eventargs": []});
};


//on the instance
cat.on('spoken', function(args){
    var classInstance = $(this).data('instance');
    console.log(classInstance.firstName + ' has spoken');
});
like image 70
basilikum Avatar answered Oct 30 '22 01:10

basilikum