Browse Source

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
tags/8.7.0.alpha1
vt512 5 years ago
parent
commit
ea22a7d17d

+ 19
- 0
client/src/main/java/com/vaadin/client/connectors/grid/GridDropTargetConnector.java View 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,

+ 20
- 6
client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java View 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>

+ 86
- 0
uitest/src/main/java/com/vaadin/tests/components/grid/GridDropCriteriaScript.java View File

@@ -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;
}

}

Loading…
Cancel
Save