Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions packages/base/src/util/dragAndDrop/GlobalDragDropManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type UI5Element from "../../UI5Element.js";
import DragRegistry from "./DragRegistry.js";

let globalHandlersAttached = false;
const subscribers = new Set<UI5Element>();

const ondragstart = (e: DragEvent) => {
if (!e.dataTransfer) {
return;
}

const draggedElement = e.composedPath().find(el => (el as any).movable) as HTMLElement;

if (!subscribers.has(draggedElement.parentElement as UI5Element)) {
return;
}

DragRegistry.setDraggedElement(draggedElement);
};

const ondragend = () => {
DragRegistry.clearDraggedElement();
};

const attachGlobalHandlers = () => {
if (globalHandlersAttached) {
return;
}

document.body.addEventListener("dragstart", ondragstart);
document.body.addEventListener("dragend", ondragend);
globalHandlersAttached = true;
};

const detachGlobalHandlers = () => {
document.body.removeEventListener("dragstart", ondragstart);
document.body.removeEventListener("dragend", ondragend);
globalHandlersAttached = false;
};

const subscribe = (subscriber: UI5Element) => {
subscribers.add(subscriber);

if (!globalHandlersAttached) {
attachGlobalHandlers();
}
};

const unsubscribe = (subscriber: UI5Element) => {
subscribers.delete(subscriber);

if (subscribers.size === 0 && globalHandlersAttached) {
detachGlobalHandlers();
}
};

const GlobalDragDropManager = {
subscribe,
unsubscribe,
};

export default GlobalDragDropManager;
5 changes: 4 additions & 1 deletion packages/main/src/Table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import TableStyles from "./generated/themes/Table.css.js";
import TableExtension from "./TableExtension.js";
import TableNavigation from "./TableNavigation.js";
import TableOverflowMode from "./types/TableOverflowMode.js";
import GlobalDragDropManager from "@ui5/webcomponents-base/dist/util/dragAndDrop/GlobalDragDropManager.js";
import TableDragAndDrop from "./TableDragAndDrop.js";
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import {
Expand Down Expand Up @@ -404,7 +405,7 @@ class Table extends UI5Element {
@i18n("@ui5/webcomponents")
static i18nBundle: I18nBundle;

_events = ["keydown", "keyup", "click", "focusin", "focusout", "dragstart", "dragenter", "dragleave", "dragover", "drop", "dragend"];
_events = ["keydown", "keyup", "click", "focusin", "focusout", "dragenter", "dragleave", "dragover", "drop"];
_onEventBound: (e: Event) => void;
_onResizeBound: ResizeObserverCallback;
_tableNavigation?: TableNavigation;
Expand All @@ -423,12 +424,14 @@ class Table extends UI5Element {
this.features.forEach(feature => feature.onTableActivate?.(this));
this._tableNavigation = new TableNavigation(this);
this._tableDragAndDrop = new TableDragAndDrop(this);
GlobalDragDropManager.subscribe(this);
}

onExitDOM() {
this._tableNavigation = undefined;
this._tableDragAndDrop = undefined;
this._events.forEach(eventType => this.removeEventListener(eventType, this._onEventBound));
GlobalDragDropManager.unsubscribe(this);
}

onBeforeRendering(): void {
Expand Down
9 changes: 0 additions & 9 deletions packages/main/src/TableDragAndDrop.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import DragRegistry from "@ui5/webcomponents-base/dist/util/dragAndDrop/DragRegistry.js";
import { findClosestPosition } from "@ui5/webcomponents-base/dist/util/dragAndDrop/findClosestPosition.js";
import Orientation from "@ui5/webcomponents-base/dist/types/Orientation.js";
import handleDragOver from "@ui5/webcomponents-base/dist/util/dragAndDrop/handleDragOver.js";
Expand All @@ -14,14 +13,6 @@ export default class TableDragAndDrop extends TableExtension {
this._table = table;
}

_ondragstart(e: DragEvent) {
DragRegistry.setDraggedElement(e.target as HTMLElement);
}

_ondragend() {
DragRegistry.clearDraggedElement();
}

_ondragenter(e: DragEvent) {
e.preventDefault();
}
Expand Down
6 changes: 3 additions & 3 deletions packages/main/test/pages/ListDragAndDrop.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<section>
<h2>Drag and drop</h2>
<ui5-list id="listDnd1" header-text="List 1">
<ui5-li id="bg1" movable>1. Bulgaria</ui5-li>
<ui5-li id="de1" movable>1. Germany</ui5-li>
<ui5-li id="es1" movable>1. Spain</ui5-li>
<ui5-li-custom id="bg1" movable><ui5-text>Item 1</ui5-text><a href="#ddd">sap</a></ui5-li-custom>
<ui5-li-custom id="de1" movable><ui5-text>Item 2</ui5-text></ui5-li-custom>
<ui5-li-custom id="es1" movable><ui5-text>Item 3</ui5-text></ui5-li-custom>
</ui5-list>
</section>

Expand Down
145 changes: 145 additions & 0 deletions packages/main/test/pages/TableDragAndDropShadowDom.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">

<title>Table (in development)</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta charset="utf-8">

<script src="%VITE_BUNDLE_PATH%" type="module"></script>

<style>
</style>
</head>

<body style="background-color: var(--sapBackgroundColor)">
<ui5-list id="list">
<ui5-li movable>Item 1</ui5-li>
<ui5-li movable>Item 2</ui5-li>
<ui5-li movable>Item 3</ui5-li>
<ui5-li movable>Item 4</ui5-li>
<ui5-li movable>Test</ui5-li>
</ui5-list>

<ui5-tree id="tree" movable style="margin-top: 1rem">
<ui5-tree-item movable text="Tree 1">
<ui5-tree-item movable text="Tree 1.1">
<ui5-tree-item movable text="Tree 1.1.1"></ui5-tree-item>
<ui5-tree-item movable text="Tree 1.1.2"></ui5-tree-item>
</ui5-tree-item>

<ui5-tree-item movable text="Tree 1.2"></ui5-tree-item>
</ui5-tree-item>

<ui5-tree-item movable text="Tree 2">
<ui5-tree-item movable text="Tree 2.1">
<ui5-tree-item movable text="Tree 2.1.1"></ui5-tree-item>
<ui5-tree-item movable text="Tree 2.1.2"></ui5-tree-item>
<ui5-tree-item movable text="Tree 2.1.3"></ui5-tree-item>
</ui5-tree-item>

<ui5-tree-item movable text="Tree 2.2">
<ui5-tree-item movable text="Tree 2.2.1">
<ui5-tree-item movable text="Tree 2.2.1.1"></ui5-tree-item>
</ui5-tree-item>
</ui5-tree-item>

<ui5-tree-item movable text="Tree 2.3">
<ui5-tree-item movable text="Tree 2.3.1"></ui5-tree-item>
<ui5-tree-item movable text="Tree 2.3.2"></ui5-tree-item>
</ui5-tree-item>
</ui5-tree-item>

<ui5-tree-item movable text="Tree 3">
<ui5-tree-item movable text="Tree 3.1"></ui5-tree-item>
</ui5-tree-item>
</ui5-tree>

<div id="host1">
<template shadowrootmode="open">
<ui5-table id="tableId" overflow-mode="Popin" style="margin-top: 1rem">
<ui5-table-selection slot="features"></ui5-table-selection>
<ui5-table-header-row slot="headerRow">
<ui5-table-header-cell width="400px">Column A</ui5-table-header-cell>
<ui5-table-header-cell width="200px">Column B</ui5-table-header-cell>
<ui5-table-header-cell min-width="150px">Column C</ui5-table-header-cell>
</ui5-table-header-row>
<ui5-table-row row-key="1" movable>
<ui5-table-cell>Test 1</ui5-table-cell>
<ui5-table-cell>Test 2</ui5-table-cell>
<ui5-table-cell>Test 3</ui5-table-cell>
</ui5-table-row>
<ui5-table-row row-key="2" movable>
<ui5-table-cell>Test 4</ui5-table-cell>
<ui5-table-cell>Test 5</ui5-table-cell>
<ui5-table-cell>Test 6</ui5-table-cell>
</ui5-table-row>
<ui5-table-row row-key="3" movable>
<ui5-table-cell>Test 7</ui5-table-cell>
<ui5-table-cell>Test 8</ui5-table-cell>
<ui5-table-cell>Test 9</ui5-table-cell>
</ui5-table-row>
</ui5-table>
</template>
</div>

<script>

const table = document.getElementById("host1").shadowRoot.querySelector("#tableId");

function treeMoveOver(e) {
e.preventDefault();
}

function listMoveOver(e) {
e.preventDefault();
}

function tableMoveOver(e) {
const { source, destination } = e.detail;

const sourceIndex = table.rows.indexOf(source.element);
const destinationIndex = table.rows.indexOf(destination.element);

if (sourceIndex === -1 || destinationIndex === -1) {
return;
}

if (source.element.hasAttribute("ui5-table-row") && destination.element.hasAttribute("ui5-table-row") && destination.placement !== "On") {
e.preventDefault();
}
}

function tableMove(e) {
const { source, destination } = e.detail;
reorderRow(source.element, destination.element, destination.placement);
}

function reorderRow(source, destination, placement) {
if (!table) {
return;
}

switch (placement) {
case "Before":
destination.insertAdjacentElement("beforebegin", source);
break;
case "After":
destination.insertAdjacentElement("afterend", source);
break;
default:
break;
}
}

table.addEventListener('move-over', tableMoveOver);
table.addEventListener('move', tableMove);

tree.addEventListener('move-over', treeMoveOver);
list.addEventListener('move-over', listMoveOver);
</script>
</body>
</html>
Loading