hagope
hagope

Reputation: 5531

How to handle multiple touch events on a single HTML element using Angular directives

In my mobile application, I have main view where I display content, in HTML:

<div class="imageView" na-swipe="next()" na-tap="showControls()"> content here </div>

In order to handle swipe and touch events using jQuery (or Hammer.js), I've created these two directives:

angular.module("naModule").directive 'naTap', ->
  (scope, element, attrs) ->
    tapping = false
    element.bind 'touchstart', -> tapping = true
    element.bind 'touchmove', -> tapping = false
    element.bind 'touchend', -> scope.$apply(attrs['naTap']) if tapping

angular.module("naModule").directive 'naSwipe', ->
  (scope, element, attrs) ->
    tapping = false
    swiping = false
    element.bind 'touchstart', -> tapping = true
    element.bind 'touchmove', -> swiping = true
    element.bind 'touchend',  -> scope.$apply(attrs['naSwipe']) if (swiping and tapping)

The naSwipe seems to work well,that is next() is called whenever a swipe is performed...However, when I tap next() and showControls() are both firing ... how do I cleanly separate touch and swipe on this one div? Thanks.

Upvotes: 2

Views: 3591

Answers (2)

Mark Rajcok
Mark Rajcok

Reputation: 364677

Somewhere, you need to reset swiping to false. This should probably be done as part of the touchstart callback.

Upvotes: 1

Alex Osborn
Alex Osborn

Reputation: 9851

I think that you are approaching this in the wrong way for your use case.

Consider using one directive, the template for which is the markup you described, and define the events you want to capture in the link() function for that directive.

Something like the following directive:

angular.module('naModule').directive('imageView', function() {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            // As required for your content ...
        },
        template: '<div class="imageView"> content here </div>',
        controller: function($scope, $attrs) {
            $scope.next = function() {
                // handle function..
            }

            $scope.showControls = function() {
                // handle function..
            }
        },
        link: function(scope, element, attrs, controller) {
            element.bind('touchstart', function(e) {
                scope.tapping = true;
                scope.swiping = true;
            }

            element.bind('touchmove', function(e) {
                scope.tapping = false;
                scope.swiping = true;
            }

            element.bind('touchend', function(e) {
                if(scope.tapping) {
                    scope.next();
                } else {
                    scope.showControls();
                }
            }
        }
    }
});

Upvotes: 3

Related Questions