]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add more context information to criteriaScript in GridDropTargetConnector (#11321)
authorvt512 <vt512@users.noreply.github.com>
Wed, 5 Dec 2018 09:53:34 +0000 (10:53 +0100)
committerSun Zhe <31067185+ZheSun88@users.noreply.github.com>
Wed, 5 Dec 2018 09:53:34 +0000 (11:53 +0200)
* 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

client/src/main/java/com/vaadin/client/connectors/grid/GridDropTargetConnector.java
client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java
uitest/src/main/java/com/vaadin/tests/components/grid/GridDropCriteriaScript.java [new file with mode: 0644]

index 98c410015959f4751d7192fb49e3b03fe0b5435a..011b98654c741fa4380478ac72b35b6fca3a5feb 100644 (file)
@@ -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,
index 2bd0ae81f3d8410fd8c4f9ff0152b1a05e63e2d0..a2c221be44fcf18bba01d8dab0fbb4dc2e33d8a7 100644 (file)
@@ -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.
      * <p>
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 (file)
index 0000000..3d036a3
--- /dev/null
@@ -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("<h1>Test for existance of targetElement "
+                + "and dropLocation in criteriaScript</h1>"
+                + "<p>Drag one of the grid items.</p>"
+                + "<p>While dragging, hints in form of lines show "
+                + "where the item is allowed to be dropped.</p>"
+                + "<p>Test passed:" + "<ul>"
+                + "<li>ABOVE: Only a line above the item is displayed while dragging over the item</li>"
+                + "<li>BELOW: Only a line below the item is displayed while dragging over the item</li>"
+                + "<li>ON_TOP: Only a border around the item is displayed while dragging over the item</li>"
+                + "</ul>" + "</p>" + "<p>Test failed:" + "<ul>"
+                + "<li>otherwise</li>" + "</ul>" + "</p>", ContentMode.HTML);
+
+        final Grid<GridItem> grid = new Grid<>();
+        grid.addColumn(GridItem::getCaption);
+        grid.setStyleGenerator(
+                gridItem -> "dropLocation-" + gridItem.getDropLocation());
+
+        new GridDragSource<>(grid);
+
+        final GridDropTarget<GridItem> 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<GridItem> createItems() {
+        final ArrayList<GridItem> 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;
+    }
+
+}