From d7142d1870bd45d5a9bb79b0d89edf3f3a5033ab Mon Sep 17 00:00:00 2001 From: Adam Wagner Date: Fri, 19 May 2017 11:22:04 +0300 Subject: [PATCH] Make it possible for drop target to accept both files and other data (#9382) --- .../DropTargetExtensionConnector.java | 54 +++++++++++++++---- .../extensions/FileDropTargetConnector.java | 6 +-- .../tests/dnd/Html5FileDragAndDropUpload.java | 15 ++++-- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java b/client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java index cd23b3bc74..cd7cc7026b 100644 --- a/client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java +++ b/client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java @@ -274,21 +274,34 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector { protected void onDrop(Event event) { NativeEvent nativeEvent = (NativeEvent) event; if (isDropAllowed(nativeEvent)) { - nativeEvent.preventDefault(); - nativeEvent.stopPropagation(); JsArrayString typesJsArray = getTypes( nativeEvent.getDataTransfer()); - List types = new ArrayList<>(); - Map data = new HashMap<>(); - for (int i = 0; i < typesJsArray.length(); i++) { - String type = typesJsArray.get(i); - types.add(type); - data.put(type, nativeEvent.getDataTransfer().getData(type)); + + /* Handle event if transfer doesn't contain files. + * + * Spec: "Dragging files can currently only happen from outside a + * browsing context, for example from a file system manager + * application." + * Thus there cannot be at the same time both files and other data + * dragged + */ + if (!containsFiles(typesJsArray)) { + nativeEvent.preventDefault(); + nativeEvent.stopPropagation(); + + List types = new ArrayList<>(); + Map data = new HashMap<>(); + for (int i = 0; i < typesJsArray.length(); i++) { + String type = typesJsArray.get(i); + types.add(type); + data.put(type, nativeEvent.getDataTransfer().getData(type)); + } + + sendDropEventToServer(types, data, DragSourceExtensionConnector + .getDropEffect(nativeEvent.getDataTransfer()), nativeEvent); } - sendDropEventToServer(types, data, DragSourceExtensionConnector - .getDropEffect(nativeEvent.getDataTransfer()), nativeEvent); } removeDragOverStyle(nativeEvent); @@ -313,6 +326,27 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector { return true; } + /** + * Tells if the given array of types contains files. + *

+ * According to HTML specification, if any files are being dragged, {@code + * dataTransfer.types} will contain the string "Files". See + * https://html.spec.whatwg.org/multipage/interaction.html#the-datatransfer-interface:dom-datatransfer-types-2 + * + * @param types + * Array of data types. + * @return {@code} true if given array contains {@code "Files"}, {@code + * false} otherwise. + */ + private boolean containsFiles(JsArrayString types) { + for (int i = 0; i < types.length(); i++) { + if ("Files".equals(types.get(i))) { + return true; + } + } + return false; + } + /** * Initiates a server RPC for the drop event. * diff --git a/client/src/main/java/com/vaadin/client/extensions/FileDropTargetConnector.java b/client/src/main/java/com/vaadin/client/extensions/FileDropTargetConnector.java index aba52f7e6b..142b7b2ff8 100644 --- a/client/src/main/java/com/vaadin/client/extensions/FileDropTargetConnector.java +++ b/client/src/main/java/com/vaadin/client/extensions/FileDropTargetConnector.java @@ -127,10 +127,10 @@ public class FileDropTargetConnector extends DropTargetExtensionConnector { if (fileParams.size() > 0) { getRpcProxy(FileDropTargetRpc.class).drop(fileParams); } - } - event.preventDefault(); - event.stopPropagation(); + event.preventDefault(); + event.stopPropagation(); + } } @Override diff --git a/uitest/src/main/java/com/vaadin/tests/dnd/Html5FileDragAndDropUpload.java b/uitest/src/main/java/com/vaadin/tests/dnd/Html5FileDragAndDropUpload.java index d58e7aa43f..708f259615 100644 --- a/uitest/src/main/java/com/vaadin/tests/dnd/Html5FileDragAndDropUpload.java +++ b/uitest/src/main/java/com/vaadin/tests/dnd/Html5FileDragAndDropUpload.java @@ -23,13 +23,13 @@ import java.util.List; import com.vaadin.server.StreamVariable; import com.vaadin.server.VaadinRequest; import com.vaadin.shared.ui.dnd.FileParameters; +import com.vaadin.shared.ui.grid.DropMode; import com.vaadin.tests.components.AbstractTestUIWithLog; import com.vaadin.ui.Grid; -import com.vaadin.ui.Html5File; -import com.vaadin.ui.Label; import com.vaadin.ui.Layout; import com.vaadin.ui.Notification; import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.components.grid.GridDropTarget; import com.vaadin.ui.dnd.FileDropTarget; public class Html5FileDragAndDropUpload extends AbstractTestUIWithLog { @@ -39,7 +39,7 @@ public class Html5FileDragAndDropUpload extends AbstractTestUIWithLog { @Override protected void setup(VaadinRequest request) { - Grid grid = new Grid<>("Drop files on the Grid"); + Grid grid = new Grid<>("Drop files or text on the Grid"); grid.addColumn(FileParameters::getName).setCaption("File name"); grid.addColumn(FileParameters::getSize).setCaption("File size"); grid.addColumn(FileParameters::getMime).setCaption("Mime type"); @@ -103,6 +103,13 @@ public class Html5FileDragAndDropUpload extends AbstractTestUIWithLog { }); }); + GridDropTarget dropTarget = new GridDropTarget<>(grid, + DropMode.ON_TOP); + dropTarget.addGridDropListener(event -> { + log("dataTransferText=" + event.getDataTransferText()); + Notification.show(event.getDataTransferText()); + }); + Layout layout = new VerticalLayout(grid); addComponent(layout); @@ -110,6 +117,6 @@ public class Html5FileDragAndDropUpload extends AbstractTestUIWithLog { @Override protected String getTestDescription() { - return "Drop files onto the Grid to upload them"; + return "Drop files onto the Grid to upload them or text"; } } -- 2.39.5