docs: function touchendHandler(event) {
  
    if (Object.keys(gestures).length == 2) {
      var elements = []
      for (var p in gestures) {
        elements.push(gestures[p].element)
      }
      fireEvent(getCommonAncestor(elements[0], elements[1]), 'dualtouchend', {
        touches: slice.call(event.touches),
        touchEvent: event
      })
    }
  
    for (var i = 0; i < event.changedTouches.length; i++) {
      var touch = event.changedTouches[i]
      var id = touch.identifier
      var gesture = gestures[id]
  
      if (!gesture) {
        continue
      }
  
      if (gesture.pressingHandler) {
        clearTimeout(gesture.pressingHandler)
        gesture.pressingHandler = null
      }
  
      if (gesture.status === 'tapping') {
        gesture.timestamp = Date.now()
        fireEvent(gesture.element, 'tap', {
          touch: touch,
          touchEvent: event
        })
  
        if (lastTap && gesture.timestamp - lastTap.timestamp < 300) {
          fireEvent(gesture.element, 'doubletap', {
            touch: touch,
            touchEvent: event
          })
        }
  
        lastTap = gesture
      }
  
      if (gesture.status === 'panning') {
        var now = Date.now()
        var duration = now - gesture.startTime
        var displacementX = touch.clientX - gesture.startTouch.clientX
        var displacementY = touch.clientY - gesture.startTouch.clientY
  
        var velocity = Math.sqrt(gesture.velocityY * gesture.velocityY
          + gesture.velocityX * gesture.velocityX)
        var isSwipe = velocity > 0.5 && (now - gesture.lastTime) < 100
        var extra = {
          duration: duration,
          isSwipe: isSwipe,
          velocityX: gesture.velocityX,
          velocityY: gesture.velocityY,
          displacementX: displacementX,
          displacementY: displacementY,
          touch: touch,
          touches: event.touches,
          changedTouches: event.changedTouches,
          touchEvent: event,
          isVertical: gesture.isVertical,
          direction: gesture.direction
        }
  
        fireEvent(gesture.element, 'panend', extra)
        if (isSwipe) {
          fireEvent(gesture.element, 'swipe', extra)
        }
      }
  
      if (gesture.status === 'pressing') {
        fireEvent(gesture.element, 'pressend', {
          touch: touch,
          touchEvent: event
        })
      }
  
      delete gestures[id]
    }
  
    if (Object.keys(gestures).length === 0) {
      docEl.removeEventListener('touchmove', touchmoveHandler, false)
      docEl.removeEventListener('touchend', touchendHandler, false)
      docEl.removeEventListener('touchcancel', touchcancelHandler, false)
    }
  }