Last active
September 3, 2015 17:20
-
-
Save DavidSouther/20e89d7fdc9af99fcf58 to your computer and use it in GitHub Desktop.
An Angular 1.x dragging directive. The drag directive has several callback attributes available, the main being drag itself. For every drag event, the component has an opportunity to update itself.
This file contains hidden or 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
var log = debug('draggable'); | |
function Draggable(element, scope){ | |
var apply; | |
if(scope.$apply){ | |
apply = function(fn){ | |
return function(){ | |
var context = this; | |
var args = arguments; | |
scope.$apply(function(){ | |
switch(args.length){ | |
case 0: fn.call(context); break; | |
case 1: fn.call(context, args[0]); break; | |
case 2: fn.call(context, args[0], args[1]); break; | |
default: fn.apply(context, args); | |
} | |
}); | |
}; | |
}; | |
} else { | |
apply = function(fn){ | |
return fn; | |
}; | |
} | |
scope.startDrag = scope.startDrag || angular.noop; | |
scope.stopDrag = scope.stopDrag || angular.noop; | |
scope.drag = scope.drag || angular.noop; | |
element.addEventListener('mousedown', this.down = apply(function(evt){ | |
stopEvent(evt); | |
log('Down'); | |
scope.dragging = true; | |
scope.dragStart({'$event': evt}); | |
document.addEventListener('mouseup', this.up = apply(function(evt){ | |
// stopEvent(evt); | |
if(!scope.dragging){ return; } | |
log('Up'); | |
scope.dragStop({'$event': evt}); | |
scope.dragging = false; | |
this.remove(); | |
}.bind(this)), false); | |
document.addEventListener('mouseout', this.out = apply(function(evt){ | |
// stopEvent(evt); | |
if(evt.toElement !== document.children[0]){ return ; }// Exiting the document | |
if(!scope.dragging){ return; } | |
log('Out'); | |
scope.dragStop({'$event': evt}); | |
scope.dragging = false; | |
this.remove(); | |
}.bind(this)), false); | |
document.addEventListener('mousemove', this.move = apply(function(evt){ | |
stopEvent(evt); | |
log('Moving'); | |
if(!scope.dragging){ return; } | |
log('Dragging'); | |
scope.drag({'$event': evt}); | |
}.bind(this)), false); | |
}.bind(this)), false); | |
if(scope.$on){ | |
scope.$on('$destroy', function(){ | |
this.destroy(); | |
}.bind(this)); | |
} | |
} | |
Draggable.prototype.destroy = function(){ | |
if(!this.element){ | |
// The element is already destroyed? | |
return; | |
} | |
this.element.removeEventListener('mousedown', this.down); | |
this.remove(); | |
}; | |
Draggable.prototype.remove = function(){ | |
document.removeEventListener('mouseup', this.up); | |
document.removeEventListener('mouseout', this.out); | |
document.removeEventListener('mousemove', this.move); | |
}; | |
function Drag(){ | |
this.restrict = 'A'; | |
this.scope = { | |
dragStart: '&', | |
dragStop: '&', | |
drag: '&' | |
}; | |
} | |
Drag.prototype.link = function(scope, elem){ | |
new Draggable(elem[0], scope); | |
}; | |
Drag.factory = function(){ | |
return new Drag(); | |
}; | |
angular.module('ttop.util.drag', [ | |
]) | |
.value('Draggable', Draggable) | |
.directive('drag', Drag.factory) | |
; | |
function stopEvent(evt){ | |
if(evt.stopPropagation){evt.stopPropagation();} | |
if(evt.preventDefault){evt.preventDefault();} | |
evt.returnValue = false; | |
} |
This file contains hidden or 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
function Token(){ | |
this.templateUrl = 'map/token'; | |
this.controller = TokenController; | |
this.scope = { | |
x: '=', | |
y: '=', | |
name: '=', | |
color: '=' | |
}; | |
this.link = function(scope, iElement, iAttrs, controller){ | |
controller.element = iElement[0]; | |
}; | |
} | |
TokenController.$inject = ['$timeout']; | |
function TokenController($timeout){ | |
this.isDetailsVisible = false; | |
} | |
TokenController.prototype = Object.create({ | |
moveToken: function($event){ | |
var zoom = this.figureZoom(); | |
this.x += $event.movementX / 48 / zoom.scaleX; | |
this.y += $event.movementY / 48 / zoom.scaleY; | |
}, | |
figureZoom: function(){ | |
var e = this.element; | |
while(e.parentElement.nodeName !== "MAP"){ e = e.parentElement; }; | |
var transform = window.getComputedStyle(e).transform; | |
var matrix = transform.match(/matrix\((.*)\)/)[1].split(','); | |
// Should expand to useing a full decomposition, but no rotations | |
return { | |
scaleX: matrix[0], | |
scaleY: matrix[3] | |
} | |
} | |
}); | |
angular.module('ttop.map.token', [ | |
'ttop.util.drag', | |
'map.token.template' | |
]) | |
.component('token', Token) | |
.filter('shortName', function(){ | |
return function(name){ | |
return name.charAt(0); | |
}; | |
}) | |
; |
This file contains hidden or 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
md-card( | |
drag="state.moveToken($event);" | |
style="\ | |
position: absolute;\ | |
top: {{ state.y * 48 }};\ | |
left: {{ state.x * 48 }};\ | |
width: 48;\ | |
height: 48;\ | |
background: {{state.color}};\ | |
border: 2px solid black;\ | |
border-radius: {{ state.scale / 4}};\ | |
display: table;\ | |
" | |
) | |
div( | |
style="display: table-cell; vertical-align: middle; text-align: center;" | |
) | |
div | |
| {{ state.name | shortName }} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment