/** * Simple Observer pattern mixin (custom event dispatching & listening) * Doesn't requires any 3rd-party JS libs. It's pure JS * * Usage: * * var MyObject = {...}; // your custom object * Observer.apply(MyObject); // you also can apply Observer to a prototype * MyObject.on('inited', function() { console.log("I'm alive!"); }); * MyObject.trigger('inited'); * * Author: kottenator * License: MIT * Date: 2014-04-11 */ var Observer = { apply: function(obj) { obj.events = {}; obj.on = this.on; obj.off = this.off; obj.trigger = this.trigger; }, /** * Add event listener * * {String} events - e.g. 'my-event-1 my-event-2' * {Function} fn - event listener */ on: function(events, fn) { events = events.replace(/^\s+|\s+$/g, '').split(/\s+/); for (var i = 0; i < events.length; i++) { var event = events[i]; if (!this.events[event]) this.events[event] = {}; this.events[event].push(fn); } }, /** * Remove event listener * * {String} events - e.g. 'my-event-1 my-event-2' * {Function} fn - event listener. If not specified (or null, or undefined, * or or any bool-casted to 'false' value) - all listeners will be removed. */ off: function(events, fn) { events = events.replace(/^\s+|\s+$/g, '').split(/\s+/); for (var i = 0; i < events.length; i++) { var event = events[i]; if (!this.events[event]) continue; var fns = this.events[event], nfns = []; if (fn) { for (var j = 0; j < fns.length; j++) { if (fns[j] !== fn) nfns.push(fns[j]); } } this.events[event] = nfns; } }, /** * Dispatch an event (call all its listeners) * * All listeners will be called with 2 arguments: fn({String} eventName, {any type} args) * * {String} events - e.g. 'my-event-1 my-event-2' * {any type} args - custom event arguments (you may specify multiple args as Array or Object) */ trigger: function(events, args) { events = events.replace(/^\s+|\s+$/g, '').split(/\s+/); for (var i = 0; i < events.length; i++) { var event = events[i]; if (!this.events[event]) continue; var fns = this.events[event]; for (var j = 0; j < fns.length; j++) { fns[j].call(this, event, args); } } } };