From f1534a2f04b939ca209c744154b6c8e1e8a8cfb3 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 8 Aug 2014 15:11:48 -0700 Subject: [PATCH] sortable as a new attribute - fixed animations and added README.md. --- README.md | 1 + demo/dnd-ctrls-sortable.html | 89 ++++++++++++++++++++++++++++++++++++ src/angular-dragdrop.js | 74 ++++++++++++++++++++++-------- 3 files changed, 145 insertions(+), 19 deletions(-) create mode 100644 demo/dnd-ctrls-sortable.html diff --git a/README.md b/README.md index 9507ec1..90df291 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Do not pass evaluated expressions in callbacks. For example, * **onStart** – string – callback method to be invoked (has to be defined in a controller) when dragging starts * **onStop** – string – callback method to be invoked when dragging stops * **onDrag** – string – callback method to be invoked while the mouse is moved during the dragging + * **sortable** – boolean – If true, the dropped item will be inserted after the droppable and the rest of the items will rotate upwards towards the droppable. This will only work when the draggable and droppable use the same model. * **applyFilter** - string - applies AngularJS $filter on the list before swapping items. Only applicable, if ngRepeat has any filter (such as orderBy, limitTo) associated with it. * **containment** – string - position/offset. Offset by default. This forces to use jQuery.position() or jQuery.offset() to calculate proper position with respect to parent element or document respectively. * **data-drag** – boolean – If true, element can be draggable. Disabled otherwise. diff --git a/demo/dnd-ctrls-sortable.html b/demo/dnd-ctrls-sortable.html new file mode 100644 index 0000000..87b212a --- /dev/null +++ b/demo/dnd-ctrls-sortable.html @@ -0,0 +1,89 @@ + + + + + Drag & Drop: Guess A Name + + + + + + + + + + + +

Whose dialog is it? "What is it, Precious? What is it?"

+
+
+
+
+
    +
  • +
    +

    + {{item.title}} +

    +
    +
  • +
+
+
+
+
+ + \ No newline at end of file diff --git a/src/angular-dragdrop.js b/src/angular-dragdrop.js index b4ade31..1fff4db 100644 --- a/src/angular-dragdrop.js +++ b/src/angular-dragdrop.js @@ -38,10 +38,10 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti callback = objExtract.callback, constructor = objExtract.constructor, args = [event, ui].concat(objExtract.args); - + // call either $scoped method i.e. $scope.dropCallback or constructor's method i.e. this.dropCallback scope.$apply((scope[callback] || scope[constructor][callback]).apply(scope, args)); - + function extract(callbackName) { var atStartBracket = callbackName.indexOf('(') !== -1 ? callbackName.indexOf('(') : callbackName.length, atEndBracket = callbackName.lastIndexOf(')') !== -1 ? callbackName.lastIndexOf(')') : callbackName.length, @@ -70,7 +70,6 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti $droppableDraggable = null, droppableScope = $droppable.scope(), draggableScope = $draggable.scope(); - dragModel = $draggable.ngattr('ng-model'); dropModel = $droppable.ngattr('ng-model'); dragModelValue = draggableScope.$eval(dragModel); @@ -87,6 +86,19 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti jqyoui_pos = angular.isArray(dragModelValue) ? dragSettings.index : null; dragItem = angular.copy(angular.isArray(dragModelValue) ? dragModelValue[jqyoui_pos] : dragModelValue); + var resetCSS = angular.bind(this, function () { + $timeout(angular.bind(this, function () { + // Do not move this into move() to avoid flickering issue + $draggable.css({'position': 'relative', 'left': '', 'top': ''}); + // Angular v1.2 uses ng-hide to hide an element not display property + // so we've to manually remove display:none set in this.move() + $droppableDraggable.css({'position': 'relative', 'left': '', 'top': '', 'display': ''}); + + this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable); + this.mutateDroppable(droppableScope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos); + this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui); + })); + }); if (angular.isArray(dropModelValue) && dropSettings && dropSettings.index !== undefined) { dropItem = dropModelValue[dropSettings.index]; } else if (!angular.isArray(dropModelValue)) { @@ -96,21 +108,37 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti } dropItem = angular.copy(dropItem); + if (dragSettings.animate === true) { - this.move($draggable, $droppableDraggable.length > 0 ? $droppableDraggable : $droppable, null, 'fast', dropSettings, null); - this.move($droppableDraggable.length > 0 && !dropSettings.multiple ? $droppableDraggable : [], $draggable.parent('[jqyoui-droppable],[data-jqyoui-droppable]'), jqyoui.startXY, 'fast', dropSettings, angular.bind(this, function() { - $timeout(angular.bind(this, function() { - // Do not move this into move() to avoid flickering issue - $draggable.css({'position': 'relative', 'left': '', 'top': ''}); - // Angular v1.2 uses ng-hide to hide an element not display property - // so we've to manually remove display:none set in this.move() - $droppableDraggable.css({'position': 'relative', 'left': '', 'top': '', 'display': ''}); - - this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable); - this.mutateDroppable(droppableScope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos); - this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui); - })); - })); + var allDraggables = $('.ui-draggable').toArray(); + // might be replacement for above line - but ngAnimate could resolve this issue. + // $('[ng-model="' + dragModel + '"][data-drag],[ng_model="' + dragModel + '"][data-drag],[ng\\:model="' + dragModel + '"][data-drag]').length + if (dragSettings.sortable) { + //Left slide + if (dropSettings.index > dragSettings.index) { + this.move($draggable, $droppableDraggable.length > 0 ? $droppableDraggable : $droppable, null, 'fast', dropSettings, null); + for (var i = dropSettings.index ; i > dragSettings.index; i--) { + if(i === dragSettings.index + 1){ + this.move(angular.element(allDraggables[i]), $draggable.parent('[jqyoui-droppable],[data-jqyoui-droppable]'), jqyoui.startXY,'fast', dropSettings, resetCSS); + }else{ + this.move(angular.element(allDraggables[i]), angular.element(allDraggables[i - 1]), null, 'fast', dropSettings, null); + } + } + } else { + //Right slide + this.move($draggable, $droppableDraggable.length > 0 ? $droppableDraggable : $droppable, null, 'fast', dropSettings, null); + for (var i = dropSettings.index ; i < dragSettings.index; i++) { + if(i === dragSettings.index - 1){ + this.move(angular.element(allDraggables[i]), $draggable.parent('[jqyoui-droppable],[data-jqyoui-droppable]'), jqyoui.startXY,'fast', dropSettings, resetCSS); + }else{ + this.move(angular.element(allDraggables[i]), angular.element(allDraggables[i + 1]), null, 'fast', dropSettings, null); + } + } + } + } else { + this.move($draggable, $droppableDraggable.length > 0 ? $droppableDraggable : $droppable, null, 'fast', dropSettings, null); + this.move($droppableDraggable.length > 0 && !dropSettings.multiple ? $droppableDraggable : [], $draggable.parent('[jqyoui-droppable],[data-jqyoui-droppable]'), jqyoui.startXY, 'fast', dropSettings, resetCSS); + } } else { $timeout(angular.bind(this, function() { this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable); @@ -171,7 +199,11 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti if (angular.isArray(dropModelValue)) { if (dropSettings && dropSettings.index >= 0) { - dropModelValue[dropSettings.index] = dragItem; + if (dragSettings.sortable) { + dropModelValue.splice(dropSettings.index, 0, dragItem); + } else { + dropModelValue[dropSettings.index] = dragItem; + } } else { dropModelValue.push(dragItem); } @@ -207,7 +239,11 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti dragModelValue.splice(dragSettings.index, 1); } } else { - dragModelValue[dragSettings.index] = dropItem; + if (dragSettings.sortable) { + dragModelValue.splice(dragSettings.index, 1); + } else { + dragModelValue[dragSettings.index] = dropItem; + } } } else { // Fix: LIST(object) to LIST(array) - model does not get updated using just scope[dragModel] = {...}