Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: attach element when used in drag source #20490

Merged
merged 3 commits into from
Nov 21, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import java.util.Locale;

import org.slf4j.LoggerFactory;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.ComponentUtil;
Expand All @@ -25,6 +27,7 @@
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dnd.internal.DndUtil;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.dom.Style;
import com.vaadin.flow.internal.nodefeature.VirtualChildrenList;
import com.vaadin.flow.shared.Registration;

Expand Down Expand Up @@ -344,6 +347,10 @@ default void setDragImage(Component dragImage) {
* the y-offset of the drag image
*/
default void setDragImage(Component dragImage, int offsetX, int offsetY) {
if (dragImage != null && !dragImage.isVisible()) {
throw new IllegalStateException(
"Drag image element is not visible and will not show.\nMake element visible to use as drag image!");
}
if (getDragImage() != null && getDragImage() != dragImage) {
// Remove drag image from the virtual children list if it's there.
if (getDraggableElement().getNode()
Expand All @@ -362,14 +369,12 @@ default void setDragImage(Component dragImage, int offsetX, int offsetY) {
getDragSourceComponent().addAttachListener(event -> {
if (!dragImage.isAttached()
&& dragImage.getParent().isEmpty()) {
getDraggableElement()
.appendVirtualChild(dragImage.getElement());
appendDragElement(dragImage.getElement());
}
event.unregisterListener();
});
} else {
getDraggableElement()
.appendVirtualChild(dragImage.getElement());
appendDragElement(dragImage.getElement());
}
}
ComponentUtil.setData(getDragSourceComponent(),
Expand All @@ -380,6 +385,21 @@ default void setDragImage(Component dragImage, int offsetX, int offsetY) {
(dragImage == null ? 0 : offsetY), getDraggableElement());
}

private void appendDragElement(Element dragElement) {
if (dragElement.getTag().equals("img")) {
getDraggableElement().appendVirtualChild(dragElement);
} else {
LoggerFactory.getLogger(DragSource.class).debug(
"Attaching child to dom in position -100,-100. Consider adding the component manually to not get overlapping components on drag for element.");
getDraggableElement().appendChild(dragElement);
Style style = dragElement.getStyle();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To ensure that appended element does not show up and does not affect DOM unless being dragged, it should probably have display: none by default and change to display: block automatically on drag start event before setting the drag element. And reset back when stopped dragging.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to work. Tested with the following example:

Div dragBox = new Div("Drag box");
DragSource<Div> dragSource = DragSource.create(dragBox);
dragSource.setDraggable(true);
Button button = new Button("Button");
dragSource.setDragImage(button);
add(dragBox);

It doesn't show anything.

Though it works once I configure it manually:

Div dragBox = new Div("Drag box");
DragSource<Div> dragSource = DragSource.create(dragBox);
dragSource.setDraggable(true);
Button button = new Button("Button");
add(button);
Element element = button.getElement();
Style style = element.getStyle();
style.set("position", "absolute");
style.set("top", "-100px");
style.set("left", "-100px");
// style.set("display", "none"); //also works even if hidden 
dragSource.setDragImage(button);
add(dragBox);

style.set("position", "absolute");
style.set("top", "-100px");
style.set("left", "-100px");
style.set("display", "none");
}
}

/**
* Get server side drag image. This image is applied automatically in the
* next drag start event in the browser.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ window.Vaadin.Flow.dndConnector = {
event.currentTarget.classList.add('v-dragged');
}
if(event.currentTarget.__dragImage) {
if(event.currentTarget.__dragImage.style.display === "none") {
event.currentTarget.__dragImage.style.display = "block";
event.currentTarget.classList.add('shown');
}
event.dataTransfer.setDragImage(
event.currentTarget.__dragImage,
event.currentTarget.__dragImageOffsetX,
Expand All @@ -102,6 +106,10 @@ window.Vaadin.Flow.dndConnector = {

__dragendListener: function (event) {
event.currentTarget.classList.remove('v-dragged');
if(event.currentTarget.classList.contains('shown')) {
event.currentTarget.classList.remove('shown');
event.currentTarget.__dragImage.style.display = "none";
}
},

updateDragSource: function (element) {
Expand Down
Loading