Skip to content

Commit 4b1cfb6

Browse files
committed
fix(*): Closes #144 - default or custom confirmation before drop
1 parent 6ee1a84 commit 4b1cfb6

File tree

4 files changed

+117
-7
lines changed

4 files changed

+117
-7
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ angular.module('myApp', ['ngDragDrop'])
5151
* **applyFilter** - string - requires if both droppable as well as draggable share the same ngModel.
5252
* **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.
5353
* **deepCopy** – boolean (optional) – If true, makes a deep copy of droppable that looses prototypical inheritance.
54+
* **beforeDrop** – promise (optional) – Ask for confirmation before dropping. Works with both window.confirm and custom popup.
5455
* **data-drop** – boolean – If true, element can be droppable. Disabled otherwise.
5556
* **data-jqyoui-options** – object – should hold all the valid options supported by [jQueryUI Droppable](http://api.jqueryui.com/droppable)
5657
* **ng-model** – string – An angular model defined in a controller. Should be a JS array or object.

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"dependencies": {
1919
"angular": "~1.x",
2020
"jquery": "2.x",
21-
"jquery-ui": "latest"
21+
"jquery-ui": "latest",
22+
"angular-ui-bootstrap-bower": "~0.12.0"
2223
},
2324
"devDependencies": {
2425
"angular-mocks": "~1.x"

demo/dnd-confirmation.html

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<!DOCTYPE html>
2+
<html ng-app="drag-and-drop">
3+
<head lang="en">
4+
<meta charset="utf-8">
5+
<title>Drag &amp; Drop: Confirm before drop</title>
6+
<script src="../components/jquery/dist/jquery.min.js"></script>
7+
<script src="../components/jquery-ui/jquery-ui.min.js"></script>
8+
<script src="../components/angular/angular.min.js"></script>
9+
<script src="../components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.js"></script>
10+
<script src="../src/angular-dragdrop.js"></script>
11+
<link href="assets/css/bootstrap.min.css" rel="stylesheet">
12+
<style type="text/css">
13+
body { padding: 50px; }
14+
</style>
15+
<script type="text/javascript">
16+
var App = angular.module('drag-and-drop', ['ngDragDrop', 'ui.bootstrap']);
17+
18+
App.controller('oneCtrl', function($scope, $q) {
19+
$scope.list1 = {title: 'Drag and Drop with default confirmation'};
20+
$scope.list2 = {};
21+
22+
$scope.beforeDrop = function() {
23+
var deferred = $q.defer();
24+
25+
if (confirm('Are you sure???')) {
26+
deferred.resolve();
27+
} else {
28+
deferred.reject();
29+
}
30+
31+
return deferred.promise;
32+
};
33+
});
34+
35+
App.controller('twoCtrl', function($scope, $q, $modal) {
36+
$scope.list1 = {title: 'Drag and Drop with custom confirmation'};
37+
$scope.list2 = {};
38+
39+
$scope.beforeDrop = function() {
40+
var modalInstance = $modal.open({
41+
templateUrl: 'myModalContent.html',
42+
controller: 'ModalInstanceCtrl'
43+
});
44+
45+
return modalInstance.result;
46+
};
47+
}).controller('ModalInstanceCtrl', function ($scope, $modalInstance) {
48+
$scope.ok = function () {
49+
$modalInstance.close();
50+
};
51+
52+
$scope.cancel = function () {
53+
$modalInstance.dismiss('cancel');
54+
};
55+
});
56+
</script>
57+
</head>
58+
<body>
59+
<h2>Default window.confirmation Vs Custom confirmation</h2>
60+
<div ng-controller="oneCtrl">
61+
<div class="row-fluid">
62+
<div class="span6">
63+
<div class="btn btn-primary" data-drag="true" ng-model="list1" jqyoui-draggable="{animate: true}" ng-hide="!list1.title">{{list1.title}}</div>
64+
</div>
65+
<div class="span6">
66+
<div class="thumbnail" data-drop="true" ng-model="list2" jqyoui-droppable="{beforeDrop: 'beforeDrop'}" ng-bind="list2.title ? 'Dropped successfully..!' : 'Drop here...'"></div>
67+
</div>
68+
</div>
69+
</div>
70+
<br><br>
71+
<div ng-controller="twoCtrl">
72+
<div class="row-fluid">
73+
<div class="span6">
74+
<div class="btn btn-primary" data-drag="true" ng-model="list1" jqyoui-draggable="{animate: true}" ng-hide="!list1.title">{{list1.title}}</div>
75+
</div>
76+
<div class="span6">
77+
<div class="thumbnail" data-drop="true" ng-model="list2" jqyoui-droppable="{beforeDrop: 'beforeDrop'}" ng-bind="list2.title ? 'Dropped successfully..!' : 'Drop here...'"></div>
78+
</div>
79+
</div>
80+
</div>
81+
82+
<script type="text/ng-template" id="myModalContent.html">
83+
<div class="modal-body">
84+
<b>Are you sure???</b>
85+
</div>
86+
<div class="modal-footer">
87+
<button class="btn btn-primary" ng-click="ok()">OK</button>
88+
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
89+
</div>
90+
</script>
91+
</body>
92+
</html>

src/angular-dragdrop.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti
4545
// call either $scoped method i.e. $scope.dropCallback or constructor's method i.e. this.dropCallback.
4646
// Removing scope.$apply call that was performance intensive (especially onDrag) and does not require it
4747
// always. So call it within the callback if needed.
48-
(scope[callback] || scope[constructor][callback]).apply(scope, args);
48+
return (scope[callback] || scope[constructor][callback]).apply(scope, args);
4949

5050
function extract(callbackName) {
5151
var atStartBracket = callbackName.indexOf('(') !== -1 ? callbackName.indexOf('(') : callbackName.length,
@@ -293,7 +293,7 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti
293293
});
294294
}
295295
};
296-
}]).directive('jqyouiDroppable', ['ngDragDropService', function(ngDragDropService) {
296+
}]).directive('jqyouiDroppable', ['ngDragDropService', '$q', function(ngDragDropService, $q) {
297297
return {
298298
restrict: 'A',
299299
priority: 1,
@@ -313,12 +313,28 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti
313313
ngDragDropService.callEventCallback(scope, dropSettings.onOut, event, ui);
314314
},
315315
drop: function(event, ui) {
316-
if (angular.element(ui.draggable).ngattr('ng-model') && attrs.ngModel) {
317-
ngDragDropService.droppableScope = scope;
318-
ngDragDropService.invokeDrop(angular.element(ui.draggable), angular.element(this), event, ui);
316+
var beforeDropPromise = null;
317+
318+
if (dropSettings.beforeDrop) {
319+
beforeDropPromise = ngDragDropService.callEventCallback(scope, dropSettings.beforeDrop, event, ui);
319320
} else {
320-
ngDragDropService.callEventCallback(scope, dropSettings.onDrop, event, ui);
321+
beforeDropPromise = (function() {
322+
var deferred = $q.defer();
323+
deferred.resolve();
324+
return deferred.promise;
325+
})();
321326
}
327+
328+
beforeDropPromise.then(angular.bind(this, function() {
329+
if (angular.element(ui.draggable).ngattr('ng-model') && attrs.ngModel) {
330+
ngDragDropService.droppableScope = scope;
331+
ngDragDropService.invokeDrop(angular.element(ui.draggable), angular.element(this), event, ui);
332+
} else {
333+
ngDragDropService.callEventCallback(scope, dropSettings.onDrop, event, ui);
334+
}
335+
}), function() {
336+
ui.draggable.css({left: '', top: ''});
337+
});
322338
}
323339
});
324340
} else {

0 commit comments

Comments
 (0)