44 @param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config
55 */
66angular . 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