@@ -83,6 +83,7 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
83
83
this . _mouseMove = this . _mouseMove . bind ( this ) ;
84
84
this . _mouseUp = this . _mouseUp . bind ( this ) ;
85
85
this . _keyEvent = this . _keyEvent . bind ( this ) ;
86
+ this . _sortByRow = this . _sortByRow . bind ( this ) ;
86
87
this . enable ( ) ;
87
88
}
88
89
@@ -176,6 +177,57 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
176
177
return this . _node ( ) . grid
177
178
}
178
179
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
+
179
231
protected _elNewCoordinates ( event : KeyboardEvent , element : HTMLElement ) {
180
232
const selectedNode = this . _node ( ) ;
181
233
const cellHeight = this . _grid ( ) . getCellHeight ( ) * selectedNode . h
@@ -197,7 +249,10 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
197
249
case 'ArrowUp' :
198
250
if ( selectedNode . y === 0 ) { break }
199
251
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 ( ) )
201
256
break
202
257
case 'ArrowDown' :
203
258
yCoord = cellHeight
0 commit comments