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

Commit 97c8ad3

Browse files
committed
feat(sortable): restore deleted options to default value
Resolves #345 refactor: abstract the options patching mechanism Resolves #348 refactor: move the ng-repeat selector to uiSortableConfig
1 parent ed7b69f commit 97c8ad3

File tree

1 file changed

+108
-50
lines changed

1 file changed

+108
-50
lines changed

src/sortable.js

Lines changed: 108 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
@param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config
55
*/
66
angular.module('ui.sortable', [])
7-
.value('uiSortableConfig',{})
7+
.value('uiSortableConfig',{
8+
// the default for jquery-ui sortable is "> *", we need to restrict this to
9+
// ng-repeat items
10+
// if the user uses
11+
items: '> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]'
12+
})
813
.directive('uiSortable', [
914
'uiSortableConfig', '$timeout', '$log',
1015
function(uiSortableConfig, $timeout, $log) {
@@ -17,12 +22,16 @@ angular.module('ui.sortable', [])
1722
link: function(scope, element, attrs, ngModel) {
1823
var savedNodes;
1924

20-
function combineCallbacks(first,second){
21-
if(second && (typeof second === 'function')) {
25+
function combineCallbacks(first, second){
26+
var firstIsFunc = first && (typeof first === 'function');
27+
var secondIsFunc = second && (typeof second === 'function');
28+
if(firstIsFunc && secondIsFunc) {
2229
return function() {
2330
first.apply(this, arguments);
2431
second.apply(this, arguments);
2532
};
33+
} else if (secondIsFunc) {
34+
return second;
2635
}
2736
return first;
2837
}
@@ -37,6 +46,93 @@ angular.module('ui.sortable', [])
3746
return null;
3847
}
3948

49+
function patchSortableOption(key, value) {
50+
if (callbacks[key]) {
51+
if( key === 'stop' ){
52+
// call apply after stop
53+
value = combineCallbacks(
54+
value, function() { scope.$apply(); });
55+
56+
value = combineCallbacks(value, afterStop);
57+
}
58+
// wrap the callback
59+
value = combineCallbacks(callbacks[key], value);
60+
} else if (wrappers[key]) {
61+
value = wrappers[key](value);
62+
}
63+
64+
if (key === 'items' && !value) {
65+
value = uiSortableConfig.items;
66+
}
67+
68+
return value;
69+
}
70+
71+
function patchUISortableOptions(newVal, oldVal, sortableWidgetInstance) {
72+
function addDummyOptionKey(value, key) {
73+
if (!(key in opts)) {
74+
// add the key in the opts object so that
75+
// the patch function detects and handles it
76+
opts[key] = null;
77+
}
78+
}
79+
// for this directive to work we have to attach some callbacks
80+
angular.forEach(callbacks, addDummyOptionKey);
81+
82+
// only initialize it in case we have to
83+
// update some options of the sortable
84+
var optsDiff = null;
85+
86+
if (oldVal) {
87+
// reset deleted options to default
88+
var defaultOptions;
89+
angular.forEach(oldVal, function(oldValue, key) {
90+
if (!newVal || !(key in newVal)) {
91+
if (key in directiveOpts) {
92+
opts[key] = 'auto';
93+
return;
94+
}
95+
96+
if (!defaultOptions) {
97+
defaultOptions = angular.element.ui.sortable().options;
98+
}
99+
var defaultValue = defaultOptions[key];
100+
defaultValue = patchSortableOption(key, defaultValue);
101+
102+
if (!optsDiff) {
103+
optsDiff = {};
104+
}
105+
optsDiff[key] = defaultValue;
106+
opts[key] = defaultValue;
107+
}
108+
});
109+
}
110+
111+
// update changed options
112+
angular.forEach(newVal, function(value, key) {
113+
// if it's a custom option of the directive,
114+
// handle it approprietly
115+
if (key in directiveOpts) {
116+
if (key === 'ui-floating' && (value === false || value === true) && sortableWidgetInstance) {
117+
sortableWidgetInstance.floating = value;
118+
}
119+
120+
opts[key] = value;
121+
return;
122+
}
123+
124+
value = patchSortableOption(key, value);
125+
126+
if (!optsDiff) {
127+
optsDiff = {};
128+
}
129+
optsDiff[key] = value;
130+
opts[key] = value;
131+
});
132+
133+
return optsDiff;
134+
}
135+
40136
function getPlaceholderElement (element) {
41137
var placeholder = element.sortable('option','placeholder');
42138

@@ -104,16 +200,11 @@ angular.module('ui.sortable', [])
104200
// we can't just do ui.item.index() because there it might have siblings
105201
// which are not items
106202
function getItemIndex(ui) {
107-
return ui.item.parent().find('> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]')
203+
return ui.item.parent().find(uiSortableConfig.items)
108204
.index(ui.item);
109205
}
110206

111-
var opts = {
112-
// the default for jquery-ui sortable is "> *", we need to restrict this to
113-
// ng-repeat items
114-
// if the user uses
115-
items: '> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]'
116-
};
207+
var opts = {};
117208

118209
// directive specific options
119210
var directiveOpts = {
@@ -338,53 +429,20 @@ angular.module('ui.sortable', [])
338429
return inner;
339430
};
340431

341-
scope.$watchCollection('uiSortable', function(newVal /*, oldVal*/) {
432+
scope.$watchCollection('uiSortable', function(newVal, oldVal) {
342433
// ensure that the jquery-ui-sortable widget instance
343434
// is still bound to the directive's element
344435
var sortableWidgetInstance = getSortableWidgetInstance(element);
345436
if (!!sortableWidgetInstance) {
346-
angular.forEach(newVal, function(value, key) {
347-
// if it's a custom option of the directive,
348-
// handle it approprietly
349-
if (key in directiveOpts) {
350-
if (key === 'ui-floating' && (value === false || value === true)) {
351-
sortableWidgetInstance.floating = value;
352-
}
353-
354-
opts[key] = value;
355-
return;
356-
}
357-
358-
if (callbacks[key]) {
359-
if( key === 'stop' ){
360-
// call apply after stop
361-
value = combineCallbacks(
362-
value, function() { scope.$apply(); });
363-
364-
value = combineCallbacks(value, afterStop);
365-
}
366-
// wrap the callback
367-
value = combineCallbacks(callbacks[key], value);
368-
} else if (wrappers[key]) {
369-
value = wrappers[key](value);
370-
}
371-
372-
if (key === 'items' && !value) {
373-
value = '> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]';
374-
}
375-
376-
opts[key] = value;
377-
element.sortable('option', key, value);
378-
});
437+
var optsDiff = patchUISortableOptions(newVal, oldVal, sortableWidgetInstance);
438+
439+
if (optsDiff) {
440+
element.sortable('option', optsDiff);
441+
}
379442
}
380443
}, true);
381444

382-
angular.forEach(callbacks, function(value, key) {
383-
opts[key] = combineCallbacks(value, opts[key]);
384-
if( key === 'stop' ){
385-
opts[key] = combineCallbacks(opts[key], afterStop);
386-
}
387-
});
445+
patchUISortableOptions(opts);
388446

389447
} else {
390448
$log.info('ui.sortable: ngModel not provided!', element);

0 commit comments

Comments
 (0)