text: (function(window, angular, undefined) {
  
    'use strict';
  
    /* global -ngSwipe */
  
    var ngSwipe = angular.module('swipe', []);
  
    ngSwipe.factory('swipe', [ function() {
  
      var MOVE_BUFFER_RADIUS = 40;
      var MAX_RATIO = 0.3;
  
      function getCoordinates(event) {
        var touches = event.touches && event.touches.length ? event.touches : [event];
        var e = (event.changedTouches && event.changedTouches[0]) ||
            (event.originalEvent && event.originalEvent.changedTouches &&
                event.originalEvent.changedTouches[0]) ||
            touches[0].originalEvent || touches[0];
  
        return {
          x: e.clientX,
          y: e.clientY
        };
      }
  
      return {
  
        bind: function(element, eventHandlers) {
  
          // Absolute total movement
          var totalX, totalY;
          // Coordinates of the start position.
          var startCoords;
          var lastPos;
          // Whether a swipe is active.
          var active = false;
          // Decide where we are going
          var isDecided = false;
          var isVertical = true;
  
          element.on('touchstart mousedown', function(event) {
            startCoords = getCoordinates(event);
            active = true;
            totalX = 0;
            totalY = 0;
            isDecided = false;
            isVertical = true;
            lastPos = startCoords;
            eventHandlers['start'] && eventHandlers['start'](startCoords, event);
          });
  
          element.on('touchcancel', function(event) {
            active = false;
            eventHandlers['cancel'] && eventHandlers['cancel'](event);
          });
  
          element.on('touchmove mousemove', function(event) {
  
            if (! active) {
              return;
            }
  
            if (! startCoords) {
              return;
            }
  
            var coords = getCoordinates(event);
  
            totalX += Math.abs(coords.x - lastPos.x);
            totalY += Math.abs(coords.y - lastPos.y);
  
            lastPos = coords;
  
            if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) {
              return;
            } else {
              if (! isDecided){
  
                var deltaX, deltaY, ratio;
  
                deltaX = Math.abs(coords.x - startCoords.x);
                deltaY = Math.abs(coords.y - startCoords.y);
  
                ratio = deltaY / deltaX;
  
                if (ratio < MAX_RATIO){
                  event.preventDefault();
                  isVertical = false;
                } else {
                  isVertical = true;
                }
  
                isDecided = true;
              }
            }
  
            event.isVertical = isVertical;
            eventHandlers['move'] && eventHandlers['move'](coords, event);
          });
  
          element.on('touchend mouseup', function(event) {
            if (! active){
              return;
            }
            event.isVertical = isVertical;
            active = false;
            eventHandlers['end'] && eventHandlers['end'](getCoordinates(event), event);
          });
        }
      };
    }]);
  
    function makeSwipeDirective(directiveName, direction, axis, eventName) {
      ngSwipe.directive(directiveName, ['$parse', 'swipe', function($parse, swipe) {
  
        var MAX_OTHER_AXIS_DISTANCE = 75;
        var MAX_RATIO = 0.3;
        var MIN_DISTANCE = 30;
  
        return function(scope, element, attr) {
  
          var swipeHandler = $parse(attr[directiveName]);
  
          var startCoords, valid;
  
          function validSwipe(coords) {
  
            if (! startCoords || ! valid){
              return false;
            }
  
            var deltaY = (coords.y - startCoords.y) * direction;
            var deltaX = (coords.x - startCoords.x) * direction;
  
            if (! axis){  // horizontal swipe
              return Math.abs(deltaY) < MAX_OTHER_AXIS_DISTANCE &&
                deltaX > 0 &&
                deltaX > MIN_DISTANCE &&
                Math.abs(deltaY) / deltaX < MAX_RATIO;
            } else {  // vertical swipe
              return Math.abs(deltaX) < MAX_OTHER_AXIS_DISTANCE &&
                deltaY > 0 &&
                deltaY > MIN_DISTANCE &&
                Math.abs(deltaX) / deltaY < MAX_RATIO;
            }
  
          }
  
          swipe.bind(element, {
            'start': function(coords, event) {
              var className = event.target.getAttribute('class');
              if (axis && (! className || className && className.match('noPreventDefault') === null)) {
                event.preventDefault();
              }
              startCoords = coords;
              valid = true;
            },
            'cancel': function() {
              valid = false;
            },
            'end': function(coords, event) {
              if (validSwipe(coords)) {
                scope.$apply(function() {
                  element.triggerHandler(eventName);
                  swipeHandler(scope, { $event: event });
                });
              }
            }
          });
        };
      }]);
    }
  
    // avoid conflicts with ngTouch module
  
    try {
      angular.module('ngTouch');
    } catch(err) {
      makeSwipeDirective('ngSwipeLeft', -1, false, 'swipeleft');
      makeSwipeDirective('ngSwipeRight', 1, false, 'swiperight');
    }
  
    // left is negative x-coordinate, right is positive
  
    makeSwipeDirective('ngSwipeUp', -1, true, 'swipeup');
    makeSwipeDirective('ngSwipeDown', 1, true, 'swipedown');
  
  })(window, window.angular);
  