From ea22a7d17dcc82d2e28dbb0051fbb6904fd7c98d Mon Sep 17 00:00:00 2001
From: vt512
Date: Wed, 5 Dec 2018 10:53:34 +0100
Subject: Add more context information to criteriaScript in
GridDropTargetConnector (#11321)
* Add more context information to criteriaScript in GridDropTargetConnector
When using drag and drop in Grids and TreeGrids a criteriaScript can be specified.
However, this criteriaScript only gets an event as input parameter.
It would be helpful if the criteriaScript would get more information:
- the DropLocation
- the targetElement which is used as a base for the DropLocation
This change provides a protected method in DropTargetExtensionConnector
which decides, if the drop is allowed by the criteriaScript.
This method is overriden in GridDropTargetConnector to
provide the both parameters dropLocation and targetElement.
* add Test UI for criteriaScript with targetElement and dropLocation
* add some description for the Test UI
---
.../connectors/grid/GridDropTargetConnector.java | 19 +++++
.../extensions/DropTargetExtensionConnector.java | 26 +++++--
.../components/grid/GridDropCriteriaScript.java | 86 ++++++++++++++++++++++
3 files changed, 125 insertions(+), 6 deletions(-)
create mode 100644 uitest/src/main/java/com/vaadin/tests/components/grid/GridDropCriteriaScript.java
diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/GridDropTargetConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/GridDropTargetConnector.java
index 98c4100159..011b98654c 100644
--- a/client/src/main/java/com/vaadin/client/connectors/grid/GridDropTargetConnector.java
+++ b/client/src/main/java/com/vaadin/client/connectors/grid/GridDropTargetConnector.java
@@ -100,6 +100,25 @@ public class GridDropTargetConnector extends DropTargetExtensionConnector {
super.extend(target);
}
+ @Override
+ protected boolean isDropAllowedByCriteriaScript(NativeEvent event) {
+ final String criteriaScript = getState().criteriaScript;
+ if (criteriaScript == null) {
+ return true;
+ }
+ return executeScript(event,
+ getTargetElement(event.getEventTarget().cast()),
+ getDropLocation(getTargetElement(event.getEventTarget().cast()),
+ event).name(),
+ criteriaScript);
+ }
+
+ private native boolean executeScript(NativeEvent event,
+ Element targetElement, String dropLocation, String script)
+ /*-{
+ return new Function('event', 'targetElement', 'dropLocation', script)(event, targetElement, dropLocation);
+ }-*/;
+
/**
* Inspects whether the current drop would happen on the whole grid instead
* of specific row as the drop target. This is based on used drop mode,
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 2bd0ae81f3..a2c221be44 100644
--- a/client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java
+++ b/client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java
@@ -326,13 +326,8 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector {
// Currently Safari, Edge and IE don't follow the spec by allowing drop
// if those don't match
- // Allow by default when criteria not set
- boolean allowed = true;
-
// Execute criteria script
- if (getState().criteriaScript != null) {
- allowed = executeScript(event, getState().criteriaScript);
- }
+ boolean allowed = isDropAllowedByCriteriaScript(event);
// Execute criterion defined via API
if (allowed && getState().criteria != null
@@ -365,6 +360,25 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector {
return allowed;
}
+ /**
+ * Checks if a criteria script exists and, if yes, executes it. This method
+ * is protected, so subclasses as e.g. GridDropTargetConnector can override
+ * it to add additional script parameters.
+ *
+ * @param event
+ * browser event (dragEnter, dragOver, drop) that should be
+ * evaluated by the criteria script
+ * @return {@code true} if no script was given or if the script returned
+ * true, {@code false} otherwise.
+ */
+ protected boolean isDropAllowedByCriteriaScript(NativeEvent event) {
+ final String criteriaScript = getState().criteriaScript;
+ if (criteriaScript == null) {
+ return true;
+ }
+ return executeScript(event, criteriaScript);
+ }
+
/**
* Tells if the given array of types contains files.
*
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridDropCriteriaScript.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridDropCriteriaScript.java
new file mode 100644
index 0000000000..3d036a3d3b
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridDropCriteriaScript.java
@@ -0,0 +1,86 @@
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.ContentMode;
+import com.vaadin.shared.ui.grid.DropLocation;
+import com.vaadin.shared.ui.grid.DropMode;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.components.grid.GridDragSource;
+import com.vaadin.ui.components.grid.GridDropTarget;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Theme("valo")
+@Widgetset("com.vaadin.DefaultWidgetSet")
+public class GridDropCriteriaScript extends AbstractTestUI {
+
+ class GridItem {
+ public final String caption;
+ public final DropLocation dropLocation;
+
+ public GridItem(String caption, DropLocation dropLocation) {
+ this.caption = caption;
+ this.dropLocation = dropLocation;
+ }
+
+ public String getCaption() {
+ return caption;
+ }
+
+ public DropLocation getDropLocation() {
+ return dropLocation;
+ }
+ }
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ getUI().setMobileHtml5DndEnabled(true);
+
+ final Label label = new Label("
Test for existance of targetElement "
+ + "and dropLocation in criteriaScript
"
+ + "Drag one of the grid items.
"
+ + "While dragging, hints in form of lines show "
+ + "where the item is allowed to be dropped.
"
+ + "Test passed:" + "
"
+ + "- ABOVE: Only a line above the item is displayed while dragging over the item
"
+ + "- BELOW: Only a line below the item is displayed while dragging over the item
"
+ + "- ON_TOP: Only a border around the item is displayed while dragging over the item
"
+ + "
" + "
" + "Test failed:" + "
" + "", ContentMode.HTML);
+
+ final Grid grid = new Grid<>();
+ grid.addColumn(GridItem::getCaption);
+ grid.setStyleGenerator(
+ gridItem -> "dropLocation-" + gridItem.getDropLocation());
+
+ new GridDragSource<>(grid);
+
+ final GridDropTarget dropTarget = new GridDropTarget<>(grid,
+ DropMode.ON_TOP_OR_BETWEEN);
+ dropTarget.setDropCriteriaScript(
+ "return targetElement.classList.contains('dropLocation-' + dropLocation);");
+
+ grid.setItems(createItems());
+
+ addComponents(label, grid);
+ }
+
+ private List createItems() {
+ final ArrayList list = new ArrayList<>();
+ for (int i = 0; i < 10; i++) {
+ for (DropLocation dropLocation : new DropLocation[] {
+ DropLocation.ON_TOP, DropLocation.ABOVE,
+ DropLocation.BELOW }) {
+ list.add(new GridItem(i + ": " + dropLocation.name(),
+ dropLocation));
+ }
+ }
+ return list;
+ }
+
+}
--
cgit v1.2.3