text: (function(){
  
    /**
     * @private
     * @param {String} eventName
     * @param {Function} handler
     */
    function _removeEventListener(eventName, handler) {
      if (!this.__eventListeners[eventName]) {
        return;
      }
  
      if (handler) {
        fabric.util.removeFromArray(this.__eventListeners[eventName], handler);
      }
      else {
        this.__eventListeners[eventName].length = 0;
      }
    }
  
    /**
     * Observes specified event
     * @deprecated `observe` deprecated since 0.8.34 (use `on` instead)
     * @memberOf fabric.Observable
     * @alias on
     * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})
     * @param {Function} handler Function that receives a notification when an event of the specified type occurs
     * @return {Self} thisArg
     * @chainable
     */
    function observe(eventName, handler) {
      if (!this.__eventListeners) {
        this.__eventListeners = { };
      }
      // one object with key/value pairs was passed
      if (arguments.length === 1) {
        for (var prop in eventName) {
          this.on(prop, eventName[prop]);
        }
      }
      else {
        if (!this.__eventListeners[eventName]) {
          this.__eventListeners[eventName] = [ ];
        }
        this.__eventListeners[eventName].push(handler);
      }
      return this;
    }
  
    /**
     * Stops event observing for a particular event handler. Calling this method
     * without arguments removes all handlers for all events
     * @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead)
     * @memberOf fabric.Observable
     * @alias off
     * @param {String|Object} eventName Event name (eg. 'after:render') or object with key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})
     * @param {Function} handler Function to be deleted from EventListeners
     * @return {Self} thisArg
     * @chainable
     */
    function stopObserving(eventName, handler) {
      if (!this.__eventListeners) {
        return;
      }
  
      // remove all key/value pairs (event name -> event handler)
      if (arguments.length === 0) {
        this.__eventListeners = { };
      }
      // one object with key/value pairs was passed
      else if (arguments.length === 1 && typeof arguments[0] === 'object') {
        for (var prop in eventName) {
          _removeEventListener.call(this, prop, eventName[prop]);
        }
      }
      else {
        _removeEventListener.call(this, eventName, handler);
      }
      return this;
    }
  
    /**
     * Fires event with an optional options object
     * @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead)
     * @memberOf fabric.Observable
     * @alias trigger
     * @param {String} eventName Event name to fire
     * @param {Object} [options] Options object
     * @return {Self} thisArg
     * @chainable
     */
    function fire(eventName, options) {
      if (!this.__eventListeners) {
        return;
      }
  
      var listenersForEvent = this.__eventListeners[eventName];
      if (!listenersForEvent) {
        return;
      }
  
      for (var i = 0, len = listenersForEvent.length; i < len; i++) {
        // avoiding try/catch for perf. reasons
        listenersForEvent[i].call(this, options || { });
      }
      return this;
    }
  
    /**
     * @namespace fabric.Observable
     * @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#events}
     * @see {@link http://fabricjs.com/events/|Events demo}
     */
    fabric.Observable = {
      observe: observe,
      stopObserving: stopObserving,
      fire: fire,
  
      on: observe,
      off: stopObserving,
      trigger: fire
    };
  })();
  