/*Created by AlexCD on 11.04.2014*/
var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.swipeLeft = function() {
    window.alert('swiped left');
  };

  $scope.swipeRight = function() {
    window.alert('swiped right');
  };
});

/**
 * Directive to add a custom swiping effect on element, a swiping effect that will work on windows mobile phones
 * @method customSwiping
 * @returns {{restrict: string, scope: {right: string, left: string}, link: link}}
 */
app.directive('customSwiping', function(){
  return {
        restrict: 'E',
        scope: {
            right: '=',
            left: '='
        },
        link: function (scope, element) {
            var startCoord, endCoord, timer;

            /**
             * Retrieves pageX, pageY coordinates
             * @method getTouchCoordinates
             * @param event
             * @returns {{x: (Number|pageX|*), y: (Number|pageY|*)}}
             */
            function getTouchCoordinates(event) {
                var touch;
                if (event.type === 'mousedown' || event.type === 'mousemove') {
                    touch = event;
                } else {
                    if (event.touches) {
                        touch = event.touches[0];
                    } else {
                        touch = event.originalEvent.touches[0] || event.originalEvent.changedTouches[0];
                    }
                }
                return {x: touch.pageX, y: touch.pageY};
            }

            /**
             * A swipe can be done 360 degrees. In this directive case, a swipe is executed when the angle has no more than 10 degrees.
             * So, to find the angle, trigonometry is used (tangent / arctangent functions)
             * @method getTheta
             * @returns {number}
             */
            function getTheta() {
                var dy, dx, theta;
                dy = endCoord.y - startCoord.y; //opposite cathetus
                dx = endCoord.x - startCoord.x; //adjacent cathetus

                //the angle
                theta = Math.atan2(dy, dx);
                theta *= 180 / Math.PI;

                //return the angle
                return Math.abs(theta);
            }

            /**
             * Each swipe uses specified callback
             * @method makeSwipe
             */
            function makeSwipe() {
                if (startCoord && endCoord) {
                    if ((startCoord.x - endCoord.x) < -10) {
                        if (scope.right) {
                            if (getTheta() >= 0 && getTheta() <= 10) {
                                scope.right();
                                scope.$apply();

                            }
                        }
                    } else if ((startCoord.x - endCoord.x) > 10) {
                        if (scope.left) {
                            if (getTheta() >= 170 && getTheta() <= 180) {
                                scope.left();
                                scope.$apply();
                            }
                        }
                    }
                }
            }

            function getStartCoord(e) {
                return getTouchCoordinates(e);
            }

            function getEndCoord(e) {
                return getTouchCoordinates(e);
            }

            function detectMouseEnd() {
                /*global window, clearTimeout*/
                if (timer) {
                    clearTimeout(timer);
                }
                timer = window.setTimeout(function () {
                    element.off('mousemove');
                    clearTimeout(timer);
                    makeSwipe();
                }, 50);
            }

            (function () {
                //For IE and desktops
                //Mouse events are used instead of pointer events. IE pointer events incorporate both mouse events and touch events but they will be prone to
                //changes as IE does this all the time. For instance IE10 uses MSPointerDown, MSPointerMove, MSPointerUp but these are deprecated and not used in IE11. IE11
                //uses pointerdown, pointermove, pointerup. Of course, conditions can be used but the idea is to keep the code as simple as possible, ignoring IE bliss.
                //So mouse events can be used instead.
                //Since mouseup event can create problems, a mouseend method will be used to track the end of swiping
                element.on('mousedown', function (e) {
                    startCoord = getStartCoord(e);

                    element.on('mousemove', function (e) {
                        endCoord = getEndCoord(e);
                        detectMouseEnd(e);
                    });

                });

                //For all other mobile browsers
                element.on('touchstart', function (e) {
                    startCoord = getStartCoord(e);
                });
                element.on('touchend', function (e) {
                    endCoord = getEndCoord(e);
                    makeSwipe();
                });

            }());

            scope.$on('$destroy', function () {
                element.off();
            });

        }
    };
});
<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta name="description" content="AngularJS Custom Swiping Directive to be used on on desktop and mobile browsers.">
  <meta name="keywords" content="Swipe, Swiping, AngularJS, Directive, Javascript">
  <meta name="author" content="Alexandru Costin Dumitru (AlexCD)">
  <meta charset="UTF-8">
  <title>Angular Custom Swiping</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <div>
    <custom-swiping left="swipeLeft" right="swipeRight">
      Swipe on this element
    </custom-swiping>
  </div>
</body>

</html>
/* Put your css in here */
custom-swiping{
  display: block;
  border: 0.1em solid #777;
  padding: 0.5em;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
angularjs-custom-swiping
========================

Swiping effect directive that works on Internet Explorer Mobile.

IE Mobile can give lots of headaches since it knows nothing about touch events, using pointer events instead.

For now, this directive use mouse events to simulate a swipe for IE Mobile and desktop browsers. In IE 10, these events use MS prefix (like MSPointerDown, MSPointerMove etc). IE 11 do not use MS prefix for pointer events and who knows what's going to happen in IE 12 and so on. That's why this directive avoids pointer events at this time and so all conditionals needed to check for these changes.

Dependencies
============
To use this directive in your projects, you must include its dependencies. Asumming you already have angular and jquery libraries included in your project, you're going to need the main directive file: customSwiping.js

Usage
=====
Once you've checked that everything is in place, you can use this directive like so:

```html
<custom-swiping left="swipeLeftCallback" right="swipeRightCallback">
  Content
</custom-swiping>
```

or

```html
<custom-swiping left="swipeLeftCallback">
  Content
</custom-swiping>
```

or 

```html
<custom-swiping right="swipeRightCallback">
  Content
</custom-swiping>
```