Skip to content
This repository was archived by the owner on Sep 8, 2020. It is now read-only.

Commit 54de466

Browse files
committed
Merge pull request #261 from thgreasi/extraProperties
feat(sortable): add extra properties to ui.item.sortable
2 parents 2e22b0e + 3a845c5 commit 54de466

File tree

4 files changed

+379
-5
lines changed

4 files changed

+379
-5
lines changed

src/sortable.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ angular.module('ui.sortable', [])
3333
return (/left|right/).test(item.css('float')) || (/inline|table-cell/).test(item.css('display'));
3434
}
3535

36+
function afterStop(e, ui) {
37+
ui.item.sortable._destroy();
38+
}
39+
3640
var opts = {};
3741

3842
// directive specific options
@@ -84,7 +88,10 @@ angular.module('ui.sortable', [])
8488

8589
// Save the starting position of dragged item
8690
ui.item.sortable = {
91+
model: ngModel.$modelValue[ui.item.index()],
8792
index: ui.item.index(),
93+
source: ui.item.parent(),
94+
sourceModel: ngModel.$modelValue,
8895
cancel: function () {
8996
ui.item.sortable._isCanceled = true;
9097
},
@@ -95,7 +102,12 @@ angular.module('ui.sortable', [])
95102
return !!ui.item.sortable._isCustomHelperUsed;
96103
},
97104
_isCanceled: false,
98-
_isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed
105+
_isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed,
106+
_destroy: function () {
107+
angular.forEach(ui.item.sortable, function(value, key) {
108+
ui.item.sortable[key] = undefined;
109+
});
110+
}
99111
};
100112
};
101113

@@ -136,7 +148,9 @@ angular.module('ui.sortable', [])
136148
// the value will be overwritten with the old value
137149
if(!ui.item.sortable.received) {
138150
ui.item.sortable.dropindex = ui.item.index();
139-
ui.item.sortable.droptarget = ui.item.parent();
151+
var droptarget = ui.item.parent();
152+
ui.item.sortable.droptarget = droptarget;
153+
ui.item.sortable.droptargetModel = droptarget.scope().$eval(droptarget.attr('ng-model'));
140154

141155
// Cancel the sort (let ng-repeat do the sort for us)
142156
// Don't cancel if this is the received list because it has
@@ -262,6 +276,8 @@ angular.module('ui.sortable', [])
262276
// call apply after stop
263277
value = combineCallbacks(
264278
value, function() { scope.$apply(); });
279+
280+
value = combineCallbacks(value, afterStop);
265281
}
266282
// wrap the callback
267283
value = combineCallbacks(callbacks[key], value);
@@ -277,6 +293,9 @@ angular.module('ui.sortable', [])
277293

278294
angular.forEach(callbacks, function(value, key) {
279295
opts[key] = combineCallbacks(value, opts[key]);
296+
if( key === 'stop' ){
297+
opts[key] = combineCallbacks(opts[key], afterStop);
298+
}
280299
});
281300

282301
} else {

test/sortable.e2e.callbacks.spec.js

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ describe('uiSortable', function() {
66
beforeEach(module('ui.sortable'));
77
beforeEach(module('ui.sortable.testHelper'));
88

9-
var EXTRA_DY_PERCENTAGE, listContent;
9+
var EXTRA_DY_PERCENTAGE, listContent, hasUndefinedProperties;
1010

1111
beforeEach(inject(function (sortableTestHelper) {
1212
EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE;
1313
listContent = sortableTestHelper.listContent;
14+
hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties;
1415
}));
1516

1617
describe('Callbacks related', function() {
@@ -188,6 +189,133 @@ describe('uiSortable', function() {
188189
});
189190
});
190191

192+
it('should properly set ui.item.sortable properties', function() {
193+
inject(function($compile, $rootScope) {
194+
var element, updateCallbackExpectations;
195+
element = $compile('<ul ui-sortable="opts" ng-model="items"><li ng-repeat="item in items" id="s-{{$index}}">{{ item }}</li></ul>')($rootScope);
196+
$rootScope.$apply(function() {
197+
$rootScope.opts = {
198+
update: function(e, ui) {
199+
if (ui.item.scope().item === 'Two') {
200+
ui.item.sortable.cancel();
201+
}
202+
updateCallbackExpectations(ui.item.sortable);
203+
}
204+
};
205+
$rootScope.items = ['One', 'Two', 'Three'];
206+
});
207+
208+
host.append(element);
209+
210+
$rootScope.$apply(function() {
211+
});
212+
var li = element.find(':eq(1)');
213+
var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight();
214+
updateCallbackExpectations = function(uiItemSortable) {
215+
expect(uiItemSortable.model).toEqual('Two');
216+
expect(uiItemSortable.index).toEqual(1);
217+
expect(uiItemSortable.source.length).toEqual(1);
218+
expect(uiItemSortable.source[0]).toBe(host.children()[0]);
219+
expect(uiItemSortable.sourceModel).toBe($rootScope.items);
220+
expect(uiItemSortable.isCanceled()).toBe(true);
221+
expect(uiItemSortable.isCustomHelperUsed()).toBe(false);
222+
};
223+
li.simulate('drag', { dy: dy });
224+
expect($rootScope.items).toEqual(['One', 'Two', 'Three']);
225+
expect($rootScope.items).toEqual(listContent(element));
226+
updateCallbackExpectations = undefined;
227+
228+
li = element.find(':eq(0)');
229+
dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight();
230+
updateCallbackExpectations = function(uiItemSortable) {
231+
expect(uiItemSortable.model).toEqual('One');
232+
expect(uiItemSortable.index).toEqual(0);
233+
expect(uiItemSortable.source.length).toEqual(1);
234+
expect(uiItemSortable.source[0]).toBe(host.children()[0]);
235+
expect(uiItemSortable.sourceModel).toBe($rootScope.items);
236+
expect(uiItemSortable.isCanceled()).toBe(false);
237+
expect(uiItemSortable.isCustomHelperUsed()).toBe(false);
238+
};
239+
li.simulate('drag', { dy: dy });
240+
expect($rootScope.items).toEqual(['Two', 'Three', 'One']);
241+
expect($rootScope.items).toEqual(listContent(element));
242+
updateCallbackExpectations = undefined;
243+
244+
li = element.find(':eq(2)');
245+
dy = -(2 + EXTRA_DY_PERCENTAGE) * li.outerHeight();
246+
updateCallbackExpectations = function(uiItemSortable) {
247+
expect(uiItemSortable.model).toEqual('One');
248+
expect(uiItemSortable.index).toEqual(2);
249+
expect(uiItemSortable.source.length).toEqual(1);
250+
expect(uiItemSortable.source[0]).toBe(host.children()[0]);
251+
expect(uiItemSortable.sourceModel).toBe($rootScope.items);
252+
expect(uiItemSortable.isCanceled()).toBe(false);
253+
expect(uiItemSortable.isCustomHelperUsed()).toBe(false);
254+
};
255+
li.simulate('drag', { dy: dy });
256+
expect($rootScope.items).toEqual(['One', 'Two', 'Three']);
257+
expect($rootScope.items).toEqual(listContent(element));
258+
updateCallbackExpectations = undefined;
259+
260+
$(element).remove();
261+
});
262+
});
263+
264+
it('should properly free ui.item.sortable object', function() {
265+
inject(function($compile, $rootScope) {
266+
var element, uiItem, uiItemSortable_Destroy;
267+
element = $compile('<ul ui-sortable="opts" ng-model="items"><li ng-repeat="item in items" id="s-{{$index}}">{{ item }}</li></ul>')($rootScope);
268+
$rootScope.$apply(function() {
269+
$rootScope.opts = {
270+
start: function (e, ui) {
271+
uiItem = ui.item;
272+
spyOn(ui.item.sortable, '_destroy').andCallThrough();
273+
uiItemSortable_Destroy = ui.item.sortable._destroy;
274+
},
275+
update: function(e, ui) {
276+
if (ui.item.scope().item === 'Two') {
277+
ui.item.sortable.cancel();
278+
}
279+
}
280+
};
281+
$rootScope.items = ['One', 'Two', 'Three'];
282+
});
283+
284+
host.append(element);
285+
286+
var li = element.find(':eq(1)');
287+
var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight();
288+
li.simulate('drag', { dy: dy });
289+
expect($rootScope.items).toEqual(['One', 'Two', 'Three']);
290+
expect($rootScope.items).toEqual(listContent(element));
291+
expect(uiItemSortable_Destroy).toHaveBeenCalled();
292+
expect(hasUndefinedProperties(uiItem.sortable)).toBe(true);
293+
uiItem = uiItemSortable_Destroy = undefined;
294+
295+
296+
li = element.find(':eq(0)');
297+
dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight();
298+
li.simulate('drag', { dy: dy });
299+
expect($rootScope.items).toEqual(['Two', 'Three', 'One']);
300+
expect($rootScope.items).toEqual(listContent(element));
301+
expect(uiItemSortable_Destroy).toHaveBeenCalled();
302+
expect(hasUndefinedProperties(uiItem.sortable)).toBe(true);
303+
uiItem = uiItemSortable_Destroy = undefined;
304+
305+
306+
li = element.find(':eq(2)');
307+
dy = -(2 + EXTRA_DY_PERCENTAGE) * li.outerHeight();
308+
li.simulate('drag', { dy: dy });
309+
expect($rootScope.items).toEqual(['One', 'Two', 'Three']);
310+
expect($rootScope.items).toEqual(listContent(element));
311+
expect(uiItemSortable_Destroy).toHaveBeenCalled();
312+
expect(hasUndefinedProperties(uiItem.sortable)).toBe(true);
313+
uiItem = uiItemSortable_Destroy = undefined;
314+
315+
$(element).remove();
316+
});
317+
});
318+
191319
});
192320

193321
});

0 commit comments

Comments
 (0)