import angular from 'angular' import Hammer from 'hammerjs' // Essentially inlined from is_js check, it's old but we preserve the behavior. function is_iOS() { const ua = (navigator?.userAgent || '').toLowerCase() /* tslint:disable */ const is_iPad = !!ua.match(/ipad.+?os (\d+)/) const is_iPhone = !!ua.match(/iphone(?:.+?os (\d+))?/) /* tslint:enable */ return is_iPad || is_iPhone } angular.module('app').directive('mflyGestureHandler', function () { return { restrict: 'A', scope: { // (Optional) Set this flag to dynamically turn off gestures 'handlerDisabled': '=', // Detectable gestures are listed here. To handle them, place a callback as an // attribute on the element which consumes this directive. For example: // //
// // All the event handlers are optional; you only need to handle the ones you care about. 'pageTurnNext': '&', // A right-to-left swipe anywhere on the element 'pageTurnPrevious': '&' // A left-to-right swipe anywhere on the element }, link($scope: ScopeKeyValuePair, element) { // Set up the Hammer recognizer on the provided element // (note that Hammer wants a DOM element, not a jqlite-wrapped element) const hammerManager = new Hammer.Manager(element[0], { // In some cases (PDF documents), we want the user to be able to select text inside the gesture handler. // By default, Hammer prevents text selection to prevent swipe gestures selecting text. Override this. // (Our gesture-handler is only effective on touch devices, which do a good job of discerning swipes from // text selection by themselves.) cssProps: { userSelect: 'inherit', }, recognizers: [ [Hammer.Swipe, { direction: Hammer.DIRECTION_HORIZONTAL }] ], // If a browser sends a PointerEvent but Hammer is not expecting them, // swipe gestures won't be detected. Additionally, Hammer's built-in // event detection doesn't seem to be kicking in correctly, so we // override it here. // // Note that Mobile Safari will start issuing PointerEvents in iOS 13. // // See: https://github.com/hammerjs/hammer.js/issues/1065 inputClass: Hammer.SUPPORT_POINTER_EVENTS ? Hammer.PointerEventInput : Hammer.TouchInput, // By default, Hammer sets `touch-action: pan-y` in css on the recognizer // element. This prevents pinch-to-zoom gestures on Chrome/Android. // // Our goal is to set `touch-action: pan-y pinch-zoom` to fix this and still // prevent the browser history actions from kicking in, but Hammer won't // set arbitrary strings into the touch-action property. // Instead, we pass an invalid value, which causes Hammer not to set // _any_ touch-action value, and then set the property ourselves. // // See: https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action touchAction: '' }) // iOS Safari only supports `manipulation` or `auto`. if (is_iOS()) { element.css('touch-action', 'manipulation') } else { element.css('touch-action', 'pan-y pinch-zoom') } // Gesture handler: pageTurnNext const swipeLeftHandler = function (event) { if (!$scope.handlerDisabled) { $scope.$apply($scope.pageTurnNext) event.preventDefault() // Override native history-forward gesture } } hammerManager.on('swipeleft', swipeLeftHandler) // Gesture handler: pageTurnPrevious const swipeRightHandler = function (event) { if (!$scope.handlerDisabled) { $scope.$apply($scope.pageTurnPrevious) event.preventDefault() // Override native history-back gesture } } hammerManager.on('swiperight', swipeRightHandler) $scope.$on('$destroy', function () { hammerManager.off('swipeleft', swipeLeftHandler) hammerManager.off('swiperight', swipeRightHandler) hammerManager.destroy() }) } } })