From 866fd1aa33b7e761c1ee90fa2e81846bd8607d2b Mon Sep 17 00:00:00 2001 From: Cory Locklear Date: Mon, 8 Dec 2014 21:30:03 -0500 Subject: [PATCH 01/73] Allow for drag handle(s) to be specified as child element -- Allow ng-drop to specify arbitrary object data that will be passed as third param to drop callback. --- ngDraggable.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index ea15411..a98fd50 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -14,6 +14,7 @@ angular.module("ngDraggable", []) var _pressEvents = 'touchstart mousedown'; var _moveEvents = 'touchmove mousemove'; var _releaseEvents = 'touchend mouseup'; + var _dragHandle; var $document = $(document); var $window = $(window); @@ -27,6 +28,11 @@ angular.module("ngDraggable", []) var initialize = function () { element.attr('draggable', 'false'); // prevent native drag + // check to see if drag handle(s) was specified + var dragHandles = element.find('[ng-drag-handle]'); + if (dragHandles.length) { + _dragHandle = dragHandles; + } toggleListeners(true); }; @@ -42,7 +48,14 @@ angular.module("ngDraggable", []) //attrs.$observe('ngCenterAnchor', onCenterAnchor); scope.$watch(attrs.ngCenterAnchor, onCenterAnchor); scope.$watch(attrs.ngDragData, onDragDataChange); - element.on(_pressEvents, onpress); + // wire up touch events + if (_dragHandle) { + // handle(s) specified, use those to initiate drag + _dragHandle.on(_pressEvents, onpress); + } else { + // no handle(s) specified, use the element as the handle + element.on(_pressEvents, onpress); + } if(! _hasTouch && element[0].nodeName.toLowerCase() == "img"){ element.on('mousedown', function(){ return false;}); // prevent native drag for images } @@ -224,7 +237,7 @@ angular.module("ngDraggable", []) // onDropCallback(scope, {$data: obj.data, $event: evt}); // }); $timeout(function(){ - onDropCallback(scope, {$data: obj.data, $event: obj}); + onDropCallback(scope, {$data: obj.data, $event: obj, $target: scope.$eval(scope.value)}); }); From f97384158d1402638a5ad116738addd17b8aa585 Mon Sep 17 00:00:00 2001 From: Scott Herndon Date: Mon, 22 Dec 2014 08:38:30 -0800 Subject: [PATCH 02/73] - removed dependency on jQuery - inject $window and $document instead of creating local vars for them - prevent duplicate drop events when element has both ng-drag and ng-drop behavior - don't move the drag element in the initial press, wait till dragging starts - don't clobber margin of drag element when moving it --- README.md | 3 +- example-cancel.html | 1 - example-clone.html | 10 --- example-reorder.html | 2 - example.html | 1 - ngDraggable.js | 158 ++++++++++++++++++++++++++----------------- 6 files changed, 97 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 1a3cecb..00963bd 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,9 @@ Drag and drop module for Angular JS with support for touch devices. [`demo`](htt ### Usage: - Install: `bower install ngDraggable` -- Add `jquery`, `angular` and `ngDraggable` to your code: +- Add `angular` and `ngDraggable` to your code: ```html - ``` diff --git a/example-cancel.html b/example-cancel.html index 428ddbe..307e35d 100755 --- a/example-cancel.html +++ b/example-cancel.html @@ -120,7 +120,6 @@

Cancel drag from child element.

footer
- + + + + + ``` From 14f3d7e63684e178e8582a8381b8603158129c2f Mon Sep 17 00:00:00 2001 From: phil Date: Mon, 5 Jan 2015 10:59:38 +1100 Subject: [PATCH 07/73] updated touch detection --- ngDraggable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ngDraggable.js b/ngDraggable.js index 7e79134..5b0d41d 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -9,7 +9,7 @@ angular.module("ngDraggable", []) link: function (scope, element, attrs) { scope.value = attrs.ngDrag; var offset,_centerAnchor=false,_mx,_my,_tx,_ty,_mrx,_mry; - var _hasTouch = ('ontouchstart' in document.documentElement); + var _hasTouch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch; var _pressEvents = 'touchstart mousedown'; var _moveEvents = 'touchmove mousemove'; var _releaseEvents = 'touchend mouseup'; From 193f11fb33254425d214ba7777688b04924895f6 Mon Sep 17 00:00:00 2001 From: Janek Lasocki-Biczysko Date: Fri, 9 Jan 2015 16:04:27 +0000 Subject: [PATCH 08/73] Added 'ngDraggable' service, fixed pageX/Y detection --- ngDraggable.js | 70 ++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 5b0d41d..c32e213 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -3,7 +3,35 @@ * https://github.com/fatlinesofcode/ngDraggable */ angular.module("ngDraggable", []) - .directive('ngDrag', ['$rootScope', '$parse', '$document', '$window', function ($rootScope, $parse, $document, $window) { + .service('ngDraggable', ['$window', function($window) { + + var isDef = function(val) { return typeof val !== 'undefined'; }; + + this.getEventProp = function getEventProp(evt, prop, skipOriginal) { + if (isDef(evt.touches) && evt.touches[0]) { + return evt.touches[0][prop]; + } + if (isDef(evt[prop])) { + return evt[prop]; + } + if (evt.originalEvent && !skipOriginal) { + return this.getEventProp(evt.originalEvent, prop, true); + } + }; + + this.getPrivOffset = function getPrivOffset(docElem) { + var box = { top: 0, left: 0 }; + if (isDef(docElem[0].getBoundingClientRect)) { + box = docElem[0].getBoundingClientRect(); + } + return { + top: box.top + $window.pageYOffset - docElem[0].clientTop, + left: box.left + $window.pageXOffset - docElem[0].clientLeft + }; + } + + }]) + .directive('ngDrag', ['$rootScope', '$parse', '$document', '$window', 'ngDraggable', function ($rootScope, $parse, $document, $window, ngDraggable) { return { restrict: 'A', link: function (scope, element, attrs) { @@ -28,19 +56,6 @@ angular.module("ngDraggable", []) element.attr('draggable', 'false'); // prevent native drag toggleListeners(true); }; - - // this same func is in ngDrop, it needs to be DRYed up but don't know if its - // worth writing a service (or equivalent) for one function - var _privoffset = function (docElem) { - var box = { top: 0, left: 0 }; - if (typeof docElem[0].getBoundingClientRect !== undefined) { - box = docElem[0].getBoundingClientRect(); - } - return { - top: box.top + $window.pageYOffset - docElem[0].clientTop, - left: box.left + $window.pageXOffset - docElem[0].clientLeft - }; - } var toggleListeners = function (enable) { if (!enable)return; @@ -110,13 +125,13 @@ angular.module("ngDraggable", []) if(! _dragEnabled)return; evt.preventDefault(); element.addClass('dragging'); - offset = _privoffset(element); + offset = ngDraggable.getPrivOffset(element); element.centerX = element[0].offsetWidth / 2; element.centerY = element[0].offsetHeight / 2; - _mx = (evt.pageX || evt.touches[0].pageX); - _my = (evt.pageY || evt.touches[0].pageY); + _mx = ngDraggable.getEventProp(evt, 'pageX'); + _my = ngDraggable.getEventProp(evt, 'pageY'); _mrx = _mx - offset.left; _mry = _my - offset.top; if (_centerAnchor) { @@ -136,8 +151,8 @@ angular.module("ngDraggable", []) if (!_dragEnabled)return; evt.preventDefault(); - _mx = (evt.pageX || evt.touches[0].pageX); - _my = (evt.pageY || evt.touches[0].pageY); + _mx = ngDraggable.getEventProp(evt, 'pageX'); + _my = ngDraggable.getEventProp(evt, 'pageY'); if (_centerAnchor) { _tx = _mx - element.centerX - $window.pageXOffset; @@ -186,7 +201,7 @@ angular.module("ngDraggable", []) } }]) - .directive('ngDrop', ['$parse', '$timeout', '$window', function ($parse, $timeout, $window) { + .directive('ngDrop', ['$parse', '$timeout', '$window', 'ngDraggable', function ($parse, $timeout, $window, ngDraggable) { return { restrict: 'A', link: function (scope, element, attrs) { @@ -214,19 +229,6 @@ angular.module("ngDraggable", []) scope.$on('draggable:move', onDragMove); scope.$on('draggable:end', onDragEnd); }; - - // this same func is in ngDrag, it needs to be DRYed up but don't know if its - // worth writing a service (or equivalent) for one function - var _privoffset = function (docElem) { - var box = { top: 0, left: 0 }; - if (typeof docElem[0].getBoundingClientRect !== undefined) { - box = docElem[0].getBoundingClientRect(); - } - return { - top: box.top + $window.pageYOffset - docElem[0].clientTop, - left: box.left + $window.pageXOffset - docElem[0].clientLeft - }; - } var onDestroy = function (enable) { toggleListeners(false); @@ -277,7 +279,7 @@ angular.module("ngDraggable", []) } var hitTest = function(x, y) { - var bounds = _privoffset(element); + var bounds = ngDraggable.getPrivOffset(element); bounds.right = bounds.left + element[0].offsetWidth; bounds.bottom = bounds.top + element[0].offsetHeight; return x >= bounds.left From 5b6225de47d1d840c4eca270d6e50e036524910b Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Wed, 14 Jan 2015 10:59:06 +1100 Subject: [PATCH 09/73] version bump --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 69ecbe1..2387b1d 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.0.3", + "version": "0.0.31", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", From 3bec9d8e7bc8529d6abf2a3b9c09cfa1b16215f5 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 19 Jan 2015 20:21:25 -0600 Subject: [PATCH 10/73] Fixed issue #73: Problems with matrix3d transform on parent elements --- ngDraggable.js | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index c32e213..116199f 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -43,9 +43,11 @@ angular.module("ngDraggable", []) var _releaseEvents = 'touchend mouseup'; // to identify the element in order to prevent getting superflous events when a single element has both drag and drop directives on it. - var _myid = scope.$id; + var _myid = scope.$id; var _data = null; + var _dragOffset = null; + var _dragEnabled = false; var _pressTimer = null; @@ -61,8 +63,8 @@ angular.module("ngDraggable", []) if (!enable)return; // add listeners. - scope.$on('$destroy', onDestroy); - scope.$watch(attrs.ngDrag, onEnableChange); + scope.$on('$destroy', onDestroy); + scope.$watch(attrs.ngDrag, onEnableChange); scope.$watch(attrs.ngCenterAnchor, onCenterAnchor); scope.$watch(attrs.ngDragData, onDragDataChange); element.on(_pressEvents, onpress); @@ -83,7 +85,7 @@ angular.module("ngDraggable", []) if(angular.isDefined(newVal)) _centerAnchor = (newVal || 'true'); } - + var isClickableElement = function (evt) { return ( angular.isDefined(angular.element(evt.target).attr("ng-click")) @@ -126,10 +128,11 @@ angular.module("ngDraggable", []) evt.preventDefault(); element.addClass('dragging'); offset = ngDraggable.getPrivOffset(element); + _dragOffset = offset; element.centerX = element[0].offsetWidth / 2; - element.centerY = element[0].offsetHeight / 2; - + element.centerY = element[0].offsetHeight / 2; + _mx = ngDraggable.getEventProp(evt, 'pageX'); _my = ngDraggable.getEventProp(evt, 'pageY'); _mrx = _mx - offset.left; @@ -140,8 +143,8 @@ angular.module("ngDraggable", []) } else { _tx = _mx - _mrx - $window.pageXOffset; _ty = _my - _mry - $window.pageYOffset; - } - + } + $document.on(_moveEvents, onmove); $document.on(_releaseEvents, onrelease); $rootScope.$broadcast('draggable:start', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data}); @@ -154,12 +157,12 @@ angular.module("ngDraggable", []) _mx = ngDraggable.getEventProp(evt, 'pageX'); _my = ngDraggable.getEventProp(evt, 'pageY'); - if (_centerAnchor) { - _tx = _mx - element.centerX - $window.pageXOffset; - _ty = _my - element.centerY - $window.pageYOffset; + if (_centerAnchor) { + _tx = _mx - element.centerX - _dragOffset.left; + _ty = _my - element.centerY - _dragOffset.top; } else { - _tx = _mx - _mrx - $window.pageXOffset; - _ty = _my - _mry - $window.pageYOffset; + _tx = _mx - _mrx - $rootScope.tempStartOffset.left; + _ty = _my - _mry - $rootScope.tempStartOffset.top; } moveElement(_tx, _ty); @@ -187,13 +190,13 @@ angular.module("ngDraggable", []) } var reset = function() { - element.css({left:'',top:'', position:'', 'z-index':'', margin: ''}); + element.css({transform:'', 'z-index':''}); } var moveElement = function (x, y) { element.css({ - left: (x+'px'), top: (y+'px'), position: 'fixed', 'z-index': 99999 - //,margin: '0' don't monkey with the margin, + transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999 + //,margin: '0' don't monkey with the margin, }); } initialize(); @@ -246,7 +249,7 @@ angular.module("ngDraggable", []) } var onDragEnd = function (evt, obj) { - + // don't listen to drop events if this is the element being dragged if (!_dropEnabled || _myid === obj.uid)return; if (isTouching(obj.x, obj.y, obj.element)) { @@ -358,7 +361,7 @@ angular.module("ngDraggable", []) var moveElement = function(x,y) { element.css({ left: (x+'px'), top: (y+'px'), position: 'fixed', 'z-index': 99999, 'visibility': 'visible' - //,margin: '0' don't monkey with the margin, + //,margin: '0' don't monkey with the margin, }); } From 38fbebc9940fc098b7c678c6487cebcbdfb6f51f Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 19 Jan 2015 22:13:02 -0600 Subject: [PATCH 11/73] Forgot to update one test variable --- ngDraggable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 116199f..6fcc4b6 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -161,8 +161,8 @@ angular.module("ngDraggable", []) _tx = _mx - element.centerX - _dragOffset.left; _ty = _my - element.centerY - _dragOffset.top; } else { - _tx = _mx - _mrx - $rootScope.tempStartOffset.left; - _ty = _my - _mry - $rootScope.tempStartOffset.top; + _tx = _mx - _mrx - _dragOffset.left; + _ty = _my - _mry - _dragOffset.top; } moveElement(_tx, _ty); From 59bb0a77269d7605f4c79792a933b73776b78b1b Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Tue, 20 Jan 2015 00:42:00 -0600 Subject: [PATCH 12/73] Fixed clone --- example-clone.html | 4 ++-- ngDraggable.js | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/example-clone.html b/example-clone.html index 4dce037..cf5a975 100755 --- a/example-clone.html +++ b/example-clone.html @@ -88,7 +88,7 @@

ngDraggable Clone Example

{{obj.name}}
-
+
{{draggableObjects[3].name}}

@@ -147,4 +147,4 @@

ngDraggable Clone Example

}); - \ No newline at end of file + diff --git a/ngDraggable.js b/ngDraggable.js index 6fcc4b6..2d5983f 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -195,7 +195,7 @@ angular.module("ngDraggable", []) var moveElement = function (x, y) { element.css({ - transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999 + transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)','z-index': 99999 //,margin: '0' don't monkey with the margin, }); } @@ -295,11 +295,12 @@ angular.module("ngDraggable", []) } } }]) - .directive('ngDragClone', ['$parse', '$timeout', function ($parse, $timeout) { + .directive('ngDragClone', ['$parse', '$timeout', 'ngDraggable', function ($parse, $timeout, ngDraggable) { return { restrict: 'A', link: function (scope, element, attrs) { var img, _allowClone=true; + var _dragOffset = null; scope.clonedData = {}; var initialize = function () { @@ -342,10 +343,16 @@ angular.module("ngDraggable", []) moveElement(obj.tx, obj.ty); } + + _dragOffset = ngDraggable.getPrivOffset(element); } var onDragMove = function(evt, obj) { if(_allowClone) { - moveElement(obj.tx, obj.ty); + + _tx = obj.tx + _dragOffset.left; + _ty = obj.ty + _dragOffset.top; + + moveElement(_tx, _ty); } } var onDragEnd = function(evt, obj) { @@ -360,7 +367,7 @@ angular.module("ngDraggable", []) } var moveElement = function(x,y) { element.css({ - left: (x+'px'), top: (y+'px'), position: 'fixed', 'z-index': 99999, 'visibility': 'visible' + transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999, 'visibility': 'visible' //,margin: '0' don't monkey with the margin, }); } From f0ad85f5ae3956c0409b40894f28c690affd8454 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Thu, 22 Jan 2015 10:38:48 +1100 Subject: [PATCH 13/73] version bump --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 2387b1d..4a82767 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.0.31", + "version": "0.0.4", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", From 1f1c638d201563fa787968691cd84679fa5a28bc Mon Sep 17 00:00:00 2001 From: Alex Wait Date: Fri, 24 Oct 2014 11:01:21 -0700 Subject: [PATCH 14/73] Adding ng-drag-start and ng-drag-move events. --- ngDraggable.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ngDraggable.js b/ngDraggable.js index 2d5983f..8eff9da 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -216,6 +216,9 @@ angular.module("ngDraggable", []) var onDropCallback = $parse(attrs.ngDropSuccess);// || function(){}; + var onDragStartCallback = $parse(attrs.ngDragStart); + var onDragMoveCallback = $parse(attrs.ngDragMove); + var initialize = function () { toggleListeners(true); }; @@ -242,10 +245,17 @@ angular.module("ngDraggable", []) var onDragStart = function(evt, obj) { if(! _dropEnabled)return; isTouching(obj.x,obj.y,obj.element); + + $timeout(function(){ + onDragStartCallback(scope, {$data: obj.data, $event: obj}); + }); } var onDragMove = function(evt, obj) { if(! _dropEnabled)return; isTouching(obj.x,obj.y,obj.element); + $timeout(function(){ + onDragMoveCallback(scope, {$data: obj.data, $event: obj}); + }); } var onDragEnd = function (evt, obj) { From fe46aa4e9c7b7600608f29f8322e55cdca7d7fa1 Mon Sep 17 00:00:00 2001 From: Alex Wait Date: Fri, 24 Oct 2014 11:03:41 -0700 Subject: [PATCH 15/73] Adding missing semicolons. --- ngDraggable.js | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 8eff9da..b468ee5 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -117,12 +117,12 @@ angular.module("ngDraggable", []) onlongpress(evt); } - } + }; var cancelPress = function() { clearTimeout(_pressTimer); $document.off(_moveEvents, cancelPress); $document.off(_releaseEvents, cancelPress); - } + }; var onlongpress = function(evt) { if(! _dragEnabled)return; evt.preventDefault(); @@ -201,7 +201,7 @@ angular.module("ngDraggable", []) } initialize(); } - } + }; }]) .directive('ngDrop', ['$parse', '$timeout', '$window', 'ngDraggable', function ($parse, $timeout, $window, ngDraggable) { @@ -230,7 +230,6 @@ angular.module("ngDraggable", []) // add listeners. attrs.$observe("ngDrop", onEnableChange); scope.$on('$destroy', onDestroy); - //scope.$watch(attrs.uiDraggable, onDraggableChange); scope.$on('draggable:start', onDragStart); scope.$on('draggable:move', onDragMove); scope.$on('draggable:end', onDragEnd); @@ -241,7 +240,7 @@ angular.module("ngDraggable", []) }; var onEnableChange = function (newVal, oldVal) { _dropEnabled=scope.$eval(newVal); - } + }; var onDragStart = function(evt, obj) { if(! _dropEnabled)return; isTouching(obj.x,obj.y,obj.element); @@ -249,7 +248,7 @@ angular.module("ngDraggable", []) $timeout(function(){ onDragStartCallback(scope, {$data: obj.data, $event: obj}); }); - } + }; var onDragMove = function(evt, obj) { if(! _dropEnabled)return; isTouching(obj.x,obj.y,obj.element); @@ -299,11 +298,11 @@ angular.module("ngDraggable", []) && x <= bounds.right && y <= bounds.bottom && y >= bounds.top; - } + }; initialize(); } - } + }; }]) .directive('ngDragClone', ['$parse', '$timeout', 'ngDraggable', function ($parse, $timeout, ngDraggable) { return { @@ -338,9 +337,9 @@ angular.module("ngDraggable", []) img.off('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); // element.on('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); img.on('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); - } + }; var onDragStart = function(evt, obj, elm) { - _allowClone=true + _allowClone=true; if(angular.isDefined(obj.data.allowClone)){ _allowClone=obj.data.allowClone; } @@ -364,17 +363,17 @@ angular.module("ngDraggable", []) moveElement(_tx, _ty); } - } + }; var onDragEnd = function(evt, obj) { //moveElement(obj.tx,obj.ty); if(_allowClone) { reset(); } - } + }; var reset = function() { element.css({left:0,top:0, position:'fixed', 'z-index':-1, visibility:'hidden'}); - } + }; var moveElement = function(x,y) { element.css({ transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999, 'visibility': 'visible' @@ -389,11 +388,11 @@ angular.module("ngDraggable", []) e.cancelBubble = true; e.returnValue = false; return false; - } + }; initialize(); } - } + }; }]) .directive('ngPreventDrag', ['$parse', '$timeout', function ($parse, $timeout) { return { From c037c57a179cd6803b59227be45a2c0bfb2b3f6f Mon Sep 17 00:00:00 2001 From: Alex Wait Date: Fri, 24 Oct 2014 11:48:30 -0700 Subject: [PATCH 16/73] Updating readme. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index fa8a2c6..cde0482 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ Draggable usage:
``` Note: ng-center-anchor is optional. If not specified, it defaults to false. +```ng-drag-start``` and ```ng-drag-move``` is also available. + Drop area usage: ```html From 7fc6366b0cff15eb0196c487cb2d8055b962d6cc Mon Sep 17 00:00:00 2001 From: Alex Wait Date: Fri, 24 Oct 2014 13:05:52 -0700 Subject: [PATCH 17/73] Adding callback that's called when dragging stops and not just when when "successful" (aka moving back to drop container) --- ngDraggable.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ngDraggable.js b/ngDraggable.js index b468ee5..c7584ff 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -217,6 +217,7 @@ angular.module("ngDraggable", []) var onDropCallback = $parse(attrs.ngDropSuccess);// || function(){}; var onDragStartCallback = $parse(attrs.ngDragStart); + var onDragStopCallback = $parse(attrs.ngDragStop); var onDragMoveCallback = $parse(attrs.ngDragMove); var initialize = function () { @@ -271,6 +272,9 @@ angular.module("ngDraggable", []) onDropCallback(scope, {$data: obj.data, $event: obj}); }); } + $timeout(function(){ + onDragStopCallback(scope, {$data: obj.data, $event: obj}); + }); updateDragStyles(false, obj.element); } From 3d4126c6939ebc13e231c57bd8daf85a79917996 Mon Sep 17 00:00:00 2001 From: Alex Wait Date: Fri, 24 Oct 2014 13:08:49 -0700 Subject: [PATCH 18/73] Updated readme to include ng-drag-stop --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index cde0482..9ad0357 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,9 @@ Draggable usage: ``` Note: ng-center-anchor is optional. If not specified, it defaults to false. + ```ng-drag-start``` and ```ng-drag-move``` is also available. +``ng-drag-stop`` can be used when you want to react to the user dragging an item and it wasn't dropped into the target container. Drop area usage: From 2a5df3b50e6638a0f2c4d08c2add27f7937c3ce3 Mon Sep 17 00:00:00 2001 From: James Brauman Date: Mon, 16 Feb 2015 13:36:38 +1100 Subject: [PATCH 19/73] Added functionality to scroll the page when dragging. --- ngDraggable.js | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/ngDraggable.js b/ngDraggable.js index c7584ff..1e816eb 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -438,4 +438,111 @@ angular.module("ngDraggable", []) element.find('*').attr('ng-cancel-drag', 'ng-cancel-drag'); } } + }]) + .directive('ngDragScroll', ['$window', '$interval', '$timeout', '$document', function($window, $interval, $timeout, $document) { + return { + restrict: 'A', + link: function(scope, element, attrs) { + var intervalPromise = null; + var lastMouseEvent = null; + + var config = { + verticalScroll: attrs.verticalScroll || true, + horizontalScroll: attrs.horizontalScroll || true, + activationDistance: attrs.activationDistance || 75, + scrollDistance: attrs.scrollDistance || 50, + scrollInterval: attrs.scrollInterval || 250 + }; + + var createInterval = function() { + intervalPromise = $interval(function() { + if (!lastMouseEvent) return; + + var viewportWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); + var viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); + + var scrollX = 0; + var scrollY = 0; + + if (config.horizontalScroll) { + // If horizontal scrolling is active. + if (lastMouseEvent.clientX < config.activationDistance) { + // If the mouse is on the left of the viewport within the activation distance. + scrollX = -config.scrollDistance; + } + else if (lastMouseEvent.clientX > viewportWidth - config.activationDistance) { + // If the mouse is on the right of the viewport within the activation distance. + scrollX = config.scrollDistance; + } + } + + if (config.verticalScroll) { + // If vertical scrolling is active. + if (lastMouseEvent.clientY < config.activationDistance) { + // If the mouse is on the top of the viewport within the activation distance. + scrollY = -config.scrollDistance; + } + else if (lastMouseEvent.clientY > viewportHeight - config.activationDistance) { + // If the mouse is on the bottom of the viewport within the activation distance. + scrollY = config.scrollDistance; + } + } + + if (scrollX !== 0 || scrollY !== 0) { + // Record the current scroll position. + var currentScrollLeft = $(document).scrollLeft(); + var currentScrollTop = $(document).scrollTop(); + + // Remove the transformation from the element, scroll the window by the scroll distance + // record how far we scrolled, then reapply the element transformation. + var elementTransform = element.css('transform'); + element.css('transform', 'initial'); + + $window.scrollBy(scrollX, scrollY); + + var horizontalScrollAmount = $(document).scrollLeft() - currentScrollLeft; + var verticalScrollAmount = $(document).scrollTop() - currentScrollTop; + + element.css('transform', elementTransform); + + // On the next digest cycle, trigger a mousemove event equal to the amount we scrolled so + // the element moves correctly. + $timeout(function() { + lastMouseEvent.pageX += horizontalScrollAmount; + lastMouseEvent.pageY += verticalScrollAmount; + + $document.trigger(lastMouseEvent); + }); + } + + }, config.scrollInterval); + }; + + var clearInterval = function() { + $interval.cancel(intervalPromise); + intervalPromise = null; + }; + + scope.$on('draggable:start', function(event, obj) { + // Ignore this event if it's not for this element. + if (obj.element[0] !== element[0]) return; + + if (!intervalPromise) createInterval(); + }); + + scope.$on('draggable:end', function(event, obj) { + // Ignore this event if it's not for this element. + if (obj.element[0] !== element[0]) return; + + if (intervalPromise) clearInterval(); + }); + + scope.$on('draggable:move', function(event, obj) { + // Ignore this event if it's not for this element. + if (obj.element[0] !== element[0]) return; + + lastMouseEvent = obj.event; + }); + } + } }]); From 00d3de4d3ed73e83d80d8a16ce616f7efb677a57 Mon Sep 17 00:00:00 2001 From: gregvis Date: Thu, 19 Feb 2015 16:21:17 -0500 Subject: [PATCH 20/73] Added -webkit-transform to css transform operations. -webkit-transform is needed for older browsers/webkits that do not support the native transform. This is especially needed for Cordova apps which target older webkits on iOS and Android. --- ngDraggable.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index c7584ff..ee1c971 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -190,12 +190,13 @@ angular.module("ngDraggable", []) } var reset = function() { - element.css({transform:'', 'z-index':''}); + element.css({transform:'', 'z-index':'', '-webkit-transform':''}); } var moveElement = function (x, y) { element.css({ - transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)','z-index': 99999 + transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)','z-index': 99999, + '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)' //,margin: '0' don't monkey with the margin, }); } @@ -380,7 +381,8 @@ angular.module("ngDraggable", []) }; var moveElement = function(x,y) { element.css({ - transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999, 'visibility': 'visible' + transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999, 'visibility': 'visible', + '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)' //,margin: '0' don't monkey with the margin, }); } From b5bc602cd21462300eec701f6d78a74f5ae8119e Mon Sep 17 00:00:00 2001 From: "J.Trotoux" Date: Mon, 23 Feb 2015 16:13:14 +0100 Subject: [PATCH 21/73] Update ngDraggable.js I am using Boostrap framwork to set my Modules. Modul width is set to 100% to adapt to columns. While dragging, module is set to "fixed position" and its width is changing to 100%. I also add width while dragging to prevent from fixed position. After dradding, i set back initial width. --- ngDraggable.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ngDraggable.js b/ngDraggable.js index c7584ff..cd8eac0 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -127,6 +127,7 @@ angular.module("ngDraggable", []) if(! _dragEnabled)return; evt.preventDefault(); element.addClass('dragging'); + element.width(element.width()); // prevent from fixed position offset = ngDraggable.getPrivOffset(element); _dragOffset = offset; @@ -176,6 +177,7 @@ angular.module("ngDraggable", []) evt.preventDefault(); $rootScope.$broadcast('draggable:end', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data, callback:onDragComplete, uid: _myid}); element.removeClass('dragging'); + element.css("width","initial"); // prevent from fixed position reset(); $document.off(_moveEvents, onmove); $document.off(_releaseEvents, onrelease); From 3960596777c33b77a0463331209f715c0dc01ad4 Mon Sep 17 00:00:00 2001 From: Juha Karttunen Date: Mon, 23 Feb 2015 23:32:20 +0200 Subject: [PATCH 22/73] Update README.md with mention of events. Closes #94 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9ad0357..c91bf4d 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ Note: ng-center-anchor is optional. If not specified, it defaults to false. ```ng-drag-start``` and ```ng-drag-move``` is also available. ``ng-drag-stop`` can be used when you want to react to the user dragging an item and it wasn't dropped into the target container. +```draggable:start```, ```draggable:move``` and ```draggable:end``` events are broadcasted on drag actions. + Drop area usage: ```html From 388faa611ae81aba1cc00eb7276997e44dea0b6c Mon Sep 17 00:00:00 2001 From: Yongning Liang Date: Fri, 27 Feb 2015 14:34:23 +0800 Subject: [PATCH 23/73] fix issue #78 drag-enter class isn't removed from the dragged element after the drag ends. --- ngDraggable.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ngDraggable.js b/ngDraggable.js index c7584ff..4fbd219 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -176,6 +176,7 @@ angular.module("ngDraggable", []) evt.preventDefault(); $rootScope.$broadcast('draggable:end', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data, callback:onDragComplete, uid: _myid}); element.removeClass('dragging'); + element.closest('.drag-enter').removeClass('drag-enter'); reset(); $document.off(_moveEvents, onmove); $document.off(_releaseEvents, onrelease); From 89e704368fc84d38beba939b72e363a61251ffe8 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Thu, 5 Mar 2015 09:47:20 +1100 Subject: [PATCH 24/73] version bump --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 4a82767..b4fbfc4 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.0.4", + "version": "0.0.4.1", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", From f3b38883fd6fbfa6d005d07472dcf4162930295e Mon Sep 17 00:00:00 2001 From: Ian Collins Date: Mon, 9 Mar 2015 12:56:11 -0400 Subject: [PATCH 25/73] update styles on drop if drag and drop elements are the same --- ngDraggable.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ngDraggable.js b/ngDraggable.js index ad28565..26545af 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -263,7 +263,11 @@ angular.module("ngDraggable", []) var onDragEnd = function (evt, obj) { // don't listen to drop events if this is the element being dragged - if (!_dropEnabled || _myid === obj.uid)return; + // only update the styles and return + if (!_dropEnabled || _myid === obj.uid) { + updateDragStyles(false, obj.element); + return; + } if (isTouching(obj.x, obj.y, obj.element)) { // call the ngDraggable ngDragSuccess element callback if(obj.callback){ From 33d28984b46466eb88b58c3523db4489892dfc79 Mon Sep 17 00:00:00 2001 From: Ian Collins Date: Mon, 9 Mar 2015 15:49:17 -0400 Subject: [PATCH 26/73] added IE9 CSS support --- ngDraggable.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 26545af..3c3eefe 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -176,7 +176,7 @@ angular.module("ngDraggable", []) evt.preventDefault(); $rootScope.$broadcast('draggable:end', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data, callback:onDragComplete, uid: _myid}); element.removeClass('dragging'); - element.closest('.drag-enter').removeClass('drag-enter'); + element.parent().find('.drag-enter').removeClass('drag-enter'); reset(); $document.off(_moveEvents, onmove); $document.off(_releaseEvents, onrelease); @@ -191,13 +191,14 @@ angular.module("ngDraggable", []) } var reset = function() { - element.css({transform:'', 'z-index':'', '-webkit-transform':''}); + element.css({transform:'', 'z-index':'', '-webkit-transform':'', '-ms-transform':''}); } var moveElement = function (x, y) { element.css({ transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)','z-index': 99999, - '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)' + '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', + '-ms-transform': 'matrix(1, 0, 0, 1, '+x+', '+y+')' //,margin: '0' don't monkey with the margin, }); } @@ -387,7 +388,8 @@ angular.module("ngDraggable", []) var moveElement = function(x,y) { element.css({ transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999, 'visibility': 'visible', - '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)' + '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', + '-ms-transform': 'matrix(1, 0, 0, 1, '+x+', '+y+')' //,margin: '0' don't monkey with the margin, }); } From e4f6a2152001ab6ebf299fc56e064ff15445f436 Mon Sep 17 00:00:00 2001 From: phil Date: Thu, 12 Mar 2015 12:56:21 +1100 Subject: [PATCH 27/73] remove get event prop --- ngDraggable.js | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 8683bbf..c3e9148 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -3,22 +3,13 @@ * https://github.com/fatlinesofcode/ngDraggable */ angular.module("ngDraggable", []) - .service('ngDraggable', ['$window', function($window) { - - var isDef = function(val) { return typeof val !== 'undefined'; }; - - this.getEventProp = function getEventProp(evt, prop, skipOriginal) { - if (isDef(evt.touches) && evt.touches[0]) { - return evt.touches[0][prop]; - } - if (isDef(evt[prop])) { - return evt[prop]; - } - if (evt.originalEvent && !skipOriginal) { - return this.getEventProp(evt.originalEvent, prop, true); - } - }; + .service('ngDraggable', [function() { + + var scope = this; + scope.inputEvent = function(event) { + return angular.isDefined(event.touches) ? event.touches[0] : event; + } }]) .directive('ngDrag', ['$rootScope', '$parse', '$document', '$window', 'ngDraggable', function ($rootScope, $parse, $document, $window, ngDraggable) { @@ -121,11 +112,13 @@ angular.module("ngDraggable", []) } }; + var cancelPress = function() { clearTimeout(_pressTimer); $document.off(_moveEvents, cancelPress); $document.off(_releaseEvents, cancelPress); }; + var onlongpress = function(evt) { if(! _dragEnabled)return; evt.preventDefault(); @@ -137,8 +130,8 @@ angular.module("ngDraggable", []) element.centerX = element[0].offsetWidth / 2; element.centerY = element[0].offsetHeight / 2; - _mx = ngDraggable.getEventProp(evt, 'pageX'); - _my = ngDraggable.getEventProp(evt, 'pageY'); + _mx = ngDraggable.inputEvent(evt).pageX;//ngDraggable.getEventProp(evt, 'pageX'); + _my = ngDraggable.inputEvent(evt).pageY;//ngDraggable.getEventProp(evt, 'pageY'); _mrx = _mx - offset.left; _mry = _my - offset.top; if (_centerAnchor) { @@ -158,8 +151,8 @@ angular.module("ngDraggable", []) if (!_dragEnabled)return; evt.preventDefault(); - _mx = ngDraggable.getEventProp(evt, 'pageX'); - _my = ngDraggable.getEventProp(evt, 'pageY'); + _mx = ngDraggable.inputEvent(evt).pageX;//ngDraggable.getEventProp(evt, 'pageX'); + _my = ngDraggable.inputEvent(evt).pageY;//ngDraggable.getEventProp(evt, 'pageY'); if (_centerAnchor) { _tx = _mx - element.centerX - _dragOffset.left; @@ -400,7 +393,7 @@ angular.module("ngDraggable", []) } var absorbEvent_ = function (event) { - var e = event.originalEvent; + var e = event;//.originalEvent; e.preventDefault && e.preventDefault(); e.stopPropagation && e.stopPropagation(); e.cancelBubble = true; From 2a17a405c9f376d80c5f1beda90ff2713aa48798 Mon Sep 17 00:00:00 2001 From: phil Date: Thu, 12 Mar 2015 12:57:13 +1100 Subject: [PATCH 28/73] bower rename --- bower.json | 4 ++-- ngDraggable.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bower.json b/bower.json index b4fbfc4..681ef8a 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { - "name": "ngDraggable", + "name": "ngdraggable", "main": "ngDraggable.js", - "version": "0.0.4.1", + "version": "0.1.0", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", diff --git a/ngDraggable.js b/ngDraggable.js index c3e9148..8a3d6bf 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -5,7 +5,7 @@ angular.module("ngDraggable", []) .service('ngDraggable', [function() { - + var scope = this; scope.inputEvent = function(event) { return angular.isDefined(event.touches) ? event.touches[0] : event; From 29aab85fa317c4d6f61af154b59c725382738f48 Mon Sep 17 00:00:00 2001 From: phil Date: Thu, 12 Mar 2015 13:04:02 +1100 Subject: [PATCH 29/73] added isTouching scope variable --- README.md | 4 ++-- ngDraggable.js | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c91bf4d..e574d7e 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,10 @@ Draggable usage: ``` Note: ng-center-anchor is optional. If not specified, it defaults to false. -```ng-drag-start``` and ```ng-drag-move``` is also available. +```ng-drag-start``` and ```ng-drag-move``` is also available. Add to the ng-drop element. ``ng-drag-stop`` can be used when you want to react to the user dragging an item and it wasn't dropped into the target container. -```draggable:start```, ```draggable:move``` and ```draggable:end``` events are broadcasted on drag actions. +```draggable:start```, ```draggable:move``` and ```draggable:end``` events are broadcast on drag actions. Drop area usage: diff --git a/ngDraggable.js b/ngDraggable.js index 8a3d6bf..345840a 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -210,6 +210,7 @@ angular.module("ngDraggable", []) restrict: 'A', link: function (scope, element, attrs) { scope.value = attrs.ngDrop; + scope.isTouching = false; var _myid = scope.$id; @@ -285,6 +286,7 @@ angular.module("ngDraggable", []) var isTouching = function(mouseX, mouseY, dragElement) { var touching= hitTest(mouseX, mouseY); + scope.isTouching = touching; updateDragStyles(touching, dragElement); return touching; } From 13ee5b3b33f72aed15a4c7e5c00e178963901e8f Mon Sep 17 00:00:00 2001 From: phil Date: Thu, 12 Mar 2015 13:07:05 +1100 Subject: [PATCH 30/73] fixed bug #83 --- ngDraggable.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 345840a..d4ce949 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -25,7 +25,7 @@ angular.module("ngDraggable", []) var _dragHandle; // to identify the element in order to prevent getting superflous events when a single element has both drag and drop directives on it. - var _myid = scope.$id; + var _myid = angular.isDefined(scope.$id) || 0; var _data = null; var _dragOffset = null; @@ -197,7 +197,6 @@ angular.module("ngDraggable", []) transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)','z-index': 99999, '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', '-ms-transform': 'matrix(1, 0, 0, 1, '+x+', '+y+')' - //,margin: '0' don't monkey with the margin, }); } initialize(); From f0dd7c8ab8bc69208bce795e22f60c4dba02c066 Mon Sep 17 00:00:00 2001 From: phil Date: Thu, 12 Mar 2015 13:40:55 +1100 Subject: [PATCH 31/73] only remove drag-enter from active drop area --- ngDraggable.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index d4ce949..299ab93 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -25,7 +25,7 @@ angular.module("ngDraggable", []) var _dragHandle; // to identify the element in order to prevent getting superflous events when a single element has both drag and drop directives on it. - var _myid = angular.isDefined(scope.$id) || 0; + var _myid = scope.$id; var _data = null; var _dragOffset = null; @@ -174,7 +174,6 @@ angular.module("ngDraggable", []) $rootScope.$broadcast('draggable:end', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data, callback:onDragComplete, uid: _myid}); element.removeClass('dragging'); element.parent().find('.drag-enter').removeClass('drag-enter'); - // element.css("width",""); reset(); $document.off(_moveEvents, onmove); $document.off(_releaseEvents, onrelease); @@ -211,6 +210,8 @@ angular.module("ngDraggable", []) scope.value = attrs.ngDrop; scope.isTouching = false; + var _lastDropTouch=null; + var _myid = scope.$id; var _dropEnabled=false; @@ -263,6 +264,7 @@ angular.module("ngDraggable", []) // don't listen to drop events if this is the element being dragged // only update the styles and return + console.log("266","onDragEnd","onDragEnd", _myid, obj.uid); if (!_dropEnabled || _myid === obj.uid) { updateDragStyles(false, obj.element); return; @@ -286,6 +288,9 @@ angular.module("ngDraggable", []) var isTouching = function(mouseX, mouseY, dragElement) { var touching= hitTest(mouseX, mouseY); scope.isTouching = touching; + if(touching){ + _lastDropTouch = element; + } updateDragStyles(touching, dragElement); return touching; } @@ -294,7 +299,8 @@ angular.module("ngDraggable", []) if(touching){ element.addClass('drag-enter'); dragElement.addClass('drag-over'); - }else{ + }else if(_lastDropTouch == element){ + _lastDropTouch=null; element.removeClass('drag-enter'); dragElement.removeClass('drag-over'); } From 737d965c8f632a3a2705a2363002e1b27794ffe8 Mon Sep 17 00:00:00 2001 From: phil Date: Thu, 12 Mar 2015 13:45:13 +1100 Subject: [PATCH 32/73] updated readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e574d7e..87cc215 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ Drag and drop module for Angular JS with support for touch devices. [`demo`](htt ### Usage: -- Install: `bower install ngDraggable` -- Add `angular` and `ngDraggable` to your code: +- Install: `bower install ngdraggable` +- Add `angular` and `ngdraggable` to your code: ```html From 064858ad18a7202cb528d44744ffd40257b47733 Mon Sep 17 00:00:00 2001 From: phil Date: Thu, 12 Mar 2015 14:05:11 +1100 Subject: [PATCH 33/73] added option to use fixed positoning instead of transform matrix --- bower.json | 2 +- example.html | 2 +- ngDraggable.js | 26 +++++++++++++++++++++----- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/bower.json b/bower.json index 681ef8a..d1dc307 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngdraggable", "main": "ngDraggable.js", - "version": "0.1.0", + "version": "0.1.1", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", diff --git a/example.html b/example.html index 2e229ce..6ea0a01 100755 --- a/example.html +++ b/example.html @@ -83,7 +83,7 @@

ngDraggable Example

  • -
    {{obj.name}}
    +
    {{obj.name}}
diff --git a/ngDraggable.js b/ngDraggable.js index 299ab93..7537bc3 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -35,6 +35,9 @@ angular.module("ngDraggable", []) var _pressTimer = null; var onDragSuccessCallback = $parse(attrs.ngDragSuccess) || null; + var allowTransform = angular.isDefined(attrs.allowTransform) ? scope.$eval(attrs.allowTransform) : true; + + console.log("40","scope","link", angular.isDefined(attrs.allowTransform) , allowTransform); var initialize = function () { element.attr('draggable', 'false'); // prevent native drag @@ -125,7 +128,12 @@ angular.module("ngDraggable", []) element.addClass('dragging'); offset = element[0].getBoundingClientRect(); + if(allowTransform) _dragOffset = offset; + else{ + _dragOffset = {left:document.body.scrollLeft, top:document.body.scrollTop}; + } + element.centerX = element[0].offsetWidth / 2; element.centerY = element[0].offsetHeight / 2; @@ -188,15 +196,23 @@ angular.module("ngDraggable", []) } var reset = function() { + if(allowTransform) element.css({transform:'', 'z-index':'', '-webkit-transform':'', '-ms-transform':''}); + else + element.css({'position':'',top:'',left:''}) } var moveElement = function (x, y) { - element.css({ - transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)','z-index': 99999, - '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', - '-ms-transform': 'matrix(1, 0, 0, 1, '+x+', '+y+')' - }); + if(allowTransform) { + element.css({ + transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + x + ', ' + y + ', 0, 1)', + 'z-index': 99999, + '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + x + ', ' + y + ', 0, 1)', + '-ms-transform': 'matrix(1, 0, 0, 1, ' + x + ', ' + y + ')' + }); + }else{ + element.css({'left':x+'px','top':y+'px', 'position':'fixed'}); + } } initialize(); } From 14750f8ba0cdaecc7ce5ae9a0ca67ceea17bbf5b Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Fri, 13 Mar 2015 00:17:55 +1100 Subject: [PATCH 34/73] renamed package back to ngDraggable lets see how bower copes --- bower.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bower.json b/bower.json index d1dc307..b3c4073 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { - "name": "ngdraggable", + "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.1.1", + "version": "0.1.2", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", From 27ebf4dfcf9b783508b8abb88ee0d89f185f6c69 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Fri, 13 Mar 2015 14:04:10 +1100 Subject: [PATCH 35/73] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 87cc215..e574d7e 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ Drag and drop module for Angular JS with support for touch devices. [`demo`](htt ### Usage: -- Install: `bower install ngdraggable` -- Add `angular` and `ngdraggable` to your code: +- Install: `bower install ngDraggable` +- Add `angular` and `ngDraggable` to your code: ```html From b8b5635ff7d2e222a53f9d06228a4b9e50a07978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bengt-Ove=20Holl=C3=A4nder?= Date: Mon, 16 Mar 2015 10:47:30 +0100 Subject: [PATCH 36/73] Add missing semicolons and remove console.logs --- ngDraggable.js | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 7537bc3..a26a346 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -9,7 +9,7 @@ angular.module("ngDraggable", []) var scope = this; scope.inputEvent = function(event) { return angular.isDefined(event.touches) ? event.touches[0] : event; - } + }; }]) .directive('ngDrag', ['$rootScope', '$parse', '$document', '$window', 'ngDraggable', function ($rootScope, $parse, $document, $window, ngDraggable) { @@ -37,8 +37,6 @@ angular.module("ngDraggable", []) var onDragSuccessCallback = $parse(attrs.ngDragSuccess) || null; var allowTransform = angular.isDefined(attrs.allowTransform) ? scope.$eval(attrs.allowTransform) : true; - console.log("40","scope","link", angular.isDefined(attrs.allowTransform) , allowTransform); - var initialize = function () { element.attr('draggable', 'false'); // prevent native drag // check to see if drag handle(s) was specified @@ -81,7 +79,7 @@ angular.module("ngDraggable", []) var onCenterAnchor = function (newVal, oldVal) { if(angular.isDefined(newVal)) _centerAnchor = (newVal || 'true'); - } + }; var isClickableElement = function (evt) { return ( @@ -89,7 +87,7 @@ angular.module("ngDraggable", []) || angular.isDefined(angular.element(evt.target).attr("ng-dblclick")) || angular.isDefined(angular.element(evt.target).attr("ng-cancel-drag")) ); - } + }; /* * When the element is clicked start the drag behaviour * On touch devices as a small delay so as not to prevent native window scrolling @@ -153,7 +151,7 @@ angular.module("ngDraggable", []) $document.on(_moveEvents, onmove); $document.on(_releaseEvents, onrelease); $rootScope.$broadcast('draggable:start', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data}); - } + }; var onmove = function (evt) { if (!_dragEnabled)return; @@ -173,7 +171,7 @@ angular.module("ngDraggable", []) moveElement(_tx, _ty); $rootScope.$broadcast('draggable:move', { x: _mx, y: _my, tx: _tx, ty: _ty, event: evt, element: element, data: _data, uid: _myid }); - } + }; var onrelease = function(evt) { if (!_dragEnabled) @@ -185,7 +183,7 @@ angular.module("ngDraggable", []) reset(); $document.off(_moveEvents, onmove); $document.off(_releaseEvents, onrelease); - } + }; var onDragComplete = function(evt) { if (!onDragSuccessCallback )return; @@ -193,14 +191,14 @@ angular.module("ngDraggable", []) scope.$apply(function () { onDragSuccessCallback(scope, {$data: _data, $event: evt}); }); - } + }; var reset = function() { if(allowTransform) element.css({transform:'', 'z-index':'', '-webkit-transform':'', '-ms-transform':''}); else - element.css({'position':'',top:'',left:''}) - } + element.css({'position':'',top:'',left:''}); + }; var moveElement = function (x, y) { if(allowTransform) { @@ -213,7 +211,7 @@ angular.module("ngDraggable", []) }else{ element.css({'left':x+'px','top':y+'px', 'position':'fixed'}); } - } + }; initialize(); } }; @@ -274,13 +272,12 @@ angular.module("ngDraggable", []) $timeout(function(){ onDragMoveCallback(scope, {$data: obj.data, $event: obj}); }); - } + }; var onDragEnd = function (evt, obj) { // don't listen to drop events if this is the element being dragged // only update the styles and return - console.log("266","onDragEnd","onDragEnd", _myid, obj.uid); if (!_dropEnabled || _myid === obj.uid) { updateDragStyles(false, obj.element); return; @@ -299,7 +296,7 @@ angular.module("ngDraggable", []) onDragStopCallback(scope, {$data: obj.data, $event: obj}); }); updateDragStyles(false, obj.element); - } + }; var isTouching = function(mouseX, mouseY, dragElement) { var touching= hitTest(mouseX, mouseY); @@ -309,7 +306,7 @@ angular.module("ngDraggable", []) } updateDragStyles(touching, dragElement); return touching; - } + }; var updateDragStyles = function(touching, dragElement) { if(touching){ @@ -320,7 +317,7 @@ angular.module("ngDraggable", []) element.removeClass('drag-enter'); dragElement.removeClass('drag-over'); } - } + }; var hitTest = function(x, y) { var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element); @@ -386,7 +383,7 @@ angular.module("ngDraggable", []) } _dragOffset = element[0].getBoundingClientRect();//ngDraggable.getPrivOffset(element); - } + }; var onDragMove = function(evt, obj) { if(_allowClone) { @@ -413,7 +410,7 @@ angular.module("ngDraggable", []) '-ms-transform': 'matrix(1, 0, 0, 1, '+x+', '+y+')' //,margin: '0' don't monkey with the margin, }); - } + }; var absorbEvent_ = function (event) { var e = event;//.originalEvent; @@ -455,11 +452,11 @@ angular.module("ngDraggable", []) e.cancelBubble = true; e.returnValue = false; return false; - } + }; initialize(); } - } + }; }]) .directive('ngCancelDrag', [function () { return { @@ -467,7 +464,7 @@ angular.module("ngDraggable", []) link: function (scope, element, attrs) { element.find('*').attr('ng-cancel-drag', 'ng-cancel-drag'); } - } + }; }]) .directive('ngDragScroll', ['$window', '$interval', '$timeout', '$document', function($window, $interval, $timeout, $document) { return { @@ -574,5 +571,5 @@ angular.module("ngDraggable", []) lastMouseEvent = obj.event; }); } - } + }; }]); From 9d1da34eae53876e29c9b82286b215cd2821cfc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bengt-Ove=20Holl=C3=A4nder?= Date: Mon, 16 Mar 2015 10:48:29 +0100 Subject: [PATCH 37/73] Remove jQuery dependency in ngDragScroll --- ngDraggable.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index a26a346..e238f9f 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -37,6 +37,9 @@ angular.module("ngDraggable", []) var onDragSuccessCallback = $parse(attrs.ngDragSuccess) || null; var allowTransform = angular.isDefined(attrs.allowTransform) ? scope.$eval(attrs.allowTransform) : true; + // deregistration function for mouse move events in $rootScope triggered by jqLite trigger handler + var _deregisterRootMoveListener = angular.noop; + var initialize = function () { element.attr('draggable', 'false'); // prevent native drag // check to see if drag handle(s) was specified @@ -150,6 +153,13 @@ angular.module("ngDraggable", []) $document.on(_moveEvents, onmove); $document.on(_releaseEvents, onrelease); + // This event is used to receive manually triggered mouse move events + // jqLite unfortunately only supports triggerHandler(...) + // See http://api.jquery.com/triggerHandler/ + // _deregisterRootMoveListener = $rootScope.$on('draggable:_triggerHandlerMove', onmove); + _deregisterRootMoveListener = $rootScope.$on('draggable:_triggerHandlerMove', function(event, origEvent) { + onmove(origEvent); + }); $rootScope.$broadcast('draggable:start', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data}); }; @@ -183,6 +193,7 @@ angular.module("ngDraggable", []) reset(); $document.off(_moveEvents, onmove); $document.off(_releaseEvents, onrelease); + _deregisterRootMoveListener(); }; var onDragComplete = function(evt) { @@ -466,7 +477,7 @@ angular.module("ngDraggable", []) } }; }]) - .directive('ngDragScroll', ['$window', '$interval', '$timeout', '$document', function($window, $interval, $timeout, $document) { + .directive('ngDragScroll', ['$window', '$interval', '$timeout', '$document', '$rootScope', function($window, $interval, $timeout, $document, $rootScope) { return { restrict: 'A', link: function(scope, element, attrs) { @@ -517,8 +528,8 @@ angular.module("ngDraggable", []) if (scrollX !== 0 || scrollY !== 0) { // Record the current scroll position. - var currentScrollLeft = $(document).scrollLeft(); - var currentScrollTop = $(document).scrollTop(); + var currentScrollLeft = $document[0].documentElement.scrollLeft; + var currentScrollTop = $document[0].documentElement.scrollTop; // Remove the transformation from the element, scroll the window by the scroll distance // record how far we scrolled, then reapply the element transformation. @@ -527,8 +538,8 @@ angular.module("ngDraggable", []) $window.scrollBy(scrollX, scrollY); - var horizontalScrollAmount = $(document).scrollLeft() - currentScrollLeft; - var verticalScrollAmount = $(document).scrollTop() - currentScrollTop; + var horizontalScrollAmount = $document[0].documentElement.scrollLeft - currentScrollLeft; + var verticalScrollAmount = $document[0].documentElement.scrollTop - currentScrollTop; element.css('transform', elementTransform); @@ -538,7 +549,7 @@ angular.module("ngDraggable", []) lastMouseEvent.pageX += horizontalScrollAmount; lastMouseEvent.pageY += verticalScrollAmount; - $document.trigger(lastMouseEvent); + $rootScope.$emit('draggable:_triggerHandlerMove', lastMouseEvent); }); } From ccabdaf95951c150ff324e42ba12c64361dddb6a Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Wed, 18 Mar 2015 09:42:01 +1100 Subject: [PATCH 38/73] version bump --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index b3c4073..1d678c0 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.1.2", + "version": "0.1.3", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", From d401b3062e48546f7a9726e9ede235e1f8357695 Mon Sep 17 00:00:00 2001 From: Ryan Baker Date: Fri, 20 Mar 2015 10:49:02 -0700 Subject: [PATCH 39/73] fixes fatlinesofcode/ngDraggable#108 --- ngDraggable.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index e238f9f..d8b00a6 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -98,11 +98,6 @@ angular.module("ngDraggable", []) var onpress = function(evt) { if(! _dragEnabled)return; - // disable drag on clickable element - if (isClickableElement(evt)) { - return; - } - if(_hasTouch){ cancelPress(); _pressTimer = setTimeout(function(){ @@ -126,7 +121,6 @@ angular.module("ngDraggable", []) var onlongpress = function(evt) { if(! _dragEnabled)return; evt.preventDefault(); - element.addClass('dragging'); offset = element[0].getBoundingClientRect(); if(allowTransform) @@ -160,13 +154,17 @@ angular.module("ngDraggable", []) _deregisterRootMoveListener = $rootScope.$on('draggable:_triggerHandlerMove', function(event, origEvent) { onmove(origEvent); }); - $rootScope.$broadcast('draggable:start', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data}); }; var onmove = function (evt) { if (!_dragEnabled)return; evt.preventDefault(); + if (!element.hasClass('dragging')) { + element.addClass('dragging'); + $rootScope.$broadcast('draggable:start', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data}); + } + _mx = ngDraggable.inputEvent(evt).pageX;//ngDraggable.getEventProp(evt, 'pageX'); _my = ngDraggable.inputEvent(evt).pageY;//ngDraggable.getEventProp(evt, 'pageY'); From 0979448a880b0ef84dac9348ef7cc8c33f4f1256 Mon Sep 17 00:00:00 2001 From: Sebastian Hofmann Date: Mon, 23 Mar 2015 16:10:05 +0100 Subject: [PATCH 40/73] added some documentation --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e574d7e..ec60d32 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,10 @@ Draggable usage: Draggable div ``` -Note: ng-center-anchor is optional. If not specified, it defaults to false. + +* `ng-center-anchor` is optional. If not specified, it defaults to false. +* If the draggable is also clickable (ng-click, ng-dblclick) the script wont react. +* You can define a drag-button as child with the attribute `ng-drag-handle`. ```ng-drag-start``` and ```ng-drag-move``` is also available. Add to the ng-drop element. ``ng-drag-stop`` can be used when you want to react to the user dragging an item and it wasn't dropped into the target container. From 87c2414795537a8de126b07e372aaba1ec31a21b Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Sun, 29 Mar 2015 14:58:58 +0200 Subject: [PATCH 41/73] Avoiding digest cycles for undefined callbacks --- ngDraggable.js | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index e238f9f..0407fe7 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -272,17 +272,22 @@ angular.module("ngDraggable", []) var onDragStart = function(evt, obj) { if(! _dropEnabled)return; isTouching(obj.x,obj.y,obj.element); - - $timeout(function(){ - onDragStartCallback(scope, {$data: obj.data, $event: obj}); - }); + + if (attrs.ngDragStart) { + $timeout(function(){ + onDragStartCallback(scope, {$data: obj.data, $event: obj}); + }); + } }; var onDragMove = function(evt, obj) { if(! _dropEnabled)return; isTouching(obj.x,obj.y,obj.element); - $timeout(function(){ - onDragMoveCallback(scope, {$data: obj.data, $event: obj}); - }); + + if (attrs.ngDragMove) { + $timeout(function(){ + onDragMoveCallback(scope, {$data: obj.data, $event: obj}); + }); + } }; var onDragEnd = function (evt, obj) { @@ -299,13 +304,19 @@ angular.module("ngDraggable", []) obj.callback(obj); } + if (attrs.ngDropSuccess) { + $timeout(function(){ + onDropCallback(scope, {$data: obj.data, $event: obj, $target: scope.$eval(scope.value)}); + }); + } + } + + if (attrs.ngDragStop) { $timeout(function(){ - onDropCallback(scope, {$data: obj.data, $event: obj, $target: scope.$eval(scope.value)}); + onDragStopCallback(scope, {$data: obj.data, $event: obj}); }); } - $timeout(function(){ - onDragStopCallback(scope, {$data: obj.data, $event: obj}); - }); + updateDragStyles(false, obj.element); }; From d44c8d6587c4e8a74d800b9e064f8738c29a9663 Mon Sep 17 00:00:00 2001 From: Cinetik Date: Mon, 30 Mar 2015 09:08:09 +0200 Subject: [PATCH 42/73] Update ngDraggable.js fixed drop hittest issue when page scrolled --- ngDraggable.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index e238f9f..052ef54 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -332,8 +332,10 @@ angular.module("ngDraggable", []) var hitTest = function(x, y) { var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element); - bounds.right = bounds.left + element[0].offsetWidth; - bounds.bottom = bounds.top + element[0].offsetHeight; + bounds.right = bounds.left + element[0].offsetWidth - $window.pageXOffset; + bounds.bottom = bounds.top + element[0].offsetHeight - $window.pageYOffset; + x -= $window.pageXOffset; + y -= $window.pageYOffset; return x >= bounds.left && x <= bounds.right && y <= bounds.bottom From f97d9fe8cc125e2c2af6e7ffdbf433922cf64625 Mon Sep 17 00:00:00 2001 From: Cinetik Date: Mon, 30 Mar 2015 09:10:18 +0200 Subject: [PATCH 43/73] Update ngDraggable.js --- ngDraggable.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 052ef54..ac8b45d 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -332,10 +332,10 @@ angular.module("ngDraggable", []) var hitTest = function(x, y) { var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element); - bounds.right = bounds.left + element[0].offsetWidth - $window.pageXOffset; - bounds.bottom = bounds.top + element[0].offsetHeight - $window.pageYOffset; - x -= $window.pageXOffset; - y -= $window.pageYOffset; + bounds.right = bounds.left + element[0].offsetWidth - window.pageXOffset; + bounds.bottom = bounds.top + element[0].offsetHeight - window.pageYOffset; + x -= window.pageXOffset; + y -= window.pageYOffset; return x >= bounds.left && x <= bounds.right && y <= bounds.bottom From cd7bce1a080255586fc374ad924715422b5e3809 Mon Sep 17 00:00:00 2001 From: Florian Meskens Date: Mon, 30 Mar 2015 09:29:29 +0200 Subject: [PATCH 44/73] Used $window angular warper instead --- ngDraggable.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index ac8b45d..052ef54 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -332,10 +332,10 @@ angular.module("ngDraggable", []) var hitTest = function(x, y) { var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element); - bounds.right = bounds.left + element[0].offsetWidth - window.pageXOffset; - bounds.bottom = bounds.top + element[0].offsetHeight - window.pageYOffset; - x -= window.pageXOffset; - y -= window.pageYOffset; + bounds.right = bounds.left + element[0].offsetWidth - $window.pageXOffset; + bounds.bottom = bounds.top + element[0].offsetHeight - $window.pageYOffset; + x -= $window.pageXOffset; + y -= $window.pageYOffset; return x >= bounds.left && x <= bounds.right && y <= bounds.bottom From b444c773fc026e9c15d7c0d6998bca3b26f751e1 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Tue, 31 Mar 2015 16:12:14 +1100 Subject: [PATCH 45/73] version bump --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 1d678c0..b200f67 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.1.3", + "version": "0.1.4", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", From 7169078835a62a9c7f6385dd002bdb1170a4f1fb Mon Sep 17 00:00:00 2001 From: Remigius Stalder Date: Wed, 1 Apr 2015 14:40:23 +0200 Subject: [PATCH 46/73] fix scrolled drop target problem --- ngDraggable.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 6b6da04..f7deb6f 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -341,10 +341,10 @@ angular.module("ngDraggable", []) var hitTest = function(x, y) { var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element); - bounds.right = bounds.left + element[0].offsetWidth - $window.pageXOffset; - bounds.bottom = bounds.top + element[0].offsetHeight - $window.pageYOffset; - x -= $window.pageXOffset; - y -= $window.pageYOffset; + x -= document.body.scrollLeft + document.documentElement.scrollLeft; + y -= document.body.scrollTop + document.documentElement.scrollTop; + bounds.right = bounds.left + element[0].offsetWidth; + bounds.bottom = bounds.top + element[0].offsetHeight; return x >= bounds.left && x <= bounds.right && y <= bounds.bottom From 3963afb87c4a154ac3c992f70d8301ceb520e1af Mon Sep 17 00:00:00 2001 From: Remigius Stalder Date: Wed, 1 Apr 2015 14:44:54 +0200 Subject: [PATCH 47/73] add $ for angular document placeholder --- ngDraggable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index f7deb6f..862cbc1 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -341,8 +341,8 @@ angular.module("ngDraggable", []) var hitTest = function(x, y) { var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element); - x -= document.body.scrollLeft + document.documentElement.scrollLeft; - y -= document.body.scrollTop + document.documentElement.scrollTop; + x -= $document.body.scrollLeft + $document.documentElement.scrollLeft; + y -= $document.body.scrollTop + $document.documentElement.scrollTop; bounds.right = bounds.left + element[0].offsetWidth; bounds.bottom = bounds.top + element[0].offsetHeight; return x >= bounds.left From d25ff173e8eb175963fc80044d26b70c7f767e7f Mon Sep 17 00:00:00 2001 From: Remigius Stalder Date: Wed, 1 Apr 2015 15:02:01 +0200 Subject: [PATCH 48/73] bounds is read-only, so modifying it does not make sense --- ngDraggable.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 862cbc1..1f6b700 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -343,8 +343,6 @@ angular.module("ngDraggable", []) var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element); x -= $document.body.scrollLeft + $document.documentElement.scrollLeft; y -= $document.body.scrollTop + $document.documentElement.scrollTop; - bounds.right = bounds.left + element[0].offsetWidth; - bounds.bottom = bounds.top + element[0].offsetHeight; return x >= bounds.left && x <= bounds.right && y <= bounds.bottom From 859851a8a065d324abaa1974064bec7fded6e852 Mon Sep 17 00:00:00 2001 From: marius Date: Thu, 16 Apr 2015 10:22:40 +0100 Subject: [PATCH 49/73] brought back the 'isClickableElement' check on drag to make ng-cancel-drag work --- ngDraggable.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ngDraggable.js b/ngDraggable.js index 6b6da04..63ece12 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -64,7 +64,7 @@ angular.module("ngDraggable", []) _dragHandle.on(_pressEvents, onpress); } else { // no handle(s) specified, use the element as the handle - element.on(_pressEvents, onpress); + element.on(_pressEvents, onpress); } if(! _hasTouch && element[0].nodeName.toLowerCase() == "img"){ element.on('mousedown', function(){ return false;}); // prevent native drag for images @@ -98,6 +98,10 @@ angular.module("ngDraggable", []) var onpress = function(evt) { if(! _dragEnabled)return; + if (isClickableElement(evt)) { + return; + } + if(_hasTouch){ cancelPress(); _pressTimer = setTimeout(function(){ From 29f494cc3cfe98264f9af22fa9e1e4b393c64978 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Fri, 17 Apr 2015 13:28:56 +1000 Subject: [PATCH 50/73] Update ngDraggable.js removed check for ng-click in clickableElement function. Only ng-cancel-drag will prevent the start of drag. --- ngDraggable.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 63ece12..28dae42 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -86,9 +86,7 @@ angular.module("ngDraggable", []) var isClickableElement = function (evt) { return ( - angular.isDefined(angular.element(evt.target).attr("ng-click")) - || angular.isDefined(angular.element(evt.target).attr("ng-dblclick")) - || angular.isDefined(angular.element(evt.target).attr("ng-cancel-drag")) + angular.isDefined(angular.element(evt.target).attr("ng-cancel-drag")) ); }; /* From 8634fefa9b559befa75a1c525c7f486eec50e924 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Fri, 17 Apr 2015 13:29:21 +1000 Subject: [PATCH 51/73] Update bower.json --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index b200f67..d05e5d1 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.1.4", + "version": "0.1.5", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", From 446535da3c93acf20fcc629e184dac1d6aa2b88c Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Fri, 17 Apr 2015 13:41:40 +1000 Subject: [PATCH 52/73] Update bower.json --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index d05e5d1..ac9bd6b 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.1.5", + "version": "0.1.6", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", From cee91d9458781408831bb4e04d5f7b8d02c1cd5f Mon Sep 17 00:00:00 2001 From: Stefan Hans Schonert Date: Sat, 18 Apr 2015 18:58:22 +0200 Subject: [PATCH 53/73] invalid $document reference and ussage --- ngDraggable.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index f278de0..68aa8d8 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -228,7 +228,7 @@ angular.module("ngDraggable", []) }; }]) - .directive('ngDrop', ['$parse', '$timeout', '$window', 'ngDraggable', function ($parse, $timeout, $window, ngDraggable) { + .directive('ngDrop', ['$parse', '$timeout', '$window', '$document', 'ngDraggable', function ($parse, $timeout, $window, $document, ngDraggable) { return { restrict: 'A', link: function (scope, element, attrs) { @@ -343,8 +343,8 @@ angular.module("ngDraggable", []) var hitTest = function(x, y) { var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element); - x -= $document.body.scrollLeft + $document.documentElement.scrollLeft; - y -= $document.body.scrollTop + $document.documentElement.scrollTop; + x -= $document[0].body.scrollLeft + $document[0].documentElement.scrollLeft; + y -= $document[0].body.scrollTop + $document[0].documentElement.scrollTop; return x >= bounds.left && x <= bounds.right && y <= bounds.bottom From eefd5ce7289c1f6fdc75f8bf6172d2be254dd203 Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Sun, 19 Apr 2015 23:56:49 +0200 Subject: [PATCH 54/73] Avoid digest cycles by not watching ng-drag-data --- ngDraggable.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index f278de0..2ff6492 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -37,6 +37,8 @@ angular.module("ngDraggable", []) var onDragSuccessCallback = $parse(attrs.ngDragSuccess) || null; var allowTransform = angular.isDefined(attrs.allowTransform) ? scope.$eval(attrs.allowTransform) : true; + var getDragData = $parse(attrs.ngDragData); + // deregistration function for mouse move events in $rootScope triggered by jqLite trigger handler var _deregisterRootMoveListener = angular.noop; @@ -57,7 +59,6 @@ angular.module("ngDraggable", []) scope.$on('$destroy', onDestroy); scope.$watch(attrs.ngDrag, onEnableChange); scope.$watch(attrs.ngCenterAnchor, onCenterAnchor); - scope.$watch(attrs.ngDragData, onDragDataChange); // wire up touch events if (_dragHandle) { // handle(s) specified, use those to initiate drag @@ -73,9 +74,6 @@ angular.module("ngDraggable", []) var onDestroy = function (enable) { toggleListeners(false); }; - var onDragDataChange = function (newVal, oldVal) { - _data = newVal; - }; var onEnableChange = function (newVal, oldVal) { _dragEnabled = (newVal); }; @@ -163,6 +161,7 @@ angular.module("ngDraggable", []) evt.preventDefault(); if (!element.hasClass('dragging')) { + _data = getDragData(scope); element.addClass('dragging'); $rootScope.$broadcast('draggable:start', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data}); } From 76c217312d71a894b9e9221695c559daa58bda9a Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Mon, 20 Apr 2015 00:01:44 +0200 Subject: [PATCH 55/73] Do not start dragging on right click --- ngDraggable.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ngDraggable.js b/ngDraggable.js index f278de0..f90ecfd 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -100,6 +100,11 @@ angular.module("ngDraggable", []) return; } + if (evt.type == "mousedown" && evt.button != 0) { + // Do not start dragging on right-click + return; + } + if(_hasTouch){ cancelPress(); _pressTimer = setTimeout(function(){ From 0feb8d410d30de6cf9cb8febffa7ff0fc8dc727e Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Mon, 20 Apr 2015 00:10:07 +0200 Subject: [PATCH 56/73] Use $watch instead of $observe for ng-drop --- ngDraggable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index f278de0..8d9a758 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -256,7 +256,7 @@ angular.module("ngDraggable", []) if (!enable)return; // add listeners. - attrs.$observe("ngDrop", onEnableChange); + scope.$watch(attrs.ngDrop, onEnableChange); scope.$on('$destroy', onDestroy); scope.$on('draggable:start', onDragStart); scope.$on('draggable:move', onDragMove); @@ -267,7 +267,7 @@ angular.module("ngDraggable", []) toggleListeners(false); }; var onEnableChange = function (newVal, oldVal) { - _dropEnabled=scope.$eval(newVal); + _dropEnabled=newVal; }; var onDragStart = function(evt, obj) { if(! _dropEnabled)return; From e22002f5cd99977cf72542773daa9d234a9e4f78 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Mon, 20 Apr 2015 08:36:16 +1000 Subject: [PATCH 57/73] version bump --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index ac9bd6b..bf11066 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.1.6", + "version": "0.1.7", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", From 66982f4ace681df17733d28ba8d07bdb7cf27d35 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Mon, 20 Apr 2015 08:39:13 +1000 Subject: [PATCH 58/73] Note a about PRs --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ec60d32..02b4657 100644 --- a/README.md +++ b/README.md @@ -67,3 +67,6 @@ app.controller('MainCtrl', function ($scope) { [`Cloning`](http://htmlpreview.github.io/?https://github.com/fatlinesofcode/ngDraggable/blob/master/example-clone.html). [`Canceling`](http://htmlpreview.github.io/?https://github.com/fatlinesofcode/ngDraggable/blob/master/example-cancel.html). + +## Pull requests +We welcome pull requests but please check that all the demos still work if you modified the source base. There have been serveral PRs recently that broke core functionality. If you are feeling really keen you could include some protractor test cases in your PR. From 66a223c9975a3aedc17011a48a52615d9eac3594 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Mon, 20 Apr 2015 08:39:47 +1000 Subject: [PATCH 59/73] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 02b4657..8f72f5b 100644 --- a/README.md +++ b/README.md @@ -69,4 +69,4 @@ app.controller('MainCtrl', function ($scope) { [`Canceling`](http://htmlpreview.github.io/?https://github.com/fatlinesofcode/ngDraggable/blob/master/example-cancel.html). ## Pull requests -We welcome pull requests but please check that all the demos still work if you modified the source base. There have been serveral PRs recently that broke core functionality. If you are feeling really keen you could include some protractor test cases in your PR. +We welcome pull requests but please check that all the examples still work if you modified the source base. There have been serveral PRs recently that broke core functionality. If you are feeling really keen you could include some protractor test cases in your PR. From d1ef32baf9a0fe5207b7da13260c94b3fc2cca13 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Tue, 21 Apr 2015 09:34:26 +1000 Subject: [PATCH 60/73] version bump --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index bf11066..18ef273 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.1.7", + "version": "0.1.8", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", From d38ee545290dda78c60e672c418d3f4c0bf4c214 Mon Sep 17 00:00:00 2001 From: benib Date: Tue, 28 Apr 2015 22:44:47 +0200 Subject: [PATCH 61/73] makes ng-drag-handle work without jQuery --- ngDraggable.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ngDraggable.js b/ngDraggable.js index 40890be..a7ed5b2 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -45,7 +45,13 @@ angular.module("ngDraggable", []) var initialize = function () { element.attr('draggable', 'false'); // prevent native drag // check to see if drag handle(s) was specified - var dragHandles = element.find('[ng-drag-handle]'); + // if querySelectorAll is available, we use this instead of find + // as JQLite find is limited to tagnames + if (element[0].querySelectorAll) { + var dragHandles = angular.element(element[0].querySelectorAll('[ng-drag-handle]')); + } else { + var dragHandles = element.find('[ng-drag-handle]'); + } if (dragHandles.length) { _dragHandle = dragHandles; } From f4c93c21579662d6e0aa0ef0499194f671ad0305 Mon Sep 17 00:00:00 2001 From: Justin Morant Date: Tue, 19 May 2015 20:06:30 -0600 Subject: [PATCH 62/73] Added a check for event.originalEvent.touches in scope.inputEvent to fix event.x undefined. --- ngDraggable.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ngDraggable.js b/ngDraggable.js index 40890be..cafec98 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -8,7 +8,13 @@ angular.module("ngDraggable", []) var scope = this; scope.inputEvent = function(event) { - return angular.isDefined(event.touches) ? event.touches[0] : event; + if (angular.isDefined(event.touches)) { + return event.touches[0]; + } + else if (angular.isDefined(event.originalEvent.touches)) { + return event.originalEvent.touches[0]; + } + return event; }; }]) From a33746067a844a6a2c281e4ed49ac3b9175c24ca Mon Sep 17 00:00:00 2001 From: Jaison Erick Date: Fri, 22 May 2015 10:36:32 -0300 Subject: [PATCH 63/73] Fix a Bug on Chrome where when you scroll the dragging element scrolls down --- ngDraggable.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 40890be..9c2155e 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -543,8 +543,8 @@ angular.module("ngDraggable", []) if (scrollX !== 0 || scrollY !== 0) { // Record the current scroll position. - var currentScrollLeft = $document[0].documentElement.scrollLeft; - var currentScrollTop = $document[0].documentElement.scrollTop; + var currentScrollLeft = ($window.pageXOffset || $document[0].documentElement.scrollLeft); + var currentScrollTop = ($window.pageYOffset || $document[0].documentElement.scrollTop); // Remove the transformation from the element, scroll the window by the scroll distance // record how far we scrolled, then reapply the element transformation. @@ -553,8 +553,8 @@ angular.module("ngDraggable", []) $window.scrollBy(scrollX, scrollY); - var horizontalScrollAmount = $document[0].documentElement.scrollLeft - currentScrollLeft; - var verticalScrollAmount = $document[0].documentElement.scrollTop - currentScrollTop; + var horizontalScrollAmount = ($window.pageXOffset || $document[0].documentElement.scrollLeft) - currentScrollLeft; + var verticalScrollAmount = ($window.pageYOffset || $document[0].documentElement.scrollTop) - currentScrollTop; element.css('transform', elementTransform); From 5eb69ad7e0103743ec28dba91cb69af5a56b8662 Mon Sep 17 00:00:00 2001 From: Jaison Erick Date: Fri, 22 May 2015 10:39:58 -0300 Subject: [PATCH 64/73] Replace setInterval by requestAnimationFrame, stopping the flickering while scroll --- ngDraggable.js | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 9c2155e..b7d2a6e 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -507,8 +507,35 @@ angular.module("ngDraggable", []) scrollInterval: attrs.scrollInterval || 250 }; + + var reqAnimFrame = (function() { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) { + window.setTimeout(callback, 1000 / 60); + }; + })(); + + var animationIsOn = false; var createInterval = function() { - intervalPromise = $interval(function() { + animationIsOn = true; + + function nextFrame(callback) { + var args = Array.prototype.slice.call(arguments); + if(animationIsOn) { + reqAnimFrame(function () { + $timeout(function () { + callback.apply(null, args); + nextFrame(callback); + }, config.scrollInterval); + }) + } + } + + nextFrame(function() { if (!lastMouseEvent) return; var viewportWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); @@ -541,6 +568,8 @@ angular.module("ngDraggable", []) } } + + if (scrollX !== 0 || scrollY !== 0) { // Record the current scroll position. var currentScrollLeft = ($window.pageXOffset || $document[0].documentElement.scrollLeft); @@ -558,36 +587,31 @@ angular.module("ngDraggable", []) element.css('transform', elementTransform); - // On the next digest cycle, trigger a mousemove event equal to the amount we scrolled so - // the element moves correctly. - $timeout(function() { - lastMouseEvent.pageX += horizontalScrollAmount; - lastMouseEvent.pageY += verticalScrollAmount; + lastMouseEvent.pageX += horizontalScrollAmount; + lastMouseEvent.pageY += verticalScrollAmount; - $rootScope.$emit('draggable:_triggerHandlerMove', lastMouseEvent); - }); + $rootScope.$emit('draggable:_triggerHandlerMove', lastMouseEvent); } - }, config.scrollInterval); + }); }; var clearInterval = function() { - $interval.cancel(intervalPromise); - intervalPromise = null; + animationIsOn = false; }; scope.$on('draggable:start', function(event, obj) { // Ignore this event if it's not for this element. if (obj.element[0] !== element[0]) return; - if (!intervalPromise) createInterval(); + if (!animationIsOn) createInterval(); }); scope.$on('draggable:end', function(event, obj) { // Ignore this event if it's not for this element. if (obj.element[0] !== element[0]) return; - if (intervalPromise) clearInterval(); + if (animationIsOn) clearInterval(); }); scope.$on('draggable:move', function(event, obj) { From 57dec58e4b4d4d4aee892ecfa854c831f2502133 Mon Sep 17 00:00:00 2001 From: Jaison Erick Date: Fri, 22 May 2015 10:56:02 -0300 Subject: [PATCH 65/73] Improved performance, using the requestAnimationFrame default framerate Breaking Change: Removed the scrollInterval attribute --- ngDraggable.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index b7d2a6e..a6e0211 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -503,8 +503,7 @@ angular.module("ngDraggable", []) verticalScroll: attrs.verticalScroll || true, horizontalScroll: attrs.horizontalScroll || true, activationDistance: attrs.activationDistance || 75, - scrollDistance: attrs.scrollDistance || 50, - scrollInterval: attrs.scrollInterval || 250 + scrollDistance: attrs.scrollDistance || 15 }; @@ -527,10 +526,10 @@ angular.module("ngDraggable", []) var args = Array.prototype.slice.call(arguments); if(animationIsOn) { reqAnimFrame(function () { - $timeout(function () { - callback.apply(null, args); - nextFrame(callback); - }, config.scrollInterval); + $rootScope.$apply(function () { + callback.apply(null, args); + nextFrame(callback); + }); }) } } From fa00c77e25e90ec8672583a2023f682345193c95 Mon Sep 17 00:00:00 2001 From: Sunny Chan Date: Fri, 19 Jun 2015 17:38:27 +0800 Subject: [PATCH 66/73] Making 3 examples work again. The cancel function is still not working? --- example-cancel.html | 6 +++--- example-clone.html | 4 ++-- example-reorder.html | 6 +++--- example.html | 6 +++--- ngDraggable.js | 3 ++- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/example-cancel.html b/example-cancel.html index c6ce1ad..6fc8bec 100755 --- a/example-cancel.html +++ b/example-cancel.html @@ -2,7 +2,7 @@ ngDraggable - + + + + +
+ +
+

ngDraggable Example

+
+ +
    +
  • +
    TEST
    +
  • +
+ +
+
+ Drop area #1 + +
+ {{obj.name}} +
+ +
+ +
+ Drop area #2 + +
+ {{obj.name}} +
+ +
+ +
+ + +
+
footer
+ + + + + + \ No newline at end of file diff --git a/ngDraggable.js b/ngDraggable.js index dcaaac1..3f4a2ee 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -3,466 +3,483 @@ * https://github.com/fatlinesofcode/ngDraggable */ angular.module("ngDraggable", []) - .service('ngDraggable', [function() { - - - var scope = this; - scope.inputEvent = function(event) { - if (angular.isDefined(event.touches)) { - return event.touches[0]; - } - //Checking both is not redundent. If only check if touches isDefined, angularjs isDefnied will return error and stop the remaining scripty if event.originalEvent is not defined. - else if (angular.isDefined(event.originalEvent) && angular.isDefined(event.originalEvent.touches)) { - return event.originalEvent.touches[0]; - } - return event; - }; - - }]) - .directive('ngDrag', ['$rootScope', '$parse', '$document', '$window', 'ngDraggable', function ($rootScope, $parse, $document, $window, ngDraggable) { - return { - restrict: 'A', - link: function (scope, element, attrs) { - scope.value = attrs.ngDrag; - var offset,_centerAnchor=false,_mx,_my,_tx,_ty,_mrx,_mry; - var _hasTouch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch; - var _pressEvents = 'touchstart mousedown'; - var _moveEvents = 'touchmove mousemove'; - var _releaseEvents = 'touchend mouseup'; - var _dragHandle; - - // to identify the element in order to prevent getting superflous events when a single element has both drag and drop directives on it. - var _myid = scope.$id; - var _data = null; - - var _dragOffset = null; - - var _dragEnabled = false; - - var _pressTimer = null; - - var onDragSuccessCallback = $parse(attrs.ngDragSuccess) || null; - var allowTransform = angular.isDefined(attrs.allowTransform) ? scope.$eval(attrs.allowTransform) : true; - - var getDragData = $parse(attrs.ngDragData); - - // deregistration function for mouse move events in $rootScope triggered by jqLite trigger handler - var _deregisterRootMoveListener = angular.noop; - - var initialize = function () { - element.attr('draggable', 'false'); // prevent native drag - // check to see if drag handle(s) was specified - // if querySelectorAll is available, we use this instead of find - // as JQLite find is limited to tagnames - if (element[0].querySelectorAll) { - var dragHandles = angular.element(element[0].querySelectorAll('[ng-drag-handle]')); - } else { - var dragHandles = element.find('[ng-drag-handle]'); - } - if (dragHandles.length) { - _dragHandle = dragHandles; - } - toggleListeners(true); - }; - - var toggleListeners = function (enable) { - if (!enable)return; - // add listeners. - - scope.$on('$destroy', onDestroy); - scope.$watch(attrs.ngDrag, onEnableChange); - scope.$watch(attrs.ngCenterAnchor, onCenterAnchor); - // wire up touch events - if (_dragHandle) { - // handle(s) specified, use those to initiate drag - _dragHandle.on(_pressEvents, onpress); - } else { - // no handle(s) specified, use the element as the handle - element.on(_pressEvents, onpress); - } - if(! _hasTouch && element[0].nodeName.toLowerCase() == "img"){ - element.on('mousedown', function(){ return false;}); // prevent native drag for images - } - }; - var onDestroy = function (enable) { - toggleListeners(false); - }; - var onEnableChange = function (newVal, oldVal) { - _dragEnabled = (newVal); - }; - var onCenterAnchor = function (newVal, oldVal) { - if(angular.isDefined(newVal)) + .service('ngDraggable', [function() { + + + var scope = this; + scope.inputEvent = function(event) { + if (angular.isDefined(event.touches)) { + return event.touches[0]; + } + //Checking both is not redundent. If only check if touches isDefined, angularjs isDefnied will return error and stop the remaining scripty if event.originalEvent is not defined. + else if (angular.isDefined(event.originalEvent) && angular.isDefined(event.originalEvent.touches)) { + return event.originalEvent.touches[0]; + } + return event; + }; + + }]) + .directive('ngDrag', ['$rootScope', '$parse', '$document', '$window', 'ngDraggable', function ($rootScope, $parse, $document, $window, ngDraggable) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + scope.value = attrs.ngDrag; + var offset,_centerAnchor=false,_mx,_my,_tx,_ty,_mrx,_mry; + var _hasTouch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch; + var _pressEvents = 'touchstart mousedown'; + var _moveEvents = 'touchmove mousemove'; + var _releaseEvents = 'touchend mouseup'; + var _dragHandle; + + // to identify the element in order to prevent getting superflous events when a single element has both drag and drop directives on it. + var _myid = scope.$id; + var _data = null; + + var _dragOffset = null; + + var _dragEnabled = false; + + var _pressTimer = null; + + var onDragStartCallback = $parse(attrs.ngDragStart) || null; + var onDragStopCallback = $parse(attrs.ngDragStop) || null; + var onDragSuccessCallback = $parse(attrs.ngDragSuccess) || null; + var allowTransform = angular.isDefined(attrs.allowTransform) ? scope.$eval(attrs.allowTransform) : true; + + var getDragData = $parse(attrs.ngDragData); + + // deregistration function for mouse move events in $rootScope triggered by jqLite trigger handler + var _deregisterRootMoveListener = angular.noop; + + var initialize = function () { + element.attr('draggable', 'false'); // prevent native drag + // check to see if drag handle(s) was specified + // if querySelectorAll is available, we use this instead of find + // as JQLite find is limited to tagnames + if (element[0].querySelectorAll) { + var dragHandles = angular.element(element[0].querySelectorAll('[ng-drag-handle]')); + } else { + var dragHandles = element.find('[ng-drag-handle]'); + } + if (dragHandles.length) { + _dragHandle = dragHandles; + } + toggleListeners(true); + }; + + var toggleListeners = function (enable) { + if (!enable)return; + // add listeners. + + scope.$on('$destroy', onDestroy); + scope.$watch(attrs.ngDrag, onEnableChange); + scope.$watch(attrs.ngCenterAnchor, onCenterAnchor); + // wire up touch events + if (_dragHandle) { + // handle(s) specified, use those to initiate drag + _dragHandle.on(_pressEvents, onpress); + } else { + // no handle(s) specified, use the element as the handle + element.on(_pressEvents, onpress); + } + if(! _hasTouch && element[0].nodeName.toLowerCase() == "img"){ + element.on('mousedown', function(){ return false;}); // prevent native drag for images + } + }; + var onDestroy = function (enable) { + toggleListeners(false); + }; + var onEnableChange = function (newVal, oldVal) { + _dragEnabled = (newVal); + }; + var onCenterAnchor = function (newVal, oldVal) { + if(angular.isDefined(newVal)) _centerAnchor = (newVal || 'true'); - }; - - var isClickableElement = function (evt) { - return ( - angular.isDefined(angular.element(evt.target).attr("ng-cancel-drag")) - ); - }; - /* - * When the element is clicked start the drag behaviour - * On touch devices as a small delay so as not to prevent native window scrolling - */ - var onpress = function(evt) { - if(! _dragEnabled)return; - - if (isClickableElement(evt)) { - return; - } + }; - if (evt.type == "mousedown" && evt.button != 0) { - // Do not start dragging on right-click - return; - } + var isClickableElement = function (evt) { + return ( + angular.isDefined(angular.element(evt.target).attr("ng-cancel-drag")) + ); + }; + /* + * When the element is clicked start the drag behaviour + * On touch devices as a small delay so as not to prevent native window scrolling + */ + var onpress = function(evt) { + if(! _dragEnabled)return; + + if (isClickableElement(evt)) { + return; + } + + if (evt.type == "mousedown" && evt.button != 0) { + // Do not start dragging on right-click + return; + } - if(_hasTouch){ + if(_hasTouch){ + cancelPress(); + _pressTimer = setTimeout(function(){ cancelPress(); - _pressTimer = setTimeout(function(){ - cancelPress(); - onlongpress(evt); - },100); - $document.on(_moveEvents, cancelPress); - $document.on(_releaseEvents, cancelPress); - }else{ onlongpress(evt); - } + },100); + $document.on(_moveEvents, cancelPress); + $document.on(_releaseEvents, cancelPress); + }else{ + onlongpress(evt); + } - }; + }; - var cancelPress = function() { - clearTimeout(_pressTimer); - $document.off(_moveEvents, cancelPress); - $document.off(_releaseEvents, cancelPress); - }; + var cancelPress = function() { + clearTimeout(_pressTimer); + $document.off(_moveEvents, cancelPress); + $document.off(_releaseEvents, cancelPress); + }; - var onlongpress = function(evt) { - if(! _dragEnabled)return; - evt.preventDefault(); + var onlongpress = function(evt) { + if(! _dragEnabled)return; + evt.preventDefault(); - offset = element[0].getBoundingClientRect(); - if(allowTransform) + offset = element[0].getBoundingClientRect(); + if(allowTransform) _dragOffset = offset; - else{ - _dragOffset = {left:document.body.scrollLeft, top:document.body.scrollTop}; - } - + else{ + _dragOffset = {left:document.body.scrollLeft, top:document.body.scrollTop}; + } - element.centerX = element[0].offsetWidth / 2; - element.centerY = element[0].offsetHeight / 2; - _mx = ngDraggable.inputEvent(evt).pageX;//ngDraggable.getEventProp(evt, 'pageX'); - _my = ngDraggable.inputEvent(evt).pageY;//ngDraggable.getEventProp(evt, 'pageY'); - _mrx = _mx - offset.left; - _mry = _my - offset.top; - if (_centerAnchor) { - _tx = _mx - element.centerX - $window.pageXOffset; - _ty = _my - element.centerY - $window.pageYOffset; - } else { - _tx = _mx - _mrx - $window.pageXOffset; - _ty = _my - _mry - $window.pageYOffset; - } + element.centerX = element[0].offsetWidth / 2; + element.centerY = element[0].offsetHeight / 2; - $document.on(_moveEvents, onmove); - $document.on(_releaseEvents, onrelease); - // This event is used to receive manually triggered mouse move events - // jqLite unfortunately only supports triggerHandler(...) - // See http://api.jquery.com/triggerHandler/ - // _deregisterRootMoveListener = $rootScope.$on('draggable:_triggerHandlerMove', onmove); - _deregisterRootMoveListener = $rootScope.$on('draggable:_triggerHandlerMove', function(event, origEvent) { - onmove(origEvent); - }); - }; + _mx = ngDraggable.inputEvent(evt).pageX;//ngDraggable.getEventProp(evt, 'pageX'); + _my = ngDraggable.inputEvent(evt).pageY;//ngDraggable.getEventProp(evt, 'pageY'); + _mrx = _mx - offset.left; + _mry = _my - offset.top; + if (_centerAnchor) { + _tx = _mx - element.centerX - $window.pageXOffset; + _ty = _my - element.centerY - $window.pageYOffset; + } else { + _tx = _mx - _mrx - $window.pageXOffset; + _ty = _my - _mry - $window.pageYOffset; + } - var onmove = function (evt) { - if (!_dragEnabled)return; - evt.preventDefault(); + $document.on(_moveEvents, onmove); + $document.on(_releaseEvents, onrelease); + // This event is used to receive manually triggered mouse move events + // jqLite unfortunately only supports triggerHandler(...) + // See http://api.jquery.com/triggerHandler/ + // _deregisterRootMoveListener = $rootScope.$on('draggable:_triggerHandlerMove', onmove); + _deregisterRootMoveListener = $rootScope.$on('draggable:_triggerHandlerMove', function(event, origEvent) { + onmove(origEvent); + }); + }; - if (!element.hasClass('dragging')) { - _data = getDragData(scope); - element.addClass('dragging'); - $rootScope.$broadcast('draggable:start', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data}); - } + var onmove = function (evt) { + if (!_dragEnabled)return; + evt.preventDefault(); - _mx = ngDraggable.inputEvent(evt).pageX;//ngDraggable.getEventProp(evt, 'pageX'); - _my = ngDraggable.inputEvent(evt).pageY;//ngDraggable.getEventProp(evt, 'pageY'); + if (!element.hasClass('dragging')) { + _data = getDragData(scope); + element.addClass('dragging'); + $rootScope.$broadcast('draggable:start', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data}); - if (_centerAnchor) { - _tx = _mx - element.centerX - _dragOffset.left; - _ty = _my - element.centerY - _dragOffset.top; - } else { - _tx = _mx - _mrx - _dragOffset.left; - _ty = _my - _mry - _dragOffset.top; + if (onDragStartCallback ){ + scope.$apply(function () { + onDragStartCallback(scope, {$data: _data, $event: evt}); + }); } + } - moveElement(_tx, _ty); + _mx = ngDraggable.inputEvent(evt).pageX;//ngDraggable.getEventProp(evt, 'pageX'); + _my = ngDraggable.inputEvent(evt).pageY;//ngDraggable.getEventProp(evt, 'pageY'); - $rootScope.$broadcast('draggable:move', { x: _mx, y: _my, tx: _tx, ty: _ty, event: evt, element: element, data: _data, uid: _myid, dragOffset: _dragOffset }); - }; + if (_centerAnchor) { + _tx = _mx - element.centerX - _dragOffset.left; + _ty = _my - element.centerY - _dragOffset.top; + } else { + _tx = _mx - _mrx - _dragOffset.left; + _ty = _my - _mry - _dragOffset.top; + } - var onrelease = function(evt) { - if (!_dragEnabled) - return; - evt.preventDefault(); - $rootScope.$broadcast('draggable:end', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data, callback:onDragComplete, uid: _myid}); - element.removeClass('dragging'); - element.parent().find('.drag-enter').removeClass('drag-enter'); - reset(); - $document.off(_moveEvents, onmove); - $document.off(_releaseEvents, onrelease); - _deregisterRootMoveListener(); - }; + moveElement(_tx, _ty); - var onDragComplete = function(evt) { - if (!onDragSuccessCallback )return; + $rootScope.$broadcast('draggable:move', { x: _mx, y: _my, tx: _tx, ty: _ty, event: evt, element: element, data: _data, uid: _myid, dragOffset: _dragOffset }); + }; + var onrelease = function(evt) { + if (!_dragEnabled) + return; + evt.preventDefault(); + $rootScope.$broadcast('draggable:end', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data, callback:onDragComplete, uid: _myid}); + element.removeClass('dragging'); + element.parent().find('.drag-enter').removeClass('drag-enter'); + reset(); + $document.off(_moveEvents, onmove); + $document.off(_releaseEvents, onrelease); + + if (onDragStopCallback ){ scope.$apply(function () { - onDragSuccessCallback(scope, {$data: _data, $event: evt}); + onDragStopCallback(scope, {$data: _data, $event: evt}); }); - }; + } + + _deregisterRootMoveListener(); + }; + + var onDragComplete = function(evt) { + - var reset = function() { - if(allowTransform) + if (!onDragSuccessCallback )return; + + scope.$apply(function () { + onDragSuccessCallback(scope, {$data: _data, $event: evt}); + }); + }; + + var reset = function() { + if(allowTransform) element.css({transform:'', 'z-index':'', '-webkit-transform':'', '-ms-transform':''}); - else + else element.css({'position':'',top:'',left:''}); - }; - - var moveElement = function (x, y) { - if(allowTransform) { - element.css({ - transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + x + ', ' + y + ', 0, 1)', - 'z-index': 99999, - '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + x + ', ' + y + ', 0, 1)', - '-ms-transform': 'matrix(1, 0, 0, 1, ' + x + ', ' + y + ')' - }); - }else{ - element.css({'left':x+'px','top':y+'px', 'position':'fixed'}); - } - }; - initialize(); - } - }; - }]) - - .directive('ngDrop', ['$parse', '$timeout', '$window', '$document', 'ngDraggable', function ($parse, $timeout, $window, $document, ngDraggable) { - return { - restrict: 'A', - link: function (scope, element, attrs) { - scope.value = attrs.ngDrop; - scope.isTouching = false; - - var _lastDropTouch=null; - - var _myid = scope.$id; - - var _dropEnabled=false; - - var onDropCallback = $parse(attrs.ngDropSuccess);// || function(){}; - - var onDragStartCallback = $parse(attrs.ngDragStart); - var onDragStopCallback = $parse(attrs.ngDragStop); - var onDragMoveCallback = $parse(attrs.ngDragMove); - - var initialize = function () { - toggleListeners(true); - }; - - var toggleListeners = function (enable) { - // remove listeners - - if (!enable)return; - // add listeners. - scope.$watch(attrs.ngDrop, onEnableChange); - scope.$on('$destroy', onDestroy); - scope.$on('draggable:start', onDragStart); - scope.$on('draggable:move', onDragMove); - scope.$on('draggable:end', onDragEnd); - }; - - var onDestroy = function (enable) { - toggleListeners(false); - }; - var onEnableChange = function (newVal, oldVal) { - _dropEnabled=newVal; - }; - var onDragStart = function(evt, obj) { - if(! _dropEnabled)return; - isTouching(obj.x,obj.y,obj.element); - - if (attrs.ngDragStart) { - $timeout(function(){ - onDragStartCallback(scope, {$data: obj.data, $event: obj}); - }); - } - }; - var onDragMove = function(evt, obj) { - if(! _dropEnabled)return; - isTouching(obj.x,obj.y,obj.element); + }; - if (attrs.ngDragMove) { - $timeout(function(){ - onDragMoveCallback(scope, {$data: obj.data, $event: obj}); - }); - } - }; + var moveElement = function (x, y) { + if(allowTransform) { + element.css({ + transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + x + ', ' + y + ', 0, 1)', + 'z-index': 99999, + '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + x + ', ' + y + ', 0, 1)', + '-ms-transform': 'matrix(1, 0, 0, 1, ' + x + ', ' + y + ')' + }); + }else{ + element.css({'left':x+'px','top':y+'px', 'position':'fixed'}); + } + }; + initialize(); + } + }; + }]) - var onDragEnd = function (evt, obj) { + .directive('ngDrop', ['$parse', '$timeout', '$window', '$document', 'ngDraggable', function ($parse, $timeout, $window, $document, ngDraggable) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + scope.value = attrs.ngDrop; + scope.isTouching = false; - // don't listen to drop events if this is the element being dragged - // only update the styles and return - if (!_dropEnabled || _myid === obj.uid) { - updateDragStyles(false, obj.element); - return; - } - if (isTouching(obj.x, obj.y, obj.element)) { - // call the ngDraggable ngDragSuccess element callback - if(obj.callback){ - obj.callback(obj); - } + var _lastDropTouch=null; - if (attrs.ngDropSuccess) { - $timeout(function(){ - onDropCallback(scope, {$data: obj.data, $event: obj, $target: scope.$eval(scope.value)}); - }); - } + var _myid = scope.$id; + + var _dropEnabled=false; + + var onDropCallback = $parse(attrs.ngDropSuccess);// || function(){}; + + var onDragStartCallback = $parse(attrs.ngDragStart); + var onDragStopCallback = $parse(attrs.ngDragStop); + var onDragMoveCallback = $parse(attrs.ngDragMove); + + var initialize = function () { + toggleListeners(true); + }; + + var toggleListeners = function (enable) { + // remove listeners + + if (!enable)return; + // add listeners. + scope.$watch(attrs.ngDrop, onEnableChange); + scope.$on('$destroy', onDestroy); + scope.$on('draggable:start', onDragStart); + scope.$on('draggable:move', onDragMove); + scope.$on('draggable:end', onDragEnd); + }; + + var onDestroy = function (enable) { + toggleListeners(false); + }; + var onEnableChange = function (newVal, oldVal) { + _dropEnabled=newVal; + }; + var onDragStart = function(evt, obj) { + if(! _dropEnabled)return; + isTouching(obj.x,obj.y,obj.element); + + if (attrs.ngDragStart) { + $timeout(function(){ + onDragStartCallback(scope, {$data: obj.data, $event: obj}); + }); + } + }; + var onDragMove = function(evt, obj) { + if(! _dropEnabled)return; + isTouching(obj.x,obj.y,obj.element); + + if (attrs.ngDragMove) { + $timeout(function(){ + onDragMoveCallback(scope, {$data: obj.data, $event: obj}); + }); + } + }; + + var onDragEnd = function (evt, obj) { + + // don't listen to drop events if this is the element being dragged + // only update the styles and return + if (!_dropEnabled || _myid === obj.uid) { + updateDragStyles(false, obj.element); + return; + } + if (isTouching(obj.x, obj.y, obj.element)) { + // call the ngDraggable ngDragSuccess element callback + if(obj.callback){ + obj.callback(obj); } - if (attrs.ngDragStop) { + if (attrs.ngDropSuccess) { $timeout(function(){ - onDragStopCallback(scope, {$data: obj.data, $event: obj}); + onDropCallback(scope, {$data: obj.data, $event: obj, $target: scope.$eval(scope.value)}); }); } + } - updateDragStyles(false, obj.element); - }; + if (attrs.ngDragStop) { + $timeout(function(){ + onDragStopCallback(scope, {$data: obj.data, $event: obj}); + }); + } - var isTouching = function(mouseX, mouseY, dragElement) { - var touching= hitTest(mouseX, mouseY); - scope.isTouching = touching; - if(touching){ - _lastDropTouch = element; - } - updateDragStyles(touching, dragElement); - return touching; - }; - - var updateDragStyles = function(touching, dragElement) { - if(touching){ - element.addClass('drag-enter'); - dragElement.addClass('drag-over'); - }else if(_lastDropTouch == element){ - _lastDropTouch=null; - element.removeClass('drag-enter'); - dragElement.removeClass('drag-over'); - } - }; - - var hitTest = function(x, y) { - var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element); - x -= $document[0].body.scrollLeft + $document[0].documentElement.scrollLeft; - y -= $document[0].body.scrollTop + $document[0].documentElement.scrollTop; - return x >= bounds.left - && x <= bounds.right - && y <= bounds.bottom - && y >= bounds.top; - }; - - initialize(); - } - }; - }]) - .directive('ngDragClone', ['$parse', '$timeout', 'ngDraggable', function ($parse, $timeout, ngDraggable) { - return { - restrict: 'A', - link: function (scope, element, attrs) { - var img, _allowClone=true; - var _dragOffset = null; - scope.clonedData = {}; - var initialize = function () { - - img = element.find('img'); - element.attr('draggable', 'false'); - img.attr('draggable', 'false'); - reset(); - toggleListeners(true); - }; - - - var toggleListeners = function (enable) { - // remove listeners - - if (!enable)return; - // add listeners. - scope.$on('draggable:start', onDragStart); - scope.$on('draggable:move', onDragMove); - scope.$on('draggable:end', onDragEnd); - preventContextMenu(); - - }; - var preventContextMenu = function() { - // element.off('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); - img.off('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); - // element.on('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); - img.on('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); - }; - var onDragStart = function(evt, obj, elm) { - _allowClone=true; - if(angular.isDefined(obj.data.allowClone)){ - _allowClone=obj.data.allowClone; - } - if(_allowClone) { - scope.$apply(function () { - scope.clonedData = obj.data; - }); - element.css('width', obj.element[0].offsetWidth); - element.css('height', obj.element[0].offsetHeight); + updateDragStyles(false, obj.element); + }; - moveElement(obj.tx, obj.ty); - } + var isTouching = function(mouseX, mouseY, dragElement) { + var touching= hitTest(mouseX, mouseY); + scope.isTouching = touching; + if(touching){ + _lastDropTouch = element; + } + updateDragStyles(touching, dragElement); + return touching; + }; - }; - var onDragMove = function(evt, obj) { - if(_allowClone) { + var updateDragStyles = function(touching, dragElement) { + if(touching){ + element.addClass('drag-enter'); + dragElement.addClass('drag-over'); + }else if(_lastDropTouch == element){ + _lastDropTouch=null; + element.removeClass('drag-enter'); + dragElement.removeClass('drag-over'); + } + }; - _tx = obj.tx + obj.dragOffset.left; - _ty = obj.ty + obj.dragOffset.top; + var hitTest = function(x, y) { + var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element); + x -= $document[0].body.scrollLeft + $document[0].documentElement.scrollLeft; + y -= $document[0].body.scrollTop + $document[0].documentElement.scrollTop; + return x >= bounds.left + && x <= bounds.right + && y <= bounds.bottom + && y >= bounds.top; + }; - moveElement(_tx, _ty); - } - }; - var onDragEnd = function(evt, obj) { - //moveElement(obj.tx,obj.ty); - if(_allowClone) { - reset(); - } - }; + initialize(); + } + }; + }]) + .directive('ngDragClone', ['$parse', '$timeout', 'ngDraggable', function ($parse, $timeout, ngDraggable) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + var img, _allowClone=true; + var _dragOffset = null; + scope.clonedData = {}; + var initialize = function () { - var reset = function() { - element.css({left:0,top:0, position:'fixed', 'z-index':-1, visibility:'hidden'}); - }; - var moveElement = function(x,y) { - element.css({ - transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999, 'visibility': 'visible', - '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', - '-ms-transform': 'matrix(1, 0, 0, 1, '+x+', '+y+')' - //,margin: '0' don't monkey with the margin, + img = element.find('img'); + element.attr('draggable', 'false'); + img.attr('draggable', 'false'); + reset(); + toggleListeners(true); + }; + + + var toggleListeners = function (enable) { + // remove listeners + + if (!enable)return; + // add listeners. + scope.$on('draggable:start', onDragStart); + scope.$on('draggable:move', onDragMove); + scope.$on('draggable:end', onDragEnd); + preventContextMenu(); + + }; + var preventContextMenu = function() { + // element.off('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); + img.off('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); + // element.on('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); + img.on('mousedown touchstart touchmove touchend touchcancel', absorbEvent_); + }; + var onDragStart = function(evt, obj, elm) { + _allowClone=true; + if(angular.isDefined(obj.data.allowClone)){ + _allowClone=obj.data.allowClone; + } + if(_allowClone) { + scope.$apply(function () { + scope.clonedData = obj.data; }); - }; - - var absorbEvent_ = function (event) { - var e = event;//.originalEvent; - e.preventDefault && e.preventDefault(); - e.stopPropagation && e.stopPropagation(); - e.cancelBubble = true; - e.returnValue = false; - return false; - }; - - initialize(); - } - }; - }]) + element.css('width', obj.element[0].offsetWidth); + element.css('height', obj.element[0].offsetHeight); + + moveElement(obj.tx, obj.ty); + } + + }; + var onDragMove = function(evt, obj) { + if(_allowClone) { + + _tx = obj.tx + obj.dragOffset.left; + _ty = obj.ty + obj.dragOffset.top; + + moveElement(_tx, _ty); + } + }; + var onDragEnd = function(evt, obj) { + //moveElement(obj.tx,obj.ty); + if(_allowClone) { + reset(); + } + }; + + var reset = function() { + element.css({left:0,top:0, position:'fixed', 'z-index':-1, visibility:'hidden'}); + }; + var moveElement = function(x,y) { + element.css({ + transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999, 'visibility': 'visible', + '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', + '-ms-transform': 'matrix(1, 0, 0, 1, '+x+', '+y+')' + //,margin: '0' don't monkey with the margin, + }); + }; + + var absorbEvent_ = function (event) { + var e = event;//.originalEvent; + e.preventDefault && e.preventDefault(); + e.stopPropagation && e.stopPropagation(); + e.cancelBubble = true; + e.returnValue = false; + return false; + }; + + initialize(); + } + }; + }]) .directive('ngPreventDrag', ['$parse', '$timeout', function ($parse, $timeout) { return { restrict: 'A', @@ -538,10 +555,10 @@ angular.module("ngDraggable", []) var args = Array.prototype.slice.call(arguments); if(animationIsOn) { reqAnimFrame(function () { - $rootScope.$apply(function () { - callback.apply(null, args); - nextFrame(callback); - }); + $rootScope.$apply(function () { + callback.apply(null, args); + nextFrame(callback); + }); }) } } From 5f5487fc8cc6e2e40fd1a7412b722f4fcd70b8c1 Mon Sep 17 00:00:00 2001 From: Philip Andrews Date: Fri, 15 Jul 2016 08:58:35 +1000 Subject: [PATCH 69/73] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 8f72f5b..3fb1235 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ ngDraggable =========== +> *NOTE:* +> I'm not actively maintaining this project any more. If any anyone would like to take on that responsible please get in touch + + Drag and drop module for Angular JS with support for touch devices. [`demo`](http://htmlpreview.github.io/?https://github.com/fatlinesofcode/ngDraggable/blob/master/example.html). ### Usage: From bf1c0648251ea98494ebb406e2aee10d41622d00 Mon Sep 17 00:00:00 2001 From: phil Date: Fri, 15 Jul 2016 09:06:13 +1000 Subject: [PATCH 70/73] added npm package. bumped version --- bower.json | 2 +- package.json | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 package.json diff --git a/bower.json b/bower.json index 18ef273..3a8d8f1 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ngDraggable", "main": "ngDraggable.js", - "version": "0.1.8", + "version": "0.1.10", "homepage": "https://github.com/fatlinesofcode/ngDraggable", "ignore": [ "**/.*", diff --git a/package.json b/package.json new file mode 100644 index 0000000..d9db26a --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "ngdraggable", + "version": "0.1.10", + "description": "Drag and drop module for Angular JS with support for touch devices", + "main": "ngDraggable.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/fatlinesofcode/ngDraggable.git" + }, + "author": "philip andrews", + "license": "MIT", + "bugs": { + "url": "https://github.com/fatlinesofcode/ngDraggable/issues" + }, + "homepage": "https://github.com/fatlinesofcode/ngDraggable#readme" +} From 41f70632c6763804357305c354883d0527c0b763 Mon Sep 17 00:00:00 2001 From: phil Date: Wed, 14 Sep 2016 16:49:03 +1000 Subject: [PATCH 71/73] check which touch event is trigger. Attempt to allow devices with both touch and mouse support to work better --- ngDraggable.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ngDraggable.js b/ngDraggable.js index 3f4a2ee..3b75dd6 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -18,6 +18,8 @@ angular.module("ngDraggable", []) return event; }; + scope.touchTimeout = 100; + }]) .directive('ngDrag', ['$rootScope', '$parse', '$document', '$window', 'ngDraggable', function ($rootScope, $parse, $document, $window, ngDraggable) { return { @@ -82,7 +84,8 @@ angular.module("ngDraggable", []) // no handle(s) specified, use the element as the handle element.on(_pressEvents, onpress); } - if(! _hasTouch && element[0].nodeName.toLowerCase() == "img"){ + // if(! _hasTouch && element[0].nodeName.toLowerCase() == "img"){ + if( element[0].nodeName.toLowerCase() == "img"){ element.on('mousedown', function(){ return false;}); // prevent native drag for images } }; @@ -107,6 +110,7 @@ angular.module("ngDraggable", []) * On touch devices as a small delay so as not to prevent native window scrolling */ var onpress = function(evt) { + // console.log("110"+" onpress: "+Math.random()+" "+ evt.type); if(! _dragEnabled)return; if (isClickableElement(evt)) { @@ -118,12 +122,15 @@ angular.module("ngDraggable", []) return; } - if(_hasTouch){ + var useTouch = evt.type === 'touchstart' ? true : false; + + + if(useTouch){ cancelPress(); _pressTimer = setTimeout(function(){ cancelPress(); onlongpress(evt); - },100); + },ngDraggable.touchTimeout); $document.on(_moveEvents, cancelPress); $document.on(_releaseEvents, cancelPress); }else{ From a7d83ca49cb6fe29c0a0d5167edd945c7b86faad Mon Sep 17 00:00:00 2001 From: phil Date: Wed, 28 Sep 2016 20:21:01 +1000 Subject: [PATCH 72/73] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d9db26a..d80e56a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ngdraggable", - "version": "0.1.10", + "version": "0.1.11", "description": "Drag and drop module for Angular JS with support for touch devices", "main": "ngDraggable.js", "scripts": { From d55490ce67e6c15909558e70f0854820cca3d389 Mon Sep 17 00:00:00 2001 From: philip andrews Date: Wed, 1 Mar 2017 16:14:12 +1100 Subject: [PATCH 73/73] fire onmove as soon as touch begins --- ngDraggable.js | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ngDraggable.js b/ngDraggable.js index 3b75dd6..a7744de 100644 --- a/ngDraggable.js +++ b/ngDraggable.js @@ -130,6 +130,7 @@ angular.module("ngDraggable", []) _pressTimer = setTimeout(function(){ cancelPress(); onlongpress(evt); + onmove(evt); },ngDraggable.touchTimeout); $document.on(_moveEvents, cancelPress); $document.on(_releaseEvents, cancelPress); diff --git a/package.json b/package.json index d80e56a..5c656b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ngdraggable", - "version": "0.1.11", + "version": "0.1.12", "description": "Drag and drop module for Angular JS with support for touch devices", "main": "ngDraggable.js", "scripts": {