'use strict'; angular.module('angular-gestures', []); /** * Inspired by AngularJS' implementation of "click dblclick mousedown..." * * This ties in the Hammer 2 events to attributes like: * * hm-tap="add_something()" hm-swipe="remove_something()" * * and also has support for Hammer options with: * * hm-tap-opts="{hold: false}" * * or any other of the "hm-event" listed underneath. */ var HGESTURES = { hmDoubleTap: 'doubletap', hmDragstart: 'panstart', // will bedeprecated soon, us Pan* hmDrag: 'pan', // will bedeprecated soon, us Pan* hmDragUp: 'panup', // will bedeprecated soon, us Pan* hmDragDown: 'pandown', // will bedeprecated soon, us Pan* hmDragLeft: 'panleft', // will bedeprecated soon, us Pan* hmDragRight: 'panright', // will bedeprecated soon, us Pan* hmDragend: 'panend', // will bedeprecated soon, us Pan* hmPanstart: 'panstart', hmPan: 'pan', hmPanUp: 'panup', hmPanDown: 'pandown', hmPanLeft: 'panleft', hmPanRight: 'panright', hmPanend: 'panend', hmHold: 'press', hmPinch: 'pinch', hmPinchIn: 'pinchin', hmPinchOut: 'pinchout', hmPress: 'press', hmRelease: 'release', hmRotate: 'rotate', hmSwipe: 'swipe', hmSwipeUp: 'swipeup', hmSwipeDown: 'swipedown', hmSwipeLeft: 'swipeleft', hmSwipeRight: 'swiperight', hmTap: 'tap', hmTouch: 'touch', hmTransformstart: 'transformstart', hmTransform: 'transform', hmTransformend: 'transformend' }; var HRECOGNIZERS = { hmDoubleTap: [Hammer.Tap, 'Hammer.Tap'], hmDragstart: [Hammer.Pan, 'Hammer.Pan'], hmDrag: [Hammer.Pan, 'Hammer.Pan'], hmDragUp: [Hammer.Pan, 'Hammer.Pan'], hmDragDown: [Hammer.Pan, 'Hammer.Pan'], hmDragLeft: [Hammer.Pan, 'Hammer.Pan'], hmDragRight: [Hammer.Pan, 'Hammer.Pan'], hmDragend: [Hammer.Pan, 'Hammer.Pan'], hmPanstart: [Hammer.Pan, 'Hammer.Pan'], hmPan: [Hammer.Pan, 'Hammer.Pan'], hmPanUp: [Hammer.Pan, 'Hammer.Pan'], hmPanDown: [Hammer.Pan, 'Hammer.Pan'], hmPanLeft: [Hammer.Pan, 'Hammer.Pan'], hmPanRight: [Hammer.Pan, 'Hammer.Pan'], hmPanend: [Hammer.Pan, 'Hammer.Pan'], hmHold: [Hammer.Press, 'Hammer.Press'], hmPinch: [Hammer.Pinch, 'Hammer.Pinch'], hmPinchIn: [Hammer.Pinch, 'Hammer.Pinch'], hmPinchOut: [Hammer.Pinch, 'Hammer.Pinch'], hmPress: [Hammer.Press, 'Hammer.Press'], hmRotate: [Hammer.Rotate, 'Hammer.Rotate'], hmSwipe: [Hammer.Swipe, 'Hammer.Swipe'], hmSwipeUp: [Hammer.Swipe, 'Hammer.Swipe'], hmSwipeDown: [Hammer.Swipe, 'Hammer.Swipe'], hmSwipeLeft: [Hammer.Swipe, 'Hammer.Swipe'], hmSwipeRight: [Hammer.Swipe, 'Hammer.Swipe'], hmTap: [Hammer.Tap, 'Hammer.Tap'] }; var VERBOSE = false; angular.forEach(HGESTURES, function(eventName, directiveName) { angular.module('angular-gestures').directive(directiveName, ['$parse', '$log', '$timeout', 'hammerDefaultOpts', function($parse, $log, $timeout, hammerDefaultOpts) { return function(scope, element, attr) { var handler; attr.$observe(directiveName, function(value) { var callback = $parse(value); var opts = $parse(attr[directiveName + 'Opts'])(scope, {}); var defaultOpts = angular.copy(hammerDefaultOpts); angular.extend(defaultOpts, opts); if (angular.isUndefined(element.hammertime)) { // validate that needed recognizer is enabled var recognizers = angular.isDefined(defaultOpts.recognizers) ? defaultOpts.recognizers : []; var recognizer = HRECOGNIZERS[directiveName]; if(angular.isDefined(recognizer)) { var enabled = false; angular.forEach(recognizers, function(r) { if (recognizer[0] === r[0]) { if (angular.isUndefined(r[1].enable) || r[1].enable === true) { enabled = true; } } }); if (!enabled) { throw new Error('Directive ' + directiveName + ' requires gesture recognizer [' + recognizer[1] + '] to be enabled'); } } element.hammer = new Hammer.Manager(element[0], defaultOpts); scope.$on('$destroy', function() { element.hammer.off(eventName); element.hammer.destroy(); }); } handler = function(event) { if (VERBOSE) { $log.debug('angular-gestures: ', eventName, event); } var callbackHandler = function () { var cb = callback(scope, { $event : event}); if (typeof cb === 'function') { cb.call(scope, event); } }; if (scope.$root.$$phase === '$apply' || scope.$root.$$phase === '$digest') { callbackHandler(); } else { scope.$apply(callbackHandler); } }; // register actual event element.hammer.on(eventName, handler); }); }; }]); }); angular.module('angular-gestures').provider('hammerDefaultOpts', function HammerDefaultOptsProvider() { var opts = {}; this.set = function(value) { opts = value; }; this.$get = function() { return opts; }; });