Event listener on non-DOM elements


I'm trying to implement a little MVC framework and now I'm implementing the view-model binder, I mean, when the model changes, trigger a refresh/render/whatever on the model. So, I need an event listener on a object:

model.on("customEvent",appendItem); $("#button").on("click",function(){ model.add(item); model.trigger("customEvent"); }); function appendItem(item) { $("#content").append(item.toHTML()); }

So how can I create my event listener on objects?


If you are already using jQuery, you can use its built-in event handling facilities.

It's a little known fact that you can also put any kind of Javascript objects into a jQuery collection, not just DOM elements. Then you can use a limited set of jQuery methods (.data(), .prop(), .on(), .off(), .trigger() and .triggerHandler()) on these objects.

//create the model - it can be any kind of object var model = {}; //pass it to the jQuery function and you have a jQuery collection //you can put an event handler on the object $(model).on('customEvent', function () { console.log('hehe'); }); //and trigger it $(model).trigger('customEvent'); <ul><li>Read more <a href="http://api.jquery.com/jquery/#working-with-plain-objects" rel="nofollow">in the Manual</a></li> <li>Try the <a href="http://jsfiddle.net/VBd72/" rel="nofollow">Demo</a></li> </ul>


For those who are not using jQuery and are interested in wiring their own stuf, here's how you may achieve similar aim:

<pre class="snippet-code-js lang-js prettyprint-override">/** * 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's 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's 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---------------"); <pre class="snippet-code-html lang-html prettyprint-override">




  • Move Woocommerce “My Account Navigation” to the top of the page
  • Difference between datetime converts in MSExcel and SQL Server
  • Using Algolia react-instantsearch with react-native
  • webapp version 2.4 to 2.5 out of memory
  • How does one incorporate a Django application into an existing twisted server?
  • How can I convert a JavaScript variable to a Java variable?
  • Connecting gwt-dispatch with guice and mvp4g
  • Python - What's the use of if True:?
  • What is the meaning and what it does autowire=“default” in spring in applicationcontext.xml file
  • Failed to create any app request
  • CSS how to fix an element to scroll horizontally with the page but not vertically?
  • Can my PDF ping my server when it is opened?
  • Why must we declare a variable name when adding a method to a struct in Golang?
  • How to retrieve information from antrun back to maven?
  • Pycharm: Marking a folder as 'sources root' is not recursive for subfolders
  • ThreadStatic in asynchronous ASP.NET Web API
  • Sending keystrokes/mouse clicks to a Java program with Autohotkey
  • Get history of file changes from TFS to implement custom “blame”-behaviour of exceptions
  • AJAX Html Editor Extender upload image appearing blank
  • Hardware Accelerated Image Scaling in windows using C++
  • Refering to the class itself from within a class mehod in Objective C
  • How to do unit test for HttpContext.Current.Server.MapPath
  • Azure Cloud Service Web Role web pages do not load
  • swift auto completion not working in Xcode6-Beta
  • Is there a amazon webstore API for customers?
  • How to get a value (ex: baseURL) in every Karate feature?
  • Finding past revisions of files in StarTeam w/ .NET SDK / C#
  • Perl system calls when running as another user using sudo
  • Can a Chrome extension content script make an jQuery AJAX request for an html file that is itself a
  • Upload files with Ajax and Jquery
  • How to pass list parameters for each object using Spring MVC?
  • Cannot Parse HTML Data Using Android / JSOUP
  • InvalidAuthenticityToken between subdomains when logging in with Rails app
  • SQL merge duplicate rows and join values that are different
  • AngularJs get employee from factory
  • Proper way to use connect-multiparty with express.js?
  • C# - Getting references of reference
  • Exception on Android 4.0 `android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode)`
  • LevelDB C iterator
  • Can't mass-assign protected attributes when import data from csv file