@@ -83,6 +83,7 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
8383 this . _mouseMove = this . _mouseMove . bind ( this ) ;
8484 this . _mouseUp = this . _mouseUp . bind ( this ) ;
8585 this . _keyEvent = this . _keyEvent . bind ( this ) ;
86+ this . _sortByRow = this . _sortByRow . bind ( this ) ;
8687 this . enable ( ) ;
8788 }
8889
@@ -176,6 +177,57 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
176177 return this . _node ( ) . grid
177178 }
178179
180+ _itemNode ( item ) {
181+ return item [ 'gridstackNode' ]
182+ }
183+
184+ _nodePosition ( node ) {
185+ return {
186+ width : node . w - 1 ,
187+ height : node . h ,
188+ column : node . x ,
189+ row : node . y
190+ }
191+ }
192+
193+ _items ( ) {
194+ return document . querySelectorAll ( '.grid-stack-item:not(.grid-stack-placeholder)' )
195+ }
196+
197+ _sortByRow ( a , b ) {
198+ return this . _itemNode ( a ) . y - this . _itemNode ( b ) . y
199+ }
200+
201+ // Find the first item above the selectedNode.
202+ // Add the items row and its height, this should be the same as the selectedNodes row, if so, the item is in the row directly
203+ // above the selectedNode.
204+ // Also check if the item column overlaps the selectedNodes columns and include the items width in this calculation
205+ _findItemAbove ( ) {
206+ const selectedNode = this . _nodePosition ( this . _node ( ) )
207+
208+ return Array . from ( this . _items ( ) ) . filter ( item => {
209+ const itemNode = this . _nodePosition ( this . _itemNode ( item ) )
210+
211+ if ( ( itemNode . row + itemNode . height ) !== selectedNode . row ) { return false }
212+ if ( selectedNode . column < itemNode . column ) { return false }
213+ if ( selectedNode . column > ( itemNode . column + itemNode . width ) ) { return false }
214+ return item
215+ } ) [ 0 ]
216+ }
217+
218+ // When we have not found any items in the row directly above the selectedNode.
219+ // Look for the first item it can find above the selectedNodes row.
220+ _findFirstItemAbove ( ) {
221+ const selectedNode = this . _nodePosition ( this . _node ( ) )
222+
223+ return Array . from ( this . _items ( ) ) . filter ( item => {
224+ if ( item === this . el ) { return false }
225+ const itemNode = this . _nodePosition ( this . _itemNode ( item ) )
226+
227+ if ( itemNode . row < selectedNode . row ) { return item }
228+ } ) . sort ( this . _sortByRow ) . reverse ( ) [ 0 ]
229+ }
230+
179231 protected _elNewCoordinates ( event : KeyboardEvent , element : HTMLElement ) {
180232 const selectedNode = this . _node ( ) ;
181233 const cellHeight = this . _grid ( ) . getCellHeight ( ) * selectedNode . h
@@ -197,7 +249,10 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
197249 case 'ArrowUp' :
198250 if ( selectedNode . y === 0 ) { break }
199251
200- yCoord = - cellHeight
252+ let itemAbove = this . _findItemAbove ( )
253+ if ( itemAbove === undefined ) { itemAbove = this . _findFirstItemAbove ( ) }
254+
255+ yCoord = - ( this . _itemNode ( itemAbove ) . h * this . _grid ( ) . getCellHeight ( ) )
201256 break
202257 case 'ArrowDown' :
203258 yCoord = cellHeight
0 commit comments