Kaynağa Gözat

Fix drag image offset for Grid rows for mobile (#9336)

Asks the polyfill to always center the drag image based on the touch coordinates.
Also temporarely removes the transform offset for the row.
tags/8.1.0.beta1
Pekka Hyvönen 7 yıl önce
ebeveyn
işleme
19ad2a565f

+ 22
- 21
client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceConnector.java Dosyayı Görüntüle

@@ -26,7 +26,8 @@ import java.util.stream.Collectors;
import com.google.gwt.animation.client.AnimationScheduler;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Float;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
@@ -39,7 +40,6 @@ import com.vaadin.client.widget.escalator.RowContainer;
import com.vaadin.client.widget.grid.selection.SelectionModel;
import com.vaadin.client.widgets.Escalator;
import com.vaadin.client.widgets.Grid;
import com.vaadin.server.SerializableFunction;
import com.vaadin.shared.Range;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.dnd.DragSourceState;
@@ -150,8 +150,8 @@ public class GridDragSourceConnector extends DragSourceExtensionConnector {
protected void setDragImage(NativeEvent dragStartEvent) {
// do not call super since need to handle specifically
// 1. use resource if set (never needs safari hack)
// 2. add number badge if necessary (with safari hack if needed)
// 3. just use normal (with safari hack if needed)
// 2. add row count badge if necessary
// 3. apply hacks for safari/mobile drag image if needed

// Add badge showing the number of dragged columns
String imageUrl = getResourceUrl(DragSourceState.RESOURCE_DRAG_IMAGE);
@@ -171,13 +171,18 @@ public class GridDragSourceConnector extends DragSourceExtensionConnector {
+ STYLE_SUFFIX_DRAG_BADGE);
badge.setInnerHTML(draggedItemKeys.size() + "");

badge.getStyle().setMarginLeft(
getRelativeX(draggedRowElement, dragStartEvent) + 10,
Style.Unit.PX);
badge.getStyle().setMarginTop(
getRelativeY(draggedRowElement, dragStartEvent)
- draggedRowElement.getOffsetHeight() + 10,
Style.Unit.PX);
if (BrowserInfo.get().isTouchDevice()) {
// the drag image is centered on the touch coordinates
// -> show the badge on the right edge of the row
badge.getStyle().setFloat(Float.RIGHT);
badge.getStyle().setMarginRight(20, Unit.PX);
} else {
badge.getStyle().setMarginLeft(
getRelativeX(draggedRowElement, dragStartEvent)
+ 10,
Unit.PX);
}
badge.getStyle().setMarginTop(-20, Unit.PX);

draggedRowElement.appendChild(badge);

@@ -187,15 +192,11 @@ public class GridDragSourceConnector extends DragSourceExtensionConnector {
badge.removeFromParent();
}, (Element) dragStartEvent.getEventTarget().cast());
}
fixDragImageForSafari(draggedRowElement);
fixDragImageForDesktopSafari(draggedRowElement);
fixDragImageTransformForMobile(draggedRowElement);
}
}

private int getRelativeY(Element element, NativeEvent event) {
int relativeTop = element.getAbsoluteTop() - Window.getScrollTop();
return WidgetUtil.getTouchOrMouseClientY(event) - relativeTop;
}

private int getRelativeX(Element element, NativeEvent event) {
int relativeLeft = element.getAbsoluteLeft() - Window.getScrollLeft();
return WidgetUtil.getTouchOrMouseClientX(event) - relativeLeft;
@@ -204,8 +205,8 @@ public class GridDragSourceConnector extends DragSourceExtensionConnector {
@Override
protected Map<String, String> createDataTransferData(
NativeEvent dragStartEvent) {
Map<String, String> dataMap = super
.createDataTransferData(dragStartEvent);
Map<String, String> dataMap = super.createDataTransferData(
dragStartEvent);

// Add data provided by the generator functions
getDraggedRows(dragStartEvent).forEach(row -> {
@@ -331,9 +332,9 @@ public class GridDragSourceConnector extends DragSourceExtensionConnector {
* Gets drag data provided by the generator functions.
*
* @param row
* The row data.
* The row data.
* @return The generated drag data type mapped to the corresponding drag
* data. If there are no generator functions, returns an empty map.
* data. If there are no generator functions, returns an empty map.
*/
private Map<String, String> getRowDragData(JsonObject row) {
// Collect a map of data types and data that is provided by the

+ 40
- 8
client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java Dosyayı Görüntüle

@@ -211,20 +211,22 @@ public class DragSourceExtensionConnector extends AbstractExtensionConnector {
}

/**
* Fixes missing drag image for Safari by making the dragged element
* Fixes missing drag image for desktop Safari by making the dragged element
* position to relative if needed. Safari won't show drag image unless the
* dragged element position is relative or absolute / fixed, but not with
* display block for the latter.
* <p>
* This method is a NOOP for non-safari browser.
* This method is a NOOP for non-safari browser, or mobile safari which is
* using the DnD Polyfill.
* <p>
* This fix is not needed if a custom drag image is used on Safari.
*
* @param draggedElement
* the element that forms the drag image
*/
protected void fixDragImageForSafari(Element draggedElement) {
if (!BrowserInfo.get().isSafari()) {
protected void fixDragImageForDesktopSafari(Element draggedElement) {
if (!BrowserInfo.get().isSafari()
|| BrowserInfo.get().isTouchDevice()) {
return;
}
final Style style = draggedElement.getStyle();
@@ -252,13 +254,41 @@ public class DragSourceExtensionConnector extends AbstractExtensionConnector {
}, draggedElement);
}

/**
* Fix drag image offset for touch devices when the dragged image has been
* offset with css transform: translate/translate3d.
* <p>
* This necessary for e.g grid rows.
* <p>
* This method is NOOP for non-touch browsers.
*
* @param draggedElement
* the element that forms the drag image
*/
protected void fixDragImageTransformForMobile(Element draggedElement) {
if (!BrowserInfo.get().isTouchDevice()) {
return;
}

Style style = draggedElement.getStyle();
String transition = style.getProperty("transform");
if (transition == null || transition.isEmpty()
|| !transition.startsWith("translate")) {
return;
}
style.clearProperty("transform");
AnimationScheduler.get().requestAnimationFrame(timestamp -> {
draggedElement.getStyle().setProperty("transform", transition);
}, draggedElement);
}

/**
* Creates the data map to be set as the {@code DataTransfer} object's data.
*
* @param dragStartEvent
* The drag start event
* The drag start event
* @return The map from type to data, or {@code null} for not setting any
* data. Returning {@code null} will cancel the drag start.
* data. Returning {@code null} will cancel the drag start.
*/
protected Map<String, String> createDataTransferData(
NativeEvent dragStartEvent) {
@@ -299,8 +329,10 @@ public class DragSourceExtensionConnector extends AbstractExtensionConnector {
dragStartEvent.getDataTransfer()
.setDragImage(dragImage.getElement(), 0, 0);
} else {
fixDragImageForSafari(
(Element) dragStartEvent.getCurrentEventTarget().cast());
Element draggedElement = (Element) dragStartEvent
.getCurrentEventTarget().cast();
fixDragImageForDesktopSafari(draggedElement);
fixDragImageTransformForMobile(draggedElement);
}
}


+ 4
- 2
client/src/main/java/com/vaadin/client/ui/ui/UIConnector.java Dosyayı Görüntüle

@@ -1231,9 +1231,11 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
}
}

// TODO add configuration to use custom drag start decider
private static native void initializeMobileDndPolyfill()
/*-{
$wnd.DragDropPolyfill.Initialize();
var conf = new Object();
// this is needed or the drag image will offset to weird place in for grid rows
conf['dragImageCenterOnTouch'] = true;
$wnd.DragDropPolyfill.Initialize(conf);
}-*/;
}

+ 2
- 0
uitest/src/main/java/com/vaadin/tests/dnd/DragImage.java Dosyayı Görüntüle

@@ -24,6 +24,8 @@ public class DragImage extends AbstractTestUIWithLog {

@Override
protected void setup(VaadinRequest request) {
setMobileHtml5DndEnabled(true);

HorizontalLayout layout1 = new HorizontalLayout();
layout1.setCaption("No custom drag image");
Styles styles = Page.getCurrent().getStyles();

Loading…
İptal
Kaydet