function($element, dragOptions, touchOptions) {
            $element = angular.element($element);
            dragOptions = dragOptions || {};
            touchOptions = touchOptions || {};

            var startEventHandler = dragOptions.start;
            var endEventHandler = dragOptions.end;
            var moveEventHandler = dragOptions.move;
            var cancelEventHandler = dragOptions.cancel;
            var transformEventHandler = dragOptions.transform || this.TRANSLATE_BOTH;

            var domElement = $element[0];
            var tO = $transform.get($element); // original transform
            var rO = domElement.getBoundingClientRect(); // original bounding rect
            var tS; // transform at start
            var rS;

            var moving = false;

            var isMoving = function() {
              return moving;
            };

            var cleanup = function() {
              moving = false;
              tS = rS = null;
              $element.removeClass('ui-drag-move');
            };

            var reset = function() {
              $transform.set(domElement, tO);
            };

            var undo = function() {
              $transform.set(domElement, tS || tO);
            };

            var setup = function() {
              moving = true;
              rS = domElement.getBoundingClientRect();
              tS = $transform.get(domElement);
              $element.addClass('ui-drag-move');
            };

            var createDragInfo = function(touch) {
              touch = angular.extend({}, touch);
              touch.originalTransform = tO;
              touch.originalRect = rO;
              touch.startRect = rS;
              touch.rect = domElement.getBoundingClientRect();
              touch.startTransform = tS;
              touch.transform = $transform.get(domElement);
              touch.reset = reset;
              touch.undo = undo;
              return touch;
            };

            var onTouchMove = function(touch, event) {
              // preventDefault no matter what
              // it is (ie. maybe html5 drag for images or scroll)
              event.preventDefault();

              // $touch calls start on the first touch
              // to ensure $drag.start is called only while actually
              // dragging and not for touches we will bind $drag.start
              // to the first time move is called

              if (isMoving()) { // drag move
                touch = createDragInfo(touch);

                var transform = transformEventHandler($element, angular.extend({}, touch.transform), touch, event);

                $transform.set(domElement, transform);

                if (moveEventHandler) {
                  moveEventHandler(touch, event);
                }
              } else { // drag start
                setup();
                if (startEventHandler) {
                  startEventHandler(createDragInfo(touch), event);
                }
              }
            };

            var onTouchEnd = function(touch, event) {
              if (!isMoving()) {
                return;
              }

              // prevents outer swipes
              event.__UiSwipeHandled__ = true;

              touch = createDragInfo(touch);
              cleanup();

              if (endEventHandler) {
                endEventHandler(touch, event);
              }
            };

            var onTouchCancel = function(touch, event) {
              if (!isMoving()) {
                return;
              }

              touch = createDragInfo(touch);
              undo(); // on cancel movement is undoed automatically;
              cleanup();

              if (cancelEventHandler) {
                cancelEventHandler(touch, event);
              }
            };

            return $touch.bind($element,
            {move: onTouchMove, end: onTouchEnd, cancel: onTouchCancel},
            touchOptions);
          }