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

Commit 51bb7b8

Browse files
author
AngularUI (via TravisCI)
committed
Travis commit : build 185
1 parent 5e9f704 commit 51bb7b8

File tree

2 files changed

+192
-165
lines changed

2 files changed

+192
-165
lines changed

sortable.js

+191-158
Original file line numberDiff line numberDiff line change
@@ -1,174 +1,207 @@
1+
(function(window, angular, undefined) { 'use strict';
12
/*
23
jQuery UI Sortable plugin wrapper
34
45
@param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config
56
*/
6-
angular.module('ui.sortable', []).value('uiSortableConfig', {}).directive('uiSortable', [
7-
'uiSortableConfig',
8-
'$timeout',
9-
'$log',
10-
function (uiSortableConfig, $timeout, $log) {
11-
'use strict';
12-
return {
13-
require: '?ngModel',
14-
link: function (scope, element, attrs, ngModel) {
15-
var savedNodes;
16-
function combineCallbacks(first, second) {
17-
if (second && typeof second === 'function') {
18-
return function (e, ui) {
19-
first(e, ui);
20-
second(e, ui);
21-
};
7+
angular.module('ui.sortable', [])
8+
.value('uiSortableConfig',{})
9+
.directive('uiSortable', [
10+
'uiSortableConfig', '$timeout', '$log',
11+
function(uiSortableConfig, $timeout, $log) {
12+
'use strict';
13+
14+
return {
15+
require: '?ngModel',
16+
link: function(scope, element, attrs, ngModel) {
17+
var savedNodes;
18+
19+
function combineCallbacks(first,second){
20+
if(second && (typeof second === 'function')) {
21+
return function(e, ui) {
22+
first(e, ui);
23+
second(e, ui);
24+
};
25+
}
26+
return first;
2227
}
23-
return first;
24-
}
25-
var opts = {};
26-
var callbacks = {
28+
29+
var opts = {};
30+
31+
var callbacks = {
2732
receive: null,
28-
remove: null,
29-
start: null,
30-
stop: null,
31-
update: null
33+
remove:null,
34+
start:null,
35+
stop:null,
36+
update:null
3237
};
33-
angular.extend(opts, uiSortableConfig);
34-
if (ngModel) {
35-
// When we add or remove elements, we need the sortable to 'refresh'
36-
// so it can find the new/removed elements.
37-
scope.$watch(attrs.ngModel + '.length', function () {
38-
// Timeout to let ng-repeat modify the DOM
39-
$timeout(function () {
40-
element.sortable('refresh');
38+
39+
angular.extend(opts, uiSortableConfig);
40+
41+
if (ngModel) {
42+
43+
// When we add or remove elements, we need the sortable to 'refresh'
44+
// so it can find the new/removed elements.
45+
scope.$watch(attrs.ngModel+'.length', function() {
46+
// Timeout to let ng-repeat modify the DOM
47+
$timeout(function() {
48+
element.sortable('refresh');
49+
});
4150
});
42-
});
43-
callbacks.start = function (e, ui) {
44-
// Save the starting position of dragged item
45-
ui.item.sortable = {
46-
index: ui.item.index(),
47-
cancel: function () {
48-
ui.item.sortable._isCanceled = true;
49-
},
50-
isCanceled: function () {
51-
return ui.item.sortable._isCanceled;
52-
},
53-
_isCanceled: false
51+
52+
callbacks.start = function(e, ui) {
53+
// Save the starting position of dragged item
54+
ui.item.sortable = {
55+
index: ui.item.index(),
56+
cancel: function () {
57+
ui.item.sortable._isCanceled = true;
58+
},
59+
isCanceled: function () {
60+
return ui.item.sortable._isCanceled;
61+
},
62+
_isCanceled: false
63+
};
5464
};
55-
};
56-
callbacks.activate = function () {
57-
// We need to make a copy of the current element's contents so
58-
// we can restore it after sortable has messed it up.
59-
// This is inside activate (instead of start) in order to save
60-
// both lists when dragging between connected lists.
61-
savedNodes = element.contents();
62-
// If this list has a placeholder (the connected lists won't),
63-
// don't inlcude it in saved nodes.
64-
var placeholder = element.sortable('option', 'placeholder');
65-
// placeholder.element will be a function if the placeholder, has
66-
// been created (placeholder will be an object). If it hasn't
67-
// been created, either placeholder will be false if no
68-
// placeholder class was given or placeholder.element will be
69-
// undefined if a class was given (placeholder will be a string)
70-
if (placeholder && placeholder.element && typeof placeholder.element === 'function') {
71-
var phElement = placeholder.element();
72-
// workaround for jquery ui 1.9.x,
73-
// not returning jquery collection
74-
if (!phElement.jquery) {
75-
phElement = angular.element(phElement);
65+
66+
callbacks.activate = function(/*e, ui*/) {
67+
// We need to make a copy of the current element's contents so
68+
// we can restore it after sortable has messed it up.
69+
// This is inside activate (instead of start) in order to save
70+
// both lists when dragging between connected lists.
71+
savedNodes = element.contents();
72+
73+
// If this list has a placeholder (the connected lists won't),
74+
// don't inlcude it in saved nodes.
75+
var placeholder = element.sortable('option','placeholder');
76+
77+
// placeholder.element will be a function if the placeholder, has
78+
// been created (placeholder will be an object). If it hasn't
79+
// been created, either placeholder will be false if no
80+
// placeholder class was given or placeholder.element will be
81+
// undefined if a class was given (placeholder will be a string)
82+
if (placeholder && placeholder.element && typeof placeholder.element === 'function') {
83+
var phElement = placeholder.element();
84+
// workaround for jquery ui 1.9.x,
85+
// not returning jquery collection
86+
if (!phElement.jquery) {
87+
phElement = angular.element(phElement);
88+
}
89+
90+
// exact match with the placeholder's class attribute to handle
91+
// the case that multiple connected sortables exist and
92+
// the placehoilder option equals the class of sortable items
93+
var excludes = element.find('[class="' + phElement.attr('class') + '"]');
94+
95+
savedNodes = savedNodes.not(excludes);
7696
}
77-
// exact match with the placeholder's class attribute to handle
78-
// the case that multiple connected sortables exist and
79-
// the placehoilder option equals the class of sortable items
80-
var excludes = element.find('[class="' + phElement.attr('class') + '"]');
81-
savedNodes = savedNodes.not(excludes);
82-
}
83-
};
84-
callbacks.update = function (e, ui) {
85-
// Save current drop position but only if this is not a second
86-
// update that happens when moving between lists because then
87-
// the value will be overwritten with the old value
88-
if (!ui.item.sortable.received) {
89-
ui.item.sortable.dropindex = ui.item.index();
90-
ui.item.sortable.droptarget = ui.item.parent();
91-
// Cancel the sort (let ng-repeat do the sort for us)
92-
// Don't cancel if this is the received list because it has
93-
// already been canceled in the other list, and trying to cancel
94-
// here will mess up the DOM.
95-
element.sortable('cancel');
96-
}
97-
// Put the nodes back exactly the way they started (this is very
98-
// important because ng-repeat uses comment elements to delineate
99-
// the start and stop of repeat sections and sortable doesn't
100-
// respect their order (even if we cancel, the order of the
101-
// comments are still messed up).
102-
if (element.sortable('option', 'helper') === 'clone') {
103-
// restore all the savedNodes except .ui-sortable-helper element
104-
// (which is placed last). That way it will be garbage collected.
105-
savedNodes = savedNodes.not(savedNodes.last());
106-
}
107-
savedNodes.appendTo(element);
108-
// If received is true (an item was dropped in from another list)
109-
// then we add the new item to this list otherwise wait until the
110-
// stop event where we will know if it was a sort or item was
111-
// moved here from another list
112-
if (ui.item.sortable.received && !ui.item.sortable.isCanceled()) {
113-
scope.$apply(function () {
114-
ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0, ui.item.sortable.moved);
115-
});
116-
}
117-
};
118-
callbacks.stop = function (e, ui) {
119-
// If the received flag hasn't be set on the item, this is a
120-
// normal sort, if dropindex is set, the item was moved, so move
121-
// the items in the list.
122-
if (!ui.item.sortable.received && 'dropindex' in ui.item.sortable && !ui.item.sortable.isCanceled()) {
123-
scope.$apply(function () {
124-
ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0, ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]);
125-
});
126-
} else {
127-
// if the item was not moved, then restore the elements
128-
// so that the ngRepeat's comment are correct.
129-
if ((!('dropindex' in ui.item.sortable) || ui.item.sortable.isCanceled()) && element.sortable('option', 'helper') !== 'clone') {
130-
savedNodes.appendTo(element);
97+
};
98+
99+
callbacks.update = function(e, ui) {
100+
// Save current drop position but only if this is not a second
101+
// update that happens when moving between lists because then
102+
// the value will be overwritten with the old value
103+
if(!ui.item.sortable.received) {
104+
ui.item.sortable.dropindex = ui.item.index();
105+
ui.item.sortable.droptarget = ui.item.parent();
106+
107+
// Cancel the sort (let ng-repeat do the sort for us)
108+
// Don't cancel if this is the received list because it has
109+
// already been canceled in the other list, and trying to cancel
110+
// here will mess up the DOM.
111+
element.sortable('cancel');
131112
}
132-
}
133-
};
134-
callbacks.receive = function (e, ui) {
135-
// An item was dropped here from another list, set a flag on the
136-
// item.
137-
ui.item.sortable.received = true;
138-
};
139-
callbacks.remove = function (e, ui) {
140-
// Remove the item from this list's model and copy data into item,
141-
// so the next list can retrive it
142-
if (!ui.item.sortable.isCanceled()) {
143-
scope.$apply(function () {
144-
ui.item.sortable.moved = ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0];
145-
});
146-
}
147-
};
148-
scope.$watch(attrs.uiSortable, function (newVal) {
149-
angular.forEach(newVal, function (value, key) {
150-
if (callbacks[key]) {
151-
if (key === 'stop') {
152-
// call apply after stop
153-
value = combineCallbacks(value, function () {
154-
scope.$apply();
155-
});
113+
114+
// Put the nodes back exactly the way they started (this is very
115+
// important because ng-repeat uses comment elements to delineate
116+
// the start and stop of repeat sections and sortable doesn't
117+
// respect their order (even if we cancel, the order of the
118+
// comments are still messed up).
119+
if (element.sortable('option','helper') === 'clone') {
120+
// restore all the savedNodes except .ui-sortable-helper element
121+
// (which is placed last). That way it will be garbage collected.
122+
savedNodes = savedNodes.not(savedNodes.last());
123+
}
124+
savedNodes.appendTo(element);
125+
126+
// If received is true (an item was dropped in from another list)
127+
// then we add the new item to this list otherwise wait until the
128+
// stop event where we will know if it was a sort or item was
129+
// moved here from another list
130+
if(ui.item.sortable.received && !ui.item.sortable.isCanceled()) {
131+
scope.$apply(function () {
132+
ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0,
133+
ui.item.sortable.moved);
134+
});
135+
}
136+
};
137+
138+
callbacks.stop = function(e, ui) {
139+
// If the received flag hasn't be set on the item, this is a
140+
// normal sort, if dropindex is set, the item was moved, so move
141+
// the items in the list.
142+
if(!ui.item.sortable.received &&
143+
('dropindex' in ui.item.sortable) &&
144+
!ui.item.sortable.isCanceled()) {
145+
146+
scope.$apply(function () {
147+
ngModel.$modelValue.splice(
148+
ui.item.sortable.dropindex, 0,
149+
ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]);
150+
});
151+
} else {
152+
// if the item was not moved, then restore the elements
153+
// so that the ngRepeat's comment are correct.
154+
if((!('dropindex' in ui.item.sortable) || ui.item.sortable.isCanceled()) && element.sortable('option','helper') !== 'clone') {
155+
savedNodes.appendTo(element);
156156
}
157-
// wrap the callback
158-
value = combineCallbacks(callbacks[key], value);
159157
}
160-
element.sortable('option', key, value);
158+
};
159+
160+
callbacks.receive = function(e, ui) {
161+
// An item was dropped here from another list, set a flag on the
162+
// item.
163+
ui.item.sortable.received = true;
164+
};
165+
166+
callbacks.remove = function(e, ui) {
167+
// Remove the item from this list's model and copy data into item,
168+
// so the next list can retrive it
169+
if (!ui.item.sortable.isCanceled()) {
170+
scope.$apply(function () {
171+
ui.item.sortable.moved = ngModel.$modelValue.splice(
172+
ui.item.sortable.index, 1)[0];
173+
});
174+
}
175+
};
176+
177+
scope.$watch(attrs.uiSortable, function(newVal /*, oldVal*/) {
178+
angular.forEach(newVal, function(value, key) {
179+
if(callbacks[key]) {
180+
if( key === 'stop' ){
181+
// call apply after stop
182+
value = combineCallbacks(
183+
value, function() { scope.$apply(); });
184+
}
185+
// wrap the callback
186+
value = combineCallbacks(callbacks[key], value);
187+
}
188+
element.sortable('option', key, value);
189+
});
190+
}, true);
191+
192+
angular.forEach(callbacks, function(value, key) {
193+
opts[key] = combineCallbacks(value, opts[key]);
161194
});
162-
}, true);
163-
angular.forEach(callbacks, function (value, key) {
164-
opts[key] = combineCallbacks(value, opts[key]);
165-
});
166-
} else {
167-
$log.info('ui.sortable: ngModel not provided!', element);
195+
196+
} else {
197+
$log.info('ui.sortable: ngModel not provided!', element);
198+
}
199+
200+
// Create sortable
201+
element.sortable(opts);
168202
}
169-
// Create sortable
170-
element.sortable(opts);
171-
}
172-
};
173-
}
174-
]);
203+
};
204+
}
205+
]);
206+
207+
})(window, window.angular);

0 commit comments

Comments
 (0)