@@ -24,6 +24,7 @@ import {CdkDrag} from './drag';
2424import { CdkDragExit , CdkDragEnter , CdkDragDrop } from './drag-events' ;
2525import { CDK_DROP_CONTAINER } from './drop-container' ;
2626import { DragDropRegistry } from './drag-drop-registry' ;
27+ import { moveItemInArray } from './drag-utils' ;
2728
2829/** Counter used to generate unique ids for drop zones. */
2930let _uniqueIdCounter = 0 ;
@@ -214,45 +215,59 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
214215 */
215216 _sortItem ( item : CdkDrag , xOffset : number , yOffset : number ) : void {
216217 const siblings = this . _positionCache . items ;
217- const isHorizontal = this . orientation === 'horizontal' ;
218218 const newIndex = this . _getItemIndexFromPointerPosition ( item , xOffset , yOffset ) ;
219- const placeholder = item . getPlaceholderElement ( ) ;
220219
221220 if ( newIndex === - 1 && siblings . length > 0 ) {
222221 return ;
223222 }
224223
224+ const isHorizontal = this . orientation === 'horizontal' ;
225225 const currentIndex = siblings . findIndex ( currentItem => currentItem . drag === item ) ;
226- const currentPosition = siblings [ currentIndex ] ;
227- const newPosition = siblings [ newIndex ] ;
228-
229- // Figure out the offset necessary for the items to be swapped.
230- const offset = isHorizontal ?
231- currentPosition . clientRect . left - newPosition . clientRect . left :
232- currentPosition . clientRect . top - newPosition . clientRect . top ;
233- const topAdjustment = isHorizontal ? 0 : offset ;
234- const leftAdjustment = isHorizontal ? offset : 0 ;
235-
236- // Since we've moved the items with a `transform`, we need to adjust their cached
237- // client rects to reflect their new position, as well as swap their positions in the cache.
238- // Note that we shouldn't use `getBoundingClientRect` here to update the cache, because the
239- // elements may be mid-animation which will give us a wrong result.
240- this . _adjustClientRect ( currentPosition . clientRect , - topAdjustment , - leftAdjustment ) ;
241- currentPosition . offset -= offset ;
242- siblings [ currentIndex ] = newPosition ;
243-
244- this . _adjustClientRect ( newPosition . clientRect , topAdjustment , leftAdjustment ) ;
245- newPosition . offset += offset ;
246- siblings [ newIndex ] = currentPosition ;
247-
248- // Swap the placeholder's position with the one of the target draggable.
249- placeholder . style . transform = isHorizontal ?
250- `translate3d(${ currentPosition . offset } px, 0, 0)` :
251- `translate3d(0, ${ currentPosition . offset } px, 0)` ;
252-
253- newPosition . drag . element . nativeElement . style . transform = isHorizontal ?
254- `translate3d(${ newPosition . offset } px, 0, 0)` :
255- `translate3d(0, ${ newPosition . offset } px, 0)` ;
226+ const currentPosition = siblings [ currentIndex ] . clientRect ;
227+ const newPosition = siblings [ newIndex ] . clientRect ;
228+ const delta = currentIndex > newIndex ? 1 : - 1 ;
229+
230+ // How many pixels the item's placeholder should be offset.
231+ const itemOffset = isHorizontal ? newPosition . left - currentPosition . left :
232+ newPosition . top - currentPosition . top ;
233+
234+ // How many pixels all the other items should be offset.
235+ const siblingOffset = isHorizontal ? currentPosition . width * delta :
236+ currentPosition . height * delta ;
237+
238+ // Save the previous order of the items before moving the item to its new index.
239+ // We use this to check whether an item has been moved as a result of the sorting.
240+ const oldOrder = siblings . slice ( ) ;
241+
242+ // Shuffle the array in place.
243+ moveItemInArray ( siblings , currentIndex , newIndex ) ;
244+
245+ siblings . forEach ( ( sibling , index ) => {
246+ // Don't do anything if the position hasn't changed.
247+ if ( oldOrder [ index ] === sibling ) {
248+ return ;
249+ }
250+
251+ const isDraggedItem = sibling . drag === item ;
252+ const offset = isDraggedItem ? itemOffset : siblingOffset ;
253+ const elementToOffset = isDraggedItem ? item . getPlaceholderElement ( ) :
254+ sibling . drag . element . nativeElement ;
255+
256+ // Update the offset to reflect the new position.
257+ sibling . offset += offset ;
258+
259+ // Since we're moving the items with a `transform`, we need to adjust their cached
260+ // client rects to reflect their new position, as well as swap their positions in the cache.
261+ // Note that we shouldn't use `getBoundingClientRect` here to update the cache, because the
262+ // elements may be mid-animation which will give us a wrong result.
263+ if ( isHorizontal ) {
264+ elementToOffset . style . transform = `translate3d(${ sibling . offset } px, 0, 0)` ;
265+ this . _adjustClientRect ( sibling . clientRect , 0 , offset ) ;
266+ } else {
267+ elementToOffset . style . transform = `translate3d(0, ${ sibling . offset } px, 0)` ;
268+ this . _adjustClientRect ( sibling . clientRect , offset , 0 ) ;
269+ }
270+ } ) ;
256271 }
257272
258273 /**
@@ -321,8 +336,8 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
321336 /**
322337 * Updates the top/left positions of a `ClientRect`, as well as their bottom/right counterparts.
323338 * @param clientRect `ClientRect` that should be updated.
324- * @param top New value for the `top` position.
325- * @param left New value for the `left` position.
339+ * @param top Amount to add to the `top` position.
340+ * @param left Amount to add to the `left` position.
326341 */
327342 private _adjustClientRect ( clientRect : ClientRect , top : number , left : number ) {
328343 clientRect . top += top ;
0 commit comments