Skip to content

Instantly share code, notes, and snippets.

@rootscity
Created February 7, 2016 05:24
Show Gist options
  • Save rootscity/fcf909f5820407a67c8e to your computer and use it in GitHub Desktop.
Save rootscity/fcf909f5820407a67c8e to your computer and use it in GitHub Desktop.
angular-material modal drag directive
// Usage
//
//<md-dialog rc-drag="md-toolbar" ng-cloak>
// <form>
// <md-toolbar>
// ...
// </md-toolbar>
// <md-dialog-content>
// ...
// </md-dialog-content>
// </form>
//</md-dialog>
function rcDragDirective($window, $document) {
'ngInject';
const moveThreshold = 100;
let documentListenersActive = false;
let rAFPending = false;
let mouseStart = null;
let mouseLast = null;
let mouseDelta = {x: 0, y: 0};
let offset = {x: 0, y: 0};
let target;
function setupDocumentListeners() {
if (!documentListenersActive) {
$document.on('mousemove', mousemove);
$document.on('mouseup', mouseup);
documentListenersActive = true;
}
}
function takedownDocumentListeners() {
if (documentListenersActive) {
$document.off('mousemove', mousemove);
$document.off('mouseup', mouseup);
documentListenersActive = false;
}
}
function updateViewport() {
target.css('transform', 'translate('+ (offset.x + mouseDelta.x) +'px,'+ (offset.y + mouseDelta.y) +'px)');
}
function requestUpdateViewport() {
if (!rAFPending) {
$window.requestAnimationFrame(function() {
updateViewport();
rAFPending = false;
});
rAFPending = true;
}
}
function mousedown(ev) {
mouseStart = {x: ev.pageX, y: ev.pageY};
mouseLast = mouseStart;
setupDocumentListeners();
}
function mousemove(ev) {
if (mouseLast === null || Math.abs(ev.pageX - mouseLast.x) > moveThreshold || Math.abs(ev.pageY - mouseLast.y) > moveThreshold) {
mouseStart = null;
mouseup();
}
else {
mouseLast = {x: ev.pageX, y: ev.pageY};
mouseDelta = {x: (ev.pageX - mouseStart.x), y: (ev.pageY - mouseStart.y)};
requestUpdateViewport();
}
}
function mouseup() {
if (mouseStart !== null) {
offset.x += mouseDelta.x;
offset.y += mouseDelta.y;
mouseDelta = {x: 0, y: 0};
}
mouseStart = null;
mouseLast = null;
takedownDocumentListeners();
}
function link(scope, elem, attrs) {
target = elem;
angular.element(elem[0].querySelector(attrs.rcDrag)).bind('mousedown', mousedown);
scope.$on('$destroy', function() {
takedownDocumentListeners();
});
}
return {
restrict: 'A',
link: link
};
}
export default rcDragDirective;
@swizzmagik
Copy link

Love this thank you so much!

@bdenham
Copy link

bdenham commented Jul 25, 2017

Thanks, just found this and it's nice. Just trying to figure out out to set a containment area (as provided with the JQuery's draggable) so the dialog box doesn't get moved and let go outside of the viewport. If you have any tips, let me know. Thanks.

@AndreyBespamyatnov
Copy link

Thanks a lot!

@cmark11
Copy link

cmark11 commented Apr 7, 2018

Can this be updated or work with mat-dialog?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment