Skip to content

Commit

Permalink
fix: attach element when used in drag source (#20490)
Browse files Browse the repository at this point in the history
* fix: attach element when used in drag source

Attach elemnt to dom and move it
outside of the viewport to have it
visible as a drag image.
Image can be used without attaching
to dom. Hidden elements are also
not shown so throw exception
when using one as dragImage.

Fixes #20426

* Use display none for added element

* Log as debug

Log attach as debug now that the

Co-authored-by: Mikhail Shabarov <[email protected]>

---------

Co-authored-by: Mikhail Shabarov <[email protected]>
  • Loading branch information
caalador and mshabarov authored Nov 21, 2024
1 parent 3052ac6 commit 69e47a5
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 4 deletions.
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();
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

0 comments on commit 69e47a5

Please sign in to comment.