Skip to content

Commit ce3bbb5

Browse files
committedSep 6, 2015
feat(sortable): Closes #59, #92, #155. Enable sorting with insertInline with ngAnimate
1 parent 824fe35 commit ce3bbb5

File tree

5 files changed

+150
-11
lines changed

5 files changed

+150
-11
lines changed
 

‎README.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
Implementing jQueryUI Drag and Drop functionality in AngularJS is easier than ever which is a wrapper for jQueryUI draggable/droppable components.
66

77

8-
###v1.0.9 - breaking change
9-
1. Draggable and Droppable will not be [deep copied](https://egghead.io/lessons/angularjs-angular-copy-for-deep-copy) by default unlike previous versions. Use `deepCopy` option if prototypical inheritance is not required.
10-
2. Callbacks will not be executed forcefully within the context of scope which requires an extra digest loop for each event (start, stop, over, out, etc), especially drag that fires many times and running a digest loop is performance intensive in such scenario. Call `scope.$apply()` within callback, if needed.
11-
12-
138
##How to Use
149

1510
* `bower install angular-dragdrop` (or `sudo bower install angular-dragdrop --allow-root`)
@@ -44,6 +39,8 @@ Implementing jQueryUI Drag and Drop functionality in AngularJS is easier than ev
4439
* **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.
4540
* **deepCopy** - boolean (optional) – If true, makes a deep copy of draggable that looses prototypical inheritance.
4641
* **beforeDrop** – promise (optional) – Ask for confirmation before swapping. Works with both window.confirm and custom popup.
42+
* **insertInline** – boolean(optional) – Make a list sortable. Same model is mandatory for draggable and droppable.
43+
* **direction** – string(optional) – Property name that will be created on each scope to manage animation direction.
4744
* **data-drag** – boolean – If true, element can be draggable. Disabled otherwise.
4845
* **data-jqyoui-options** – object – should hold all the valid options supported by [jQueryUI Draggable](http://api.jqueryui.com/draggable)
4946
* **ng-model** – string – An angular model defined in a controller. Should be a JS array or object
@@ -76,6 +73,11 @@ Implementing jQueryUI Drag and Drop functionality in AngularJS is easier than ev
7673
Demo is [here](http://codef0rmer.github.io/angular-dragdrop/#/)
7774

7875

76+
###v1.0.9 - breaking change
77+
1. Draggable and Droppable will not be [deep copied](https://egghead.io/lessons/angularjs-angular-copy-for-deep-copy) by default unlike previous versions. Use `deepCopy` option if prototypical inheritance is not required.
78+
2. Callbacks will not be executed forcefully within the context of scope which requires an extra digest loop for each event (start, stop, over, out, etc), especially drag that fires many times and running a digest loop is performance intensive in such scenario. Call `scope.$apply()` within callback, if needed.
79+
80+
7981
###v1.0.5 - breaking change
8082
Do not pass evaluated expressions in callbacks. For example,
8183
####Before:

‎bower.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
},
2222
"devDependencies": {
2323
"angular-mocks": "latest",
24-
"angular-ui-bootstrap-bower": "latest"
24+
"angular-ui-bootstrap-bower": "latest",
25+
"angular-animate": "latest"
2526
}
2627
}

‎demo/dnd-insertInline.html

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<!DOCTYPE html>
2+
<html ng-app="drag-and-drop">
3+
<head lang="en">
4+
<meta charset="utf-8">
5+
<title>Drag &amp; Drop: Guess A Name</title>
6+
<!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
7+
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
8+
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
9+
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />
10+
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.min.css" rel="stylesheet"> -->
11+
<script src="../components/jquery/dist/jquery.min.js"></script>
12+
<script src="../components/jquery-ui/jquery-ui.min.js"></script>
13+
<script src="../components/angular/angular.min.js"></script>
14+
<script src="../components/angular-animate/angular-animate.js"></script>
15+
<script src="../src/angular-dragdrop.js"></script>
16+
<link href="assets/css/bootstrap.min.css" rel="stylesheet">
17+
<style>
18+
body {
19+
padding: 30px;
20+
}
21+
.thumbnails[jqyoui-droppable], .thumbnail[jqyoui-droppable] { border: 1px solid red; }
22+
.thumbnail {
23+
height: 50px;
24+
width: 50px;
25+
text-align: center;
26+
padding-top: 0px;
27+
cursor: pointer;
28+
background: rgb(182, 173, 123);
29+
position: relative;
30+
-webkit-transition: none;
31+
transition: none;
32+
}
33+
34+
.thumbnail[data-drag="false"] { background: green; }
35+
36+
.thumbnail.ng-leave {
37+
-webkit-transition-duration: 0s;
38+
transition-duration: 0s;
39+
opacity: 1;
40+
}
41+
42+
.thumbnail.ng-leave.ng-leave-active {
43+
opacity: 0;
44+
}
45+
46+
.thumbnail.ng-enter {
47+
-webkit-transition: left 0.3s;
48+
transition: left 0.3s;
49+
}
50+
.thumbnail.ng-enter[data-direction="left"] {
51+
left: -80px;
52+
}
53+
.thumbnail.ng-enter[data-direction="right"] {
54+
left: 80px;
55+
}
56+
.thumbnail.ng-enter.ng-enter-active {
57+
left: 0px;
58+
}
59+
</style>
60+
61+
<script type="text/javascript">
62+
var App = angular.module('drag-and-drop', ['ngAnimate', 'ngDragDrop']);
63+
64+
App.controller('oneCtrl', function($scope) {
65+
$scope.list1 = [
66+
{ 'title': 'N', 'drag': true },
67+
{ 'title': 'L', 'drag': true },
68+
{ 'title': 'I', 'drag': true },
69+
{ 'title': 'I', 'drag': true },
70+
{ 'title': 'E', 'drag': true },
71+
{ 'title': 'N', 'drag': true }
72+
];
73+
});
74+
</script>
75+
</head>
76+
<body>
77+
<div ng-controller="oneCtrl">
78+
<div class='contentWrapper ng-cloak'>
79+
<div class='content'>
80+
<div class="row-fluid">
81+
<ul class="thumbnails">
82+
<li class="thumbnail" ng-repeat="item in list1" data-drop="true" data-drag="true" ng-model="list1" jqyoui-droppable="{index: {{$index}}}" jqyoui-draggable="{index: {{$index}}, insertInline: true, direction:'jqyouiDirection'}" data-jqyoui-options="{revert: 'invalid'}" data-direction="{{item.jqyouiDirection}}">
83+
<h1>{{item.title}}</h1>
84+
</li>
85+
</ul>
86+
</div>
87+
</div>
88+
</div>
89+
</div>
90+
</body>
91+
</html>

‎src/angular-dragdrop.js

+29-5
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti
7878
droppableScope = this.droppableScope,
7979
draggableScope = this.draggableScope,
8080
$helper = null,
81-
promises = [];
81+
promises = [],
82+
temp;
8283

8384
dragModel = $draggable.ngattr('ng-model');
8485
dropModel = $droppable.ngattr('ng-model');
@@ -117,7 +118,26 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti
117118
}
118119

119120
$q.all(promises).then(angular.bind(this, function() {
120-
if (dragSettings.animate === true) {
121+
if (dragSettings.insertInline && dragModel === dropModel) {
122+
if (dragSettings.index > dropSettings.index) {
123+
temp = dragModelValue[dragSettings.index];
124+
for (var i = dragSettings.index; i > dropSettings.index; i--) {
125+
dropModelValue[i] = angular.copy(dropModelValue[i - 1]);
126+
dropModelValue[i - 1] = {};
127+
dropModelValue[i][dragSettings.direction] = 'left';
128+
}
129+
dropModelValue[dropSettings.index] = temp;
130+
} else {
131+
temp = dragModelValue[dragSettings.index];
132+
for (var i = dragSettings.index; i < dropSettings.index; i++) {
133+
dropModelValue[i] = angular.copy(dropModelValue[i + 1]);
134+
dropModelValue[i + 1] = {};
135+
dropModelValue[i][dragSettings.direction] = 'right';
136+
}
137+
dropModelValue[dropSettings.index] = temp;
138+
}
139+
this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui);
140+
} else if (dragSettings.animate === true) {
121141
// be nice with absolutely positioned brethren :-)
122142
$helper = $draggable.clone();
123143
$helper.css({'position': 'absolute'}).css($draggable.offset());
@@ -145,9 +165,9 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti
145165
this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui);
146166
}));
147167
}
148-
}), function() {
149-
ui.draggable.css({left: '', top: ''});
150-
});
168+
})).finally(angular.bind(this, function() {
169+
this.restore($draggable);
170+
}));
151171
};
152172

153173
this.move = function($fromEl, $toEl, toPos, duration, dropSettings, callback) {
@@ -250,6 +270,10 @@ var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$ti
250270
}
251271
}
252272

273+
this.restore($draggable);
274+
};
275+
276+
this.restore = function($draggable) {
253277
$draggable.css({'z-index': '', 'left': '', 'top': ''});
254278
};
255279

‎test/spec/tests.js

+21
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,25 @@ describe('Service: ngDragDropService', function() {
179179
scope.list = {title: 'Item 1'};
180180
expect(ngDragDropService.fixIndex(scope, {applyFilter: 'filterIt'}, scope.list)).toBe(undefined);
181181
});
182+
183+
it('should support insertInline option', function() {
184+
scope.list = [
185+
{ 'title': 'N' },
186+
{ 'title': 'L' },
187+
{ 'title': 'I' },
188+
{ 'title': 'I' },
189+
{ 'title': 'E' },
190+
{ 'title': 'N' }
191+
];
192+
ngDragDropService.draggableScope = ngDragDropService.droppableScope = scope;
193+
expect(scope.list.map(function(item) { return item.title; }).join('')).toBe('NLIIEN');
194+
ngDragDropService.invokeDrop(
195+
$('<div data-drop="true" data-drag="true" ng-model="list" jqyoui-droppable="{index: 5}" jqyoui-draggable="{index: 5, insertInline: true, direction:\'jqyouiDirection\'}">' + scope.list[5].title + '</div>').data('$scope', scope),
196+
$('<div data-drop="true" data-drag="true" ng-model="list" jqyoui-droppable="{index: 0}" jqyoui-draggable="{index: 0, insertInline: true, direction:\'jqyouiDirection\'}">' + scope.list[0].title + '</div>').data('$scope', scope),
197+
document.createEvent('Event'),
198+
{}
199+
);
200+
timeout.flush();
201+
expect(scope.list.map(function(item) { return item.title; }).join('')).toBe('NNLIIE');
202+
});
182203
});

0 commit comments

Comments
 (0)
Please sign in to comment.