Created
February 20, 2014 22:51
-
-
Save dtothefp/9124970 to your computer and use it in GitHub Desktop.
Vanilla JS Draggable Directive
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module = angular.module 'draggable', [] | |
module.controller "dragDropCtrl", ($scope) -> | |
$scope.dropPosition = null | |
module.directive 'pixbiDraggable', ($timeout) -> | |
restrict: 'A' | |
controller: 'dragDropCtrl' | |
scope: { | |
dropPosition: "=" | |
} | |
transclude: true | |
replace: true | |
# Did not make template because when replace is set to true Angular throws an error "must have exactly one root element" | |
template: ''' | |
<div class="draggable" ng-transclude ng-mousedown="makeDraggable($event)" ng-mouseenter="makeCursor()" ng-mouseleave="removeCursor()" ng-mousemove="animateDrag($event)" ng-mouseup="stopDraggable($event)"> | |
</div> | |
''' | |
link: ($scope, $element, $attributes) -> | |
draggable = false | |
elm = $element[0] | |
initialMousePosition = {} | |
offsetX = 0 | |
offsetY = 0 | |
totalX = 0 | |
totalY = 0 | |
lastX = 0 | |
lastY = 0 | |
elmAttrs = null | |
initialElmPos = {} | |
getElmAttr = -> | |
elmAttrs = { | |
top: elm.offsetTop | |
left: elm.offsetLeft | |
width: elm.offsetWidth | |
height: elm.offsetHeight | |
} | |
# TODO Element position/size is not correct upon initial execution of link function. Currently, using timeout to find attributes after link | |
$timeout( getElmAttr, 500) | |
$scope.makeDraggable = (e) -> | |
draggable = true | |
initialElmPos = { | |
top: elm.offsetTop | |
left: elm.offsetLeft | |
} | |
initialMousePosition = | |
x: e.pageX | |
y: e.pageY | |
$scope.animateDrag = (e) -> | |
e.preventDefault(); | |
if draggable | |
elm.style.transform = elm.style.webkitTransform = "translate3d(#{totalX + (e.pageX - initialMousePosition.x)}px, #{totalY + (e.pageY - initialMousePosition.y)}px, 0)" | |
offsetX = e.pageX - initialMousePosition.x | |
offsetY = e.pageY - initialMousePosition.y | |
elmAttrs.top += offsetY - lastY | |
elmAttrs.left += offsetX - lastX | |
if checkDragPos elmAttrs, $scope.dropPosition | |
elm.style.transition = "all 1s ease" | |
# TODO Elements are stacking on top of one another, fix layout of where want elements to end up | |
elm.style.transform = elm.style.webkitTransform = "translate3d(" + ($scope.dropPosition.left + ( $scope.dropPosition.width / 2 ) - (elmAttrs.width / 3)) + "px, " + ($scope.dropPosition.top + ( $scope.dropPosition.height / 2 ) - (elmAttrs.height / 3)) + "px, 0)" | |
draggable = false | |
lastY = offsetY | |
lastX = offsetX | |
$scope.stopDraggable = (e) -> | |
if draggable | |
elm.style.transition = "all 1s ease" | |
elm.style.transform = elm.style.webkitTransform = "translate3d(#{initialElmPos.left}px, 0, 0)" | |
draggable = false | |
totalX += offsetX | |
totalY += offsetY | |
lastX = 0 | |
lastY = 0 | |
checkDragPos = (draggablePos, dropablePos ) -> | |
# TODO Currently only checking if element has entered bucked bounds from the left. Would want to check top, bottom, right depending upon layout | |
if draggablePos.left + draggablePos.width >= dropablePos["left"] | |
true | |
else if draggablePos.top <= (dropablePos.top + dropablePos.height) and draggablePos.left >= dropablePos.left | |
true | |
else | |
false | |
module.directive 'pixbiDropable', ($timeout) -> | |
restrict: "A" | |
controller: 'dragDropCtrl' | |
transclude: true | |
replace: true | |
template: ''' | |
<div class="dropable"></div> | |
''' | |
scope: | |
dropPosition: "=" | |
link: ($scope, $element, $attributes) -> | |
elm = $element[0] | |
$scope.dropPosition = null | |
checkPos = -> | |
$scope.dropPosition = | |
top: elm.offsetTop | |
left: elm.offsetLeft | |
width: elm.offsetWidth | |
height: elm.offsetHeight | |
# TODO Element position/size is not correct upon initial execution of link function. Currently, using timeout to find attributes after link | |
$timeout checkPos, 500 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment