How to add an EventListener to non-DOM elements in Javascript?

In Java, C #, Actionscript, etc. Events are for classes, while in Javascript it seems to be limited to dom. I read a sample here in order to do this with jQuery http://www.west-wind.com/weblog/posts/2010/May/27/NonDom-Element-Event-Binding-with-jQuery

but if I don't need jQuery and if I want to understand the mechanism, how would you do it?

+7
source share
2 answers

in the simplest mechanism, it's something like:

function PubSub() { this.subs = {}; this.subscribe = function(channel, sub) { this.subs[channel] = this.subs[channel] || []; //create array for channel this.subs[channel].push(sub); }; this.publish = function(channel) { var args = [].slice.call(arguments, 1); //pop off channel argument this.subs[channel].forEach(function(sub) { sub.apply(void 0, args); //call each method listening on the channel }); }; } 

Demo here: http://jsfiddle.net/3PNtR/

- EDIT (~ 5 years later) -

same simple mechanism, new syntax

 class PubSub { constructor () { this.subs = {} } subscribe (channel, sub) { this.subs[channel] = this.subs[channel] || [] this.subs[channel].push(sub) } publish (channel, ...args) { ;(this.subs[channel] || []).forEach(sub => sub(...args)) } } 
+3
source

There are at least two ways to achieve this:

- If you are a jQuery user (currently I am not), you can wrap your simple JavaScript object using jQuery and then, as DOM elements, it will be able to listen to events. This method already has an answer here . I'm not sure how this method works under the hood, I plan to study it later, and you can explore it yourself.

- Using VanillaJS, you can achieve the same effect by creating an eventful class from which all objects that want to interact will be created and created. Then all instances of this class will be able to register, emit and broadcast the event. Borrowing the semantics from the DOM API and AngularJS, I wrote an example demonstrating how this can be done and how it can be used. There he is:

 /** * EventfulObject constructor/base. * @type EventfulObject_L7.EventfulObjectConstructor|Function */ var EventfulObject = function() { /** * Map from event name to a list of subscribers. * @type Object */ var event = {}; /** * List of all instances of the EventfulObject type. * @type Array */ var instances = []; /** * @returns {EventfulObject_L1.EventfulObjectConstructor} An `EventfulObject`. */ var EventfulObjectConstructor = function() { instances.push(this); }; EventfulObjectConstructor.prototype = { /** * Broadcasts an event of the given name. * All instances that wish to receive a broadcast must implement the `receiveBroadcast` method, the event that is being broadcast will be passed to the implementation. * @param {String} name Event name. * @returns {undefined} */ broadcast: function(name) { instances.forEach(function(instance) { (instance.hasOwnProperty("receiveBroadcast") && typeof instance["receiveBroadcast"] === "function") && instance["receiveBroadcast"](name); }); }, /** * Emits an event of the given name only to instances that are subscribed to it. * @param {String} name Event name. * @returns {undefined} */ emit: function(name) { event.hasOwnProperty(name) && event[name].forEach(function(subscription) { subscription.process.call(subscription.context); }); }, /** * Registers the given action as a listener to the named event. * This method will first create an event identified by the given name if one does not exist already. * @param {String} name Event name. * @param {Function} action Listener. * @returns {Function} A deregistration function for this listener. */ on: function(name, action) { event.hasOwnProperty(name) || (event[name] = []); event[name].push({ context: this, process: action }); var subscriptionIndex = event[name].length - 1; return function() { event[name].splice(subscriptionIndex, 1); }; } }; return EventfulObjectConstructor; }(); var Model = function(id) { EventfulObject.call(this); this.id = id; this.receiveBroadcast = function(name) { console.log("I smell another " + name + "; and I'm model " + this.id); }; }; Model.prototype = Object.create(EventfulObject.prototype); Model.prototype.constructor = Model; // ---------- TEST AND USAGE (hopefully it clear enough...) // ---------- note: I'm not testing event deregistration. var ob1 = new EventfulObject(); ob1.on("crap", function() { console.log("Speaking about craps on a broadcast? - Count me out!"); }); var model1 = new Model(1); var model2 = new Model(2); model2.on("bust", function() { console.log("I'm model2 and I'm busting!"); }); var ob2 = new EventfulObject(); ob2.on("bust", function() { console.log("I'm ob2 - busted!!!"); }); ob2.receiveBroadcast = function() { console.log("If it zips, I'll catch it. - That me ob2."); }; console.log("start:BROADCAST\n---------------"); model1.broadcast("crap"); console.log("end :BROADCAST\n---------------\n-\n-\n"); console.log("start:EMIT\n---------------"); ob1.emit("bust"); console.log("end:EMIT\n---------------"); 
 <h1>THE CODE IS IN the JavaScript pane!</h1> <h3>AND... THE SHOW IS ON YOUR CONSOLE!</h3> 

You can use this as a basis for a more reliable solution.

+4
source

Source: https://habr.com/ru/post/889716/


All Articles