text: /**
   * create new hammer instance
   * all methods should return the instance itself, so it is chainable.
   * @param   {HTMLElement}       element
   * @param   {Object}            [options={}]
   * @returns {Hammer.Instance}
   * @constructor
   */
  Hammer.Instance = function(element, options) {
    var self = this;
  
    // setup HammerJS window events and register all gestures
    // this also sets up the default options
    setup();
  
    this.element = element;
  
    // start/stop detection option
    this.enabled = true;
  
    // merge options
    this.options = Hammer.utils.extend(
      Hammer.utils.extend({}, Hammer.defaults),
      options || {});
  
    // add some css to the element to prevent the browser from doing its native behavoir
    if(this.options.stop_browser_behavior) {
      Hammer.utils.stopDefaultBrowserBehavior(this.element, this.options.stop_browser_behavior);
    }
  
    // start detection on touchstart
    this._eventStartHandler = Hammer.event.onTouch(element, Hammer.EVENT_START, function(ev) {
      if(self.enabled) {
        Hammer.detection.startDetect(self, ev);
      }
    });
  
    // keep a list of user event handlers which needs to be removed when calling 'dispose'
    this._eventHandler = [];
  
    // return instance
    return this;
  };
  
  
  Hammer.Instance.prototype = {
    /**
     * bind events to the instance
     * @param   {String}      gesture
     * @param   {Function}    handler
     * @returns {Hammer.Instance}
     */
    on: function onEvent(gesture, handler) {
      var gestures = gesture.split(' ');
      Hammer.utils.each(gestures, function(gesture) {
        this.element.addEventListener(gesture, handler, false);
        this._eventHandler.push({ gesture: gesture, handler: handler });
      }, this);
      return this;
    },
  
  
    /**
     * unbind events to the instance
     * @param   {String}      gesture
     * @param   {Function}    handler
     * @returns {Hammer.Instance}
     */
    off: function offEvent(gesture, handler) {
      var gestures = gesture.split(' ');
      Hammer.utils.each(gestures, function(gesture) {
        this.element.removeEventListener(gesture, handler, false);
  
        // remove the event handler from the internal list
        var index = -1;
        Hammer.utils.each(this._eventHandler, function(eventHandler, i) {
          if (index === -1 && eventHandler.gesture === gesture && eventHandler.handler === handler) {
            index = i;
          }
        }, this);
  
        if (index > -1) {
          this._eventHandler.splice(index, 1);
        }
      }, this);
      return this;
    },
  
  
    /**
     * trigger gesture event
     * @param   {String}      gesture
     * @param   {Object}      [eventData]
     * @returns {Hammer.Instance}
     */
    trigger: function triggerEvent(gesture, eventData) {
      // optional
      if(!eventData) {
        eventData = {};
      }
  
      // create DOM event
      var event = Hammer.DOCUMENT.createEvent('Event');
      event.initEvent(gesture, true, true);
      event.gesture = eventData;
  
      // trigger on the target if it is in the instance element,
      // this is for event delegation tricks
      var element = this.element;
      if(Hammer.utils.hasParent(eventData.target, element)) {
        element = eventData.target;
      }
  
      element.dispatchEvent(event);
      return this;
    },
  
  
    /**
     * enable of disable hammer.js detection
     * @param   {Boolean}   state
     * @returns {Hammer.Instance}
     */
    enable: function enable(state) {
      this.enabled = state;
      return this;
    },
  
  
    /**
     * dispose this hammer instance
     * @returns {Hammer.Instance}
     */
    dispose: function dispose() {
  
      // undo all changes made by stop_browser_behavior
      if(this.options.stop_browser_behavior) {
        Hammer.utils.startDefaultBrowserBehavior(this.element, this.options.stop_browser_behavior);
      }
  
      // unbind all custom event handlers
      Hammer.utils.each(this._eventHandler, function(eventHandler) {
        this.element.removeEventListener(eventHandler.gesture, eventHandler.handler, false);
      }, this);
      this._eventHandler.length = 0;
  
      // unbind the start event listener
      Hammer.event.unbindDom(this.element, Hammer.EVENT_TYPES[Hammer.EVENT_START], this._eventStartHandler);
      return this;
    }
  };
  