@@ -228,9 +228,74 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
228228 } ) . sort ( this . _sortByRow ) . reverse ( ) [ 0 ]
229229 }
230230
231+ // Find the first item below the selectedNode.
232+ // Add the selectedNodes row and its height, this should be the same as the items row, if so, the item is in the row directly
233+ // below the selectedNode.
234+ // Also check if the item column overlaps the selectedNodes columns and include the items width in this calculation
235+ _findItemBelow ( ) {
236+ const selectedNode = this . _nodePosition ( this . _node ( ) )
237+
238+ return Array . from ( this . _items ( ) ) . filter ( item => {
239+ const itemNode = this . _nodePosition ( this . _itemNode ( item ) )
240+ const row = selectedNode . height + selectedNode . row
241+
242+ if ( itemNode . row !== row ) { return false }
243+ if ( selectedNode . column < itemNode . column ) { return false }
244+ if ( selectedNode . column > ( itemNode . column + itemNode . width ) ) { return false }
245+ return item
246+ } ) [ 0 ]
247+ }
248+
249+ // When we have not found any items in the row directly below the selectedNode.
250+ // Look for the first item it can find below the selectedNodes row.
251+ _findFirstItemBelow ( ) {
252+ const selectedNode = this . _nodePosition ( this . _node ( ) )
253+
254+ return Array . from ( this . _items ( ) ) . filter ( item => {
255+ const itemNode = this . _nodePosition ( this . _itemNode ( item ) )
256+
257+ if ( item === this . el ) { return false }
258+ if ( selectedNode . column < itemNode . column ) { return false }
259+ if ( selectedNode . column > ( itemNode . column + itemNode . width ) ) { return false }
260+ if ( itemNode . row <= selectedNode . row ) { return false }
261+
262+ return item
263+ } ) . sort ( this . _sortByRow ) [ 0 ]
264+ }
265+
266+ // When the selected item spans more than one column and the position directly below are all empty.
267+ // When this happens we want to look for the first item in the row below which overlap the selected item on the columns.
268+ _findFirstRowBelow ( ) {
269+ const selectedNode = this . _nodePosition ( this . _node ( ) )
270+
271+ return Array . from ( this . _items ( ) ) . filter ( item => {
272+ if ( item === this . el ) { return false }
273+ const itemNode = this . _nodePosition ( this . _itemNode ( item ) )
274+
275+ if ( itemNode . row < ( selectedNode . row + selectedNode . height ) ) { return false }
276+ return item
277+ } ) . sort ( this . _sortByRow ) [ 0 ]
278+ }
279+
280+ // Check if the selectedNode has any siblings to the left or right
281+ _findSiblings ( itemBelow : Element ) {
282+ const itemBelowNode = this . _nodePosition ( this . _itemNode ( itemBelow ) )
283+ const selectedNode = this . _nodePosition ( this . _node ( ) )
284+
285+ return Array . from ( this . _items ( ) ) . filter ( item => {
286+ const itemNode = this . _nodePosition ( this . _itemNode ( item ) )
287+
288+ if ( item === this . el ) { return false }
289+ if ( itemNode . row !== selectedNode . row ) { return false }
290+
291+ if ( itemNode . column < itemBelowNode . column ) { return false }
292+ if ( itemNode . column > ( itemBelowNode . column + itemBelowNode . width ) ) { return false }
293+ return item
294+ } )
295+ }
296+
231297 protected _elNewCoordinates ( event : KeyboardEvent , element : HTMLElement ) {
232298 const selectedNode = this . _node ( ) ;
233- const cellHeight = this . _grid ( ) . getCellHeight ( ) * selectedNode . h
234299 let xCoord : number , yCoord : number
235300
236301 switch ( event . code ) {
@@ -255,8 +320,26 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
255320 yCoord = - ( this . _itemNode ( itemAbove ) . h * this . _grid ( ) . getCellHeight ( ) )
256321 break
257322 case 'ArrowDown' :
258- yCoord = cellHeight
259- break
323+ let itemBelow = this . _findItemBelow ( )
324+
325+ if ( itemBelow === undefined ) { itemBelow = this . _findFirstItemBelow ( ) }
326+ if ( itemBelow === undefined ) { itemBelow = this . _findFirstRowBelow ( ) }
327+
328+ const itemBelowNode = this . _nodePosition ( this . _itemNode ( itemBelow ) )
329+ const siblings = this . _findSiblings ( itemBelow )
330+
331+ if ( siblings . length >= 1 ) {
332+ const rowPosition = ( itemBelowNode . row - selectedNode . y ) * this . _grid ( ) . getCellHeight ( ) ;
333+
334+ yCoord = rowPosition + ( itemBelowNode . height * this . _grid ( ) . getCellHeight ( ) )
335+ } else if ( selectedNode . h < itemBelowNode . height ) {
336+ yCoord = ( itemBelowNode . height * this . _grid ( ) . getCellHeight ( ) )
337+ } else {
338+ const cellHeight = this . _grid ( ) . getCellHeight ( ) * selectedNode . h ;
339+
340+ yCoord = ( cellHeight + this . _grid ( ) . getCellHeight ( ) )
341+ }
342+ break ;
260343 }
261344
262345 return this . _setCoordinates ( element , xCoord , yCoord ) ;
0 commit comments