1 fabric.Observable = {
  2   
  3   /**
  4    * @mthod observe
  5    * @param {String} eventName
  6    * @param {Function} handler
  7    */
  8   observe: function(eventName, handler) {
  9     if (!this.__eventListeners) {
 10       this.__eventListeners = { };
 11     }
 12     if (!this.__eventListeners[eventName]) {
 13       this.__eventListeners[eventName] = [ ];
 14     }
 15     this.__eventListeners[eventName].push(handler);
 16   },
 17   
 18   /**
 19    * @mthod stopObserving
 20    * @memberOf fabric.util
 21    * @param {String} eventName
 22    * @param {Function} handler
 23    */
 24   stopObserving: function(eventName, handler) {
 25     if (!this.__eventListeners) {
 26       this.__eventListeners = { };
 27     }
 28     if (this.__eventListeners[eventName]) {
 29       fabric.util.removeFromArray(this.__eventListeners[eventName], handler);
 30     }
 31   },
 32   
 33   /**
 34    * Fires event with an optional memo object
 35    * @mthod fire
 36    * @memberOf fabric.util
 37    * @param {String} eventName
 38    * @param {Object} [memo]
 39    */
 40   fire: function(eventName, memo) {
 41     if (!this.__eventListeners) {
 42       this.__eventListeners = { }
 43     }
 44     var listenersForEvent = this.__eventListeners[eventName];
 45     if (!listenersForEvent) return;
 46     for (var i = 0, len = listenersForEvent.length; i < len; i++) {
 47       // avoiding try/catch for perf. reasons
 48       listenersForEvent[i]({ memo: memo });
 49     }
 50   }
 51 };