bind events to the instance
@param   {String}      gesture
@param   {Function}    handler
@returns {Hammer.Instance}
165376
function onEvent(gesture, handler) {
    var gestures = gesture.split(' ');
    Hammer.utils.each(gestures, function(gesture) {
      this.element.addEventListener(gesture, handler, false);
    }, this);
    return this;
  }
740203
function touchEnd(jqEvent) {
			//As we use Jquery bind for events, we need to target the original event object
			//If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
			var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent,
			    touches = event.touches;

			//If we are still in a touch with another finger return
			//This allows us to wait a fraction and see if the other finger comes up, if it does within the threshold, then we treat it as a multi release, not a single release.
			if (touches) {
				if(touches.length) {
					startMultiFingerRelease();
					return true;
				}
			}
			
			//If a previous finger has been released, check how long ago, if within the threshold, then assume it was a multifinger release.
			//This is used to allow 2 fingers to release fractionally after each other, whilst maintainig the event as containg 2 fingers, not 1
			if(inMultiFingerRelease()) {	
				fingerCount=previousTouchFingerCount;
			}	
		
			//Set end of swipe
			endTime = getTimeStamp();
			
			//Get duration incase move was never fired
			duration = calculateDuration();
			
			//If we trigger handlers at end of swipe OR, we trigger during, but they didnt trigger and we are still in the move phase
			if(didSwipeBackToCancel() || !validateSwipeDistance()) {
			    phase = PHASE_CANCEL;
                triggerHandler(event, phase);
			} else if (options.triggerOnTouchEnd || (options.triggerOnTouchEnd == false && phase === PHASE_MOVE)) {
				//call this on jq event so we are cross browser 
				jqEvent.preventDefault(); 
				phase = PHASE_END;
                triggerHandler(event, phase);
			}
			//Special cases - A tap should always fire on touch end regardless,
			//So here we manually trigger the tap end handler by itself
			//We dont run trigger handler as it will re-trigger events that may have fired already
			else if (!options.triggerOnTouchEnd && hasTap()) {
                //Trigger the pinch events...
			    phase = PHASE_END;
			    triggerHandlerForGesture(event, phase, TAP);
			}
			else if (phase === PHASE_MOVE) {
				phase = PHASE_CANCEL;
				triggerHandler(event, phase);
			}

			setTouchInProgress(false);

            return null;
		}
580574
function (eventType, handler) {
		// simplest possible event model for internal use
		this.element['on' + eventType] = function () {
			var evt = win.event;
			evt.target = evt.srcElement;
			handler(evt);
		};
		return this;
	}
848820
function(type, handler)
	{
		var obj = this.__obj;
		
		if (obj)
		{
			switch (true)
			{
				// TODO Remove the last tiny piece of jQuery support?
				case conbo.$ && obj instanceof conbo.$:
				case window.$ && obj instanceof window.$:
				{
					obj.on(type, handler);
					break;
				}
				
				case obj instanceof conbo.EventDispatcher:
				{
					obj.addEventListener(type, handler);
					break;
				}
				
				default:
				{
					var types = type.split(' ');
					
					types.forEach(function(type)
					{
						obj.addEventListener(type, handler);
					});
				}
			}
		}
		
		return this;
	}
412115
function startDetect(inst, eventData) {
    // already busy with a Hammer.gesture detection on an element
    if(this.current) {
      return;
    }

    this.stopped = false;

    this.current = {
      inst      : inst, // reference to HammerInstance we're working for
      startEvent: Hammer.utils.extend({}, eventData), // start eventData for distances, timing etc
      lastEvent : false, // last eventData
      name      : '' // current gesture we're in/detected, can be 'tap', 'hold' etc
    };

    this.detect(eventData);
  }
1354881
function bind(elements) {
      for (var i = 0; i < elements.length; i++) {
        Binder.on('click', elements[i], this.click);
        Binder.on('touchstart', elements[i], this.click, capture);
      }
    }
323078
function( type, handler ) {

      if( handler === void 0 || handler === null )
        throw new Error( 'Missing argument "handler"' )

      if( typeof handler !== 'function' && typeof handler.handleEvent !== 'function' )
        throw new TypeError( 'Handler must be a function.' )

      this._events[ type ] ?
        this._events[ type ].push( handler ) :
        this._events[ type ] = [ handler ]

      if( Emitter.warn && this._events[ type ].length > this._maxListeners ) {
        if( this._maxListeners > 0 && !this._memLeakDetected ) {
          this._memLeakDetected = true
          console.warn(
            'WARNING: Possible event emitter memory leak detected.',
            this._events[ type ].length, 'event handlers added.',
            'Use emitter.setMaxListeners() to increase the threshold.'
          )
          console.trace()
        }
      }

      return this

    }
556179
function bindEvent(element, type, handler, context) {
    /**
     * Event handler
     * @param {Event} e - event object
     */
    function eventHandler(e) {
        handler.call(context || element, e || window.event);
    }

    /**
     * Event handler for normalize mouseenter event
     * @param {MouseEvent} e - event object
     */
    function mouseEnterHandler(e) {
        e = e || window.event;

        if (checkMouse(element, e)) {
            eventHandler(e);
        }
    }

    if ('addEventListener' in element) {
        if (type === 'mouseenter' || type === 'mouseleave') {
            type = (type === 'mouseenter') ? 'mouseover' : 'mouseout';
            element.addEventListener(type, mouseEnterHandler);
            memorizeHandler(element, type, handler, mouseEnterHandler);
        } else {
            element.addEventListener(type, eventHandler);
            memorizeHandler(element, type, handler, eventHandler);
        }
    } else if ('attachEvent' in element) {
        element.attachEvent(`on${type}`, eventHandler);
        memorizeHandler(element, type, handler, eventHandler);
    }
}
1307819
function offEvent(gesture, handler){
      var gestures = gesture.split(' ');
      for(var t=0; t<gestures.length; t++) {
        this.element.removeEventListener(gestures[t], handler, false);
      }
      return this;
    }
899955
function (events, handler) {
    var handlers = this.handlers;
    splitStr(events).forEach(function (event) {
      if (!handler) {
        delete handlers[event];
      } else {
        handlers[event].splice(handlers[event].indexOf(handler), 1);
      }
    });
    return this;
  }
92197
function _add(node, evType, handler) {
  let recognizer = gestures[evType];
  let deps = recognizer.deps;
  let name = recognizer.name;
  let gobj = node[GESTURE_KEY];
  if (!gobj) {
    node[GESTURE_KEY] = gobj = {};
  }
  for (let i = 0, dep, gd; i < deps.length; i++) {
    dep = deps[i];
    // don't add mouse handlers on iOS because they cause gray selection overlays
    if (IS_TOUCH_ONLY && isMouseEvent(dep) && dep !== 'click') {
      continue;
    }
    gd = gobj[dep];
    if (!gd) {
      gobj[dep] = gd = {_count: 0};
    }
    if (gd._count === 0) {
      node.addEventListener(dep, _handleNative, PASSIVE_TOUCH(dep));
    }
    gd[name] = (gd[name] || 0) + 1;
    gd._count = (gd._count || 0) + 1;
  }
  node.addEventListener(evType, handler);
  if (recognizer.touchAction) {
    setTouchAction(node, recognizer.touchAction);
  }
}
1231498
function (type, handler) {
        var handlers = this.handlers();
        if (handlers[type]) {
            throw new Error('The hook has already been registered, you can use only one hook for specific event type: ' + type + ', point.id:' + this._id);
        }
        handlers[type] = handler;
        this._handlersConfigured = true;
        return this;
    }
49792
function stopHandler( event ) {
					$this.unbind( touchMoveEvent, moveHandler )
						.unbind( touchStopEvent, stopHandler );

					if ( start && stop ) {
						$.event.special.swipe.handleSwipe( start, stop );
					}
					start = stop = undefined;
				}
258445
function onEvent(gesture, handler){
      var gestures = gesture.split(' ');
      for(var t=0; t<gestures.length; t++) {
        this.element.addEventListener(gestures[t], handler, false);
      }
      return this;
    }
593176
function( type, handler ) {

      var handlers = this._events[ type ]
      var position = handlers.indexOf( handler )

      if( handlers && ~position ) {
        if( handlers.length === 1 ) {
          this._events[ type ] = undefined
          delete this._events[ type ]
        } else {
          handlers.splice( position, 1 )
        }
      }

      return this

    }
451539
function touchHandler (event) {
  let opt = this._opt
  opt.preventDefault && event.preventDefault()
  opt.stopPropagation && event.stopPropagation()

  // 如果 touchstart 没有被触发(可能被子元素的 touchstart 回调触发了 stopPropagation)，
  // 那么后续的手势将取消计算
  if (event.type !== 'touchstart' && !dataProcessor.startTime) {
    return
  }

  let data = dataProcessor.process(event, opt.preventX, opt.preventY)
  this._recognize(data)
  this.trigger(event.type, event, data)
}
996802
function (obj, type, handler, id) {

		switch (type) {
		case 'touchstart':
			return this.addPointerListenerStart(obj, type, handler, id);
		case 'touchend':
			return this.addPointerListenerEnd(obj, type, handler, id);
		case 'touchmove':
			return this.addPointerListenerMove(obj, type, handler, id);
		default:
			throw 'Unknown touch event type';
		}
	}