Skip to content

Commit

Permalink
Fix dnd to first child (#853)
Browse files Browse the repository at this point in the history
* Fid dnd to first child

* Build

* Changelog

* Test

* Use switch

* Build

* Move generateHitAreas test

* Add test for ghostDropHint
  • Loading branch information
mbraak authored Nov 1, 2024
1 parent c5eea63 commit c272846
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 15 deletions.
4 changes: 4 additions & 0 deletions docs/_entries/general/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ title: Changelog
name: changelog
---

#### Development version

- Issue #853: fix dnd to first child (thanks to Oskar von Dungern)

#### 1.8.6 (october 26 2024)

- Issue #840: using the up and down keys scrolls the page
Expand Down
46 changes: 43 additions & 3 deletions src/nodeElement/ghostDropHint.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
import { DropHint } from "../dragAndDropHandler/types";
import { Node } from "../node";
import { Position } from "../position";

class GhostDropHint implements DropHint {
private element: HTMLElement;
private ghost: HTMLElement;
private node: Node;

constructor(element: HTMLElement) {
constructor(node: Node, element: HTMLElement, position: Position) {
this.element = element;
this.node = node;
this.ghost = this.createGhostElement();

this.element.after(this.ghost);
this.ghost.classList.add("jqtree-inside");
switch (position) {
case Position.After:
this.moveAfter();
break;

case Position.Before:
this.moveBefore();
break;

case Position.Inside: {
if (node.isFolder() && node.is_open) {
this.moveInsideOpenFolder();
} else {
this.moveInside();
}
}
}
}

private createGhostElement() {
Expand All @@ -27,6 +46,27 @@ class GhostDropHint implements DropHint {
return ghost;
}

private moveAfter(): void {
this.element.after(this.ghost);
}

private moveBefore(): void {
this.element.before(this.ghost);
}

private moveInside(): void {
this.element.after(this.ghost);
this.ghost.classList.add("jqtree-inside");
}

private moveInsideOpenFolder(): void {
const childElement = this.node.children[0]?.element;

if (childElement) {
childElement.before(this.ghost);
}
}

public remove(): void {
this.ghost.remove();
}
Expand Down
2 changes: 1 addition & 1 deletion src/nodeElement/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class NodeElement {
if (this.mustShowBorderDropHint(position)) {
return new BorderDropHint(this.element, this.getScrollLeft());
} else {
return new GhostDropHint(this.element);
return new GhostDropHint(this.node, this.element, position);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import {
generateHitAreasForGroup,
generateHitAreasFromPositions,
generateHitPositions,
} from "../dragAndDropHandler/generateHitAreas";
import { HitArea } from "../dragAndDropHandler/types";
import { Node } from "../node";
import { Position } from "../position";
} from "../../dragAndDropHandler/generateHitAreas";
import { HitArea } from "../../dragAndDropHandler/types";
import { Node } from "../../node";
import { Position } from "../../position";

const mockHtmlElement = (y: number) =>
({
Expand Down
65 changes: 65 additions & 0 deletions src/test/nodeElement/ghostDropHint.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Node } from "../../node";
import GhostDropHint from "../../nodeElement/ghostDropHint";
import { Position } from "../../position";

beforeEach(() => {
document.body.innerHTML = "";
});

it("creates a hint element after the node element when the position is After", () => {
const nodeElement = document.createElement("div");
document.body.append(nodeElement);

const node = new Node();
new GhostDropHint(node, nodeElement, Position.After);

expect(nodeElement.nextSibling).toHaveClass("jqtree-ghost");
expect(nodeElement.previousSibling).toBeNull();
expect(nodeElement.children).toBeEmpty();
});

it("creates a hint element after the node element when the position is Before", () => {
const nodeElement = document.createElement("div");
document.body.append(nodeElement);

const node = new Node();
new GhostDropHint(node, nodeElement, Position.Before);

expect(nodeElement.previousSibling).toHaveClass("jqtree-ghost");
expect(nodeElement.nextSibling).toBeNull();
expect(nodeElement.children).toBeEmpty();
});

it("creates a hint element after the node element when the position is Inside and the node is an open folder", () => {
const nodeElement = document.createElement("div");
document.body.append(nodeElement);

const childElement = document.createElement("div");
nodeElement.append(childElement);

const node = new Node({ is_open: true });
const childNode = new Node();
childNode.element = childElement;
node.addChild(childNode);

new GhostDropHint(node, nodeElement, Position.Inside);

expect(nodeElement.previousSibling).toBeNull();
expect(nodeElement.nextSibling).toBeNull();
expect(nodeElement.children.length).toBe(2);
expect(nodeElement.children[0]).toHaveClass("jqtree-ghost");
});

it("creates a hint element after the node element when the position is Inside and the node is a closed folder", () => {
const nodeElement = document.createElement("div");
document.body.append(nodeElement);

const node = new Node();
node.addChild(new Node());

new GhostDropHint(node, nodeElement, Position.Inside);

expect(nodeElement.nextSibling).toHaveClass("jqtree-ghost");
expect(nodeElement.previousSibling).toBeNull();
expect(nodeElement.children).toBeEmpty();
});
39 changes: 35 additions & 4 deletions tree.jquery.debug.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tree.jquery.debug.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tree.jquery.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tree.jquery.js.map

Large diffs are not rendered by default.

0 comments on commit c272846

Please sign in to comment.