1
1
/**
2
2
* angular-ui-sortable - This directive allows you to jQueryUI Sortable.
3
- * @version v0.14.4 - 2017-04-15
3
+ * @version v0.17.1 - 2017-04-15
4
4
* @link http://angular-ui.github.com
5
5
* @license MIT
6
6
*/
@@ -23,10 +23,25 @@ angular.module('ui.sortable', [])
23
23
'uiSortableConfig' , '$timeout' , '$log' ,
24
24
function ( uiSortableConfig , $timeout , $log ) {
25
25
return {
26
- require : '?ngModel' ,
26
+ require :'?ngModel' ,
27
27
scope : {
28
- ngModel : '=' ,
29
- uiSortable : '='
28
+ ngModel :'=' ,
29
+ uiSortable :'=' ,
30
+ ////Expression bindings from html.
31
+ create :'&uiSortableCreate' ,
32
+ // helper:'&uiSortableHelper',
33
+ start :'&uiSortableStart' ,
34
+ activate :'&uiSortableActivate' ,
35
+ // sort:'&uiSortableSort',
36
+ // change:'&uiSortableChange',
37
+ // over:'&uiSortableOver',
38
+ // out:'&uiSortableOut',
39
+ beforeStop :'&uiSortableBeforeStop' ,
40
+ update :'&uiSortableUpdate' ,
41
+ remove :'&uiSortableRemove' ,
42
+ receive :'&uiSortableReceive' ,
43
+ deactivate :'&uiSortableDeactivate' ,
44
+ stop :'&uiSortableStop'
30
45
} ,
31
46
link : function ( scope , element , attrs , ngModel ) {
32
47
var savedNodes ;
@@ -107,7 +122,7 @@ angular.module('ui.sortable', [])
107
122
}
108
123
return ;
109
124
}
110
-
125
+
111
126
if ( ! defaultOptions ) {
112
127
defaultOptions = angular . element . ui . sortable ( ) . options ;
113
128
}
@@ -195,16 +210,13 @@ angular.module('ui.sortable', [])
195
210
return ( / l e f t | r i g h t / ) . test ( item . css ( 'float' ) ) || ( / i n l i n e | t a b l e - c e l l / ) . test ( item . css ( 'display' ) ) ;
196
211
}
197
212
198
- function getElementScope ( elementScopes , element ) {
199
- var result = null ;
213
+ function getElementContext ( elementScopes , element ) {
200
214
for ( var i = 0 ; i < elementScopes . length ; i ++ ) {
201
- var x = elementScopes [ i ] ;
202
- if ( x . element [ 0 ] === element [ 0 ] ) {
203
- result = x . scope ;
204
- break ;
215
+ var c = elementScopes [ i ] ;
216
+ if ( c . element [ 0 ] === element [ 0 ] ) {
217
+ return c ;
205
218
}
206
219
}
207
- return result ;
208
220
}
209
221
210
222
function afterStop ( e , ui ) {
@@ -229,11 +241,19 @@ angular.module('ui.sortable', [])
229
241
} ;
230
242
231
243
var callbacks = {
232
- receive : null ,
233
- remove : null ,
244
+ create : null ,
234
245
start : null ,
235
- stop : null ,
236
- update : null
246
+ activate : null ,
247
+ // sort: null,
248
+ // change: null,
249
+ // over: null,
250
+ // out: null,
251
+ beforeStop : null ,
252
+ update : null ,
253
+ remove : null ,
254
+ receive : null ,
255
+ deactivate : null ,
256
+ stop : null
237
257
} ;
238
258
239
259
var wrappers = {
@@ -275,7 +295,8 @@ angular.module('ui.sortable', [])
275
295
ui . item . sortable = {
276
296
model : ngModel . $modelValue [ index ] ,
277
297
index : index ,
278
- source : ui . item . parent ( ) ,
298
+ source : element ,
299
+ sourceList : ui . item . parent ( ) ,
279
300
sourceModel : ngModel . $modelValue ,
280
301
cancel : function ( ) {
281
302
ui . item . sortable . _isCanceled = true ;
@@ -292,16 +313,33 @@ angular.module('ui.sortable', [])
292
313
angular . forEach ( ui . item . sortable , function ( value , key ) {
293
314
ui . item . sortable [ key ] = undefined ;
294
315
} ) ;
316
+ } ,
317
+ _connectedSortables : [ ] ,
318
+ _getElementContext : function ( element ) {
319
+ return getElementContext ( this . _connectedSortables , element ) ;
295
320
}
296
321
} ;
297
322
} ;
298
323
299
324
callbacks . activate = function ( e , ui ) {
325
+ var isSourceContext = ui . item . sortable . source === element ;
326
+ var savedNodesOrigin = isSourceContext ?
327
+ ui . item . sortable . sourceList :
328
+ element ;
329
+ var elementContext = {
330
+ element : element ,
331
+ scope : scope ,
332
+ isSourceContext : isSourceContext ,
333
+ savedNodesOrigin : savedNodesOrigin
334
+ } ;
335
+ // save the directive's scope so that it is accessible from ui.item.sortable
336
+ ui . item . sortable . _connectedSortables . push ( elementContext ) ;
337
+
300
338
// We need to make a copy of the current element's contents so
301
339
// we can restore it after sortable has messed it up.
302
340
// This is inside activate (instead of start) in order to save
303
341
// both lists when dragging between connected lists.
304
- savedNodes = element . contents ( ) ;
342
+ savedNodes = savedNodesOrigin . contents ( ) ;
305
343
helper = ui . helper ;
306
344
307
345
// If this list has a placeholder (the connected lists won't),
@@ -311,29 +349,20 @@ angular.module('ui.sortable', [])
311
349
var excludes = getPlaceholderExcludesludes ( element , placeholder ) ;
312
350
savedNodes = savedNodes . not ( excludes ) ;
313
351
}
314
-
315
- // save the directive's scope so that it is accessible from ui.item.sortable
316
- var connectedSortables = ui . item . sortable . _connectedSortables || [ ] ;
317
-
318
- connectedSortables . push ( {
319
- element : element ,
320
- scope : scope
321
- } ) ;
322
-
323
- ui . item . sortable . _connectedSortables = connectedSortables ;
324
352
} ;
325
353
326
354
callbacks . update = function ( e , ui ) {
327
355
// Save current drop position but only if this is not a second
328
356
// update that happens when moving between lists because then
329
357
// the value will be overwritten with the old value
330
- if ( ! ui . item . sortable . received ) {
358
+ if ( ! ui . item . sortable . received ) {
331
359
ui . item . sortable . dropindex = getItemIndex ( ui . item ) ;
332
- var droptarget = ui . item . parent ( ) ;
360
+ var droptarget = ui . item . closest ( '[ui-sortable], [data-ui-sortable], [x-ui-sortable]' ) ;
333
361
ui . item . sortable . droptarget = droptarget ;
362
+ ui . item . sortable . droptargetList = ui . item . parent ( ) ;
334
363
335
- var droptargetScope = getElementScope ( ui . item . sortable . _connectedSortables , droptarget ) ;
336
- ui . item . sortable . droptargetModel = droptargetScope . ngModel ;
364
+ var droptargetContext = ui . item . sortable . _getElementContext ( droptarget ) ;
365
+ ui . item . sortable . droptargetModel = droptargetContext . scope . ngModel ;
337
366
338
367
// Cancel the sort (let ng-repeat do the sort for us)
339
368
// Don't cancel if this is the received list because it has
@@ -353,55 +382,60 @@ angular.module('ui.sortable', [])
353
382
// That way it will be garbage collected.
354
383
savedNodes = savedNodes . not ( sortingHelper ) ;
355
384
}
356
- savedNodes . appendTo ( element ) ;
385
+ var elementContext = ui . item . sortable . _getElementContext ( element ) ;
386
+ savedNodes . appendTo ( elementContext . savedNodesOrigin ) ;
357
387
358
388
// If this is the target connected list then
359
389
// it's safe to clear the restored nodes since:
360
390
// update is currently running and
361
391
// stop is not called for the target list.
362
- if ( ui . item . sortable . received ) {
392
+ if ( ui . item . sortable . received ) {
363
393
savedNodes = null ;
364
394
}
365
395
366
396
// If received is true (an item was dropped in from another list)
367
397
// then we add the new item to this list otherwise wait until the
368
398
// stop event where we will know if it was a sort or item was
369
399
// moved here from another list
370
- if ( ui . item . sortable . received && ! ui . item . sortable . isCanceled ( ) ) {
400
+ if ( ui . item . sortable . received && ! ui . item . sortable . isCanceled ( ) ) {
371
401
scope . $apply ( function ( ) {
372
402
ngModel . $modelValue . splice ( ui . item . sortable . dropindex , 0 ,
373
403
ui . item . sortable . moved ) ;
374
404
} ) ;
405
+ scope . $emit ( 'ui-sortable:moved' , ui ) ;
375
406
}
376
407
} ;
377
408
378
409
callbacks . stop = function ( e , ui ) {
379
410
// If the received flag hasn't be set on the item, this is a
380
411
// normal sort, if dropindex is set, the item was moved, so move
381
412
// the items in the list.
382
- if ( ! ui . item . sortable . received &&
383
- ( 'dropindex' in ui . item . sortable ) &&
384
- ! ui . item . sortable . isCanceled ( ) ) {
413
+ var wasMoved = ( 'dropindex' in ui . item . sortable ) &&
414
+ ! ui . item . sortable . isCanceled ( ) ;
415
+
416
+ if ( wasMoved && ! ui . item . sortable . received ) {
385
417
386
418
scope . $apply ( function ( ) {
387
419
ngModel . $modelValue . splice (
388
420
ui . item . sortable . dropindex , 0 ,
389
421
ngModel . $modelValue . splice ( ui . item . sortable . index , 1 ) [ 0 ] ) ;
390
422
} ) ;
391
- } else {
392
- // if the item was not moved, then restore the elements
423
+ scope . $emit ( 'ui-sortable:moved' , ui ) ;
424
+ } else if ( ! wasMoved &&
425
+ ! angular . equals ( element . contents ( ) . toArray ( ) , savedNodes . toArray ( ) ) ) {
426
+ // if the item was not moved
427
+ // and the DOM element order has changed,
428
+ // then restore the elements
393
429
// so that the ngRepeat's comment are correct.
394
- if ( ( ! ( 'dropindex' in ui . item . sortable ) || ui . item . sortable . isCanceled ( ) ) &&
395
- ! angular . equals ( element . contents ( ) , savedNodes ) ) {
396
-
397
- var sortingHelper = getSortingHelper ( element , ui , savedNodes ) ;
398
- if ( sortingHelper && sortingHelper . length ) {
399
- // Restore all the savedNodes except from the sorting helper element.
400
- // That way it will be garbage collected.
401
- savedNodes = savedNodes . not ( sortingHelper ) ;
402
- }
403
- savedNodes . appendTo ( element ) ;
430
+
431
+ var sortingHelper = getSortingHelper ( element , ui , savedNodes ) ;
432
+ if ( sortingHelper && sortingHelper . length ) {
433
+ // Restore all the savedNodes except from the sorting helper element.
434
+ // That way it will be garbage collected.
435
+ savedNodes = savedNodes . not ( sortingHelper ) ;
404
436
}
437
+ var elementContext = ui . item . sortable . _getElementContext ( element ) ;
438
+ savedNodes . appendTo ( elementContext . savedNodesOrigin ) ;
405
439
}
406
440
407
441
// It's now safe to clear the savedNodes and helper
@@ -435,6 +469,21 @@ angular.module('ui.sortable', [])
435
469
}
436
470
} ;
437
471
472
+ // setup attribute handlers
473
+ angular . forEach ( callbacks , function ( value , key ) {
474
+ callbacks [ key ] = combineCallbacks ( callbacks [ key ] ,
475
+ function ( ) {
476
+ var attrHandler = scope [ key ] ;
477
+ var attrHandlerFn ;
478
+ if ( typeof attrHandler === 'function' &&
479
+ ( 'uiSortable' + key . substring ( 0 , 1 ) . toUpperCase ( ) + key . substring ( 1 ) ) . length &&
480
+ typeof ( attrHandlerFn = attrHandler ( ) ) === 'function' ) {
481
+ attrHandlerFn . apply ( this , arguments ) ;
482
+ }
483
+ } ) ;
484
+ } ) ;
485
+
486
+
438
487
wrappers . helper = function ( inner ) {
439
488
if ( inner && typeof inner === 'function' ) {
440
489
return function ( e , item ) {
@@ -443,7 +492,8 @@ angular.module('ui.sortable', [])
443
492
item . sortable = {
444
493
model : ngModel . $modelValue [ index ] ,
445
494
index : index ,
446
- source : item . parent ( ) ,
495
+ source : element ,
496
+ sourceList : item . parent ( ) ,
447
497
sourceModel : ngModel . $modelValue ,
448
498
_restore : function ( ) {
449
499
angular . forEach ( item . sortable , function ( value , key ) {
@@ -469,7 +519,7 @@ angular.module('ui.sortable', [])
469
519
var sortableWidgetInstance = getSortableWidgetInstance ( element ) ;
470
520
if ( ! ! sortableWidgetInstance ) {
471
521
var optsDiff = patchUISortableOptions ( newVal , oldVal , sortableWidgetInstance ) ;
472
-
522
+
473
523
if ( optsDiff ) {
474
524
element . sortable ( 'option' , optsDiff ) ;
475
525
}
@@ -485,7 +535,7 @@ angular.module('ui.sortable', [])
485
535
} else {
486
536
$log . info ( 'ui.sortable: ngModel not provided!' , element ) ;
487
537
}
488
-
538
+
489
539
// Create sortable
490
540
element . sortable ( opts ) ;
491
541
}
0 commit comments