Skip to content

Commit 78dfd52

Browse files
Move the item down to the first available position
First look for the next item in the row directly below the selected item. When nothing is find look for the first item below the selected item. And when that fails because of whitespacing, look for the first item which is below and overlaps the selected item. Also check if the selected item has sibling, because when the item below spans more columns, it can mean there is no space for that item. Instead, move the selected item below the next item.
1 parent 0707d1e commit 78dfd52

File tree

1 file changed

+86
-3
lines changed

1 file changed

+86
-3
lines changed

src/dd-draggable.ts

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)