* 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 UItags/8.7.0.alpha1
super.extend(target); | 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 | * 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, | * of specific row as the drop target. This is based on used drop mode, |
// Currently Safari, Edge and IE don't follow the spec by allowing drop | // Currently Safari, Edge and IE don't follow the spec by allowing drop | ||||
// if those don't match | // if those don't match | ||||
// Allow by default when criteria not set | |||||
boolean allowed = true; | |||||
// Execute criteria script | // Execute criteria script | ||||
if (getState().criteriaScript != null) { | |||||
allowed = executeScript(event, getState().criteriaScript); | |||||
} | |||||
boolean allowed = isDropAllowedByCriteriaScript(event); | |||||
// Execute criterion defined via API | // Execute criterion defined via API | ||||
if (allowed && getState().criteria != null | if (allowed && getState().criteria != null | ||||
return allowed; | 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. | * Tells if the given array of types contains files. | ||||
* <p> | * <p> |
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; | |||||
} | |||||
} |