diff options
author | Pekka Hyvönen <pekka@vaadin.com> | 2017-05-10 14:42:31 +0300 |
---|---|---|
committer | Ilia Motornyi <elmot@vaadin.com> | 2017-05-10 14:42:31 +0300 |
commit | cbb4393847f02fdbdcd64528918aeacbdc5565e3 (patch) | |
tree | b6003782b956f5f1f9aed2f1d4707d383515a810 /client | |
parent | 624a9594b55f0b35e75b9aefd80a97049bc51eed (diff) | |
download | vaadin-framework-cbb4393847f02fdbdcd64528918aeacbdc5565e3.tar.gz vaadin-framework-cbb4393847f02fdbdcd64528918aeacbdc5565e3.zip |
Fix partly missing drag image regression on Safari
Doesn't fix #9261, drag image missing on Safari when dragging grid row because
that has position: absolute and offset.
Diffstat (limited to 'client')
-rw-r--r-- | client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceConnector.java | 82 | ||||
-rw-r--r-- | client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java | 54 |
2 files changed, 103 insertions, 33 deletions
diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceConnector.java index 3f673bac01..134e76e7e5 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceConnector.java @@ -27,6 +27,7 @@ import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.TableRowElement; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Image; import com.vaadin.client.BrowserInfo; import com.vaadin.client.ServerConnector; import com.vaadin.client.WidgetUtil; @@ -37,6 +38,7 @@ import com.vaadin.client.widgets.Escalator; import com.vaadin.client.widgets.Grid; import com.vaadin.shared.Range; import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.dnd.DragSourceState; import com.vaadin.shared.ui.dnd.DropEffect; import com.vaadin.shared.ui.grid.GridDragSourceRpc; import com.vaadin.shared.ui.grid.GridDragSourceState; @@ -98,33 +100,53 @@ public class GridDragSourceConnector extends DragSourceExtensionConnector { return; } + super.onDragStart(event); + } + + @Override + 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) + // Add badge showing the number of dragged columns - if (draggedItemKeys.size() > 1) { - Element draggedRowElement = (Element) event.getTarget(); - - Element badge = DOM.createSpan(); - badge.setClassName(gridConnector.getWidget().getStylePrimaryName() - + "-row" + STYLE_SUFFIX_DRAG_BADGE); - badge.setInnerHTML(draggedItemKeys.size() + ""); - - badge.getStyle().setMarginLeft( - getRelativeX(draggedRowElement, (NativeEvent) event) + 10, - Style.Unit.PX); - badge.getStyle().setMarginTop( - getRelativeY(draggedRowElement, (NativeEvent) event) - - draggedRowElement.getOffsetHeight() + 10, - Style.Unit.PX); - - draggedRowElement.appendChild(badge); - - // Remove badge on the next animation frame. Drag image will still - // contain the badge. - AnimationScheduler.get().requestAnimationFrame(timestamp -> { - badge.removeFromParent(); - }, (Element) event.getTarget()); + String imageUrl = getResourceUrl(DragSourceState.RESOURCE_DRAG_IMAGE); + if (imageUrl != null && !imageUrl.isEmpty()) { + Image dragImage = new Image( + getConnection().translateVaadinUri(imageUrl)); + dragStartEvent.getDataTransfer() + .setDragImage(dragImage.getElement(), 0, 0); + } else { + Element draggedRowElement = (Element) dragStartEvent + .getEventTarget().cast(); + if (draggedItemKeys.size() > 1) { + + Element badge = DOM.createSpan(); + badge.setClassName( + gridConnector.getWidget().getStylePrimaryName() + "-row" + + 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); + + draggedRowElement.appendChild(badge); + + // Remove badge on the next animation frame. Drag image will + // still contain the badge. + AnimationScheduler.get().requestAnimationFrame(timestamp -> { + badge.removeFromParent(); + }, (Element) dragStartEvent.getEventTarget().cast()); + setDraggable(draggedRowElement); + } + fixDragImageForSafari(draggedRowElement); } - - super.onDragStart(event); } private int getRelativeY(Element element, NativeEvent event) { @@ -196,9 +218,9 @@ public class GridDragSourceConnector extends DragSourceExtensionConnector { * allowed and a selected row is dragged. * * @param draggedRow - * Data of dragged row. + * Data of dragged row. * @return {@code true} if multiple rows are dragged, {@code false} - * otherwise. + * otherwise. */ private boolean dragMultipleRows(JsonObject draggedRow) { SelectionModel<JsonObject> selectionModel = getGrid() @@ -221,7 +243,7 @@ public class GridDragSourceConnector extends DragSourceExtensionConnector { * Get all selected rows from a subset of rows defined by {@code range}. * * @param range - * Range of indexes. + * Range of indexes. * @return List of data of all selected rows in the given range. */ private List<JsonObject> getSelectedRowsInRange(Range range) { @@ -241,7 +263,7 @@ public class GridDragSourceConnector extends DragSourceExtensionConnector { * Converts a list of {@link JsonObject}s to a {@link JsonArray}. * * @param objects - * List of json objects. + * List of json objects. * @return Json array containing all json objects. */ private JsonArray toJsonArray(List<JsonObject> objects) { @@ -257,7 +279,7 @@ public class GridDragSourceConnector extends DragSourceExtensionConnector { * otherwise. * * @param row - * Row data. + * Row data. * @return Drag data if present or row data otherwise. */ private JsonObject getDragData(JsonObject row) { diff --git a/client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java b/client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java index 932128a8b3..e718fb90d7 100644 --- a/client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java +++ b/client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java @@ -15,9 +15,12 @@ */ package com.vaadin.client.extensions; +import com.google.gwt.animation.client.AnimationScheduler; import com.google.gwt.dom.client.DataTransfer; 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.Position; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.BrowserInfo; @@ -163,7 +166,7 @@ public class DragSourceExtensionConnector extends AbstractExtensionConnector { } // Set drag image - setDragImage(event); + setDragImage(nativeEvent); // Set text data parameter String dataTransferText = createDataTransferText(event); @@ -185,6 +188,48 @@ public class DragSourceExtensionConnector extends AbstractExtensionConnector { } /** + * Fixes missing drag image for 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. + * <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()) { + return; + } + final Style style = draggedElement.getStyle(); + final String position = style.getPosition(); + + // relative works always + if ("relative".equalsIgnoreCase(position)) { + return; + } + + // absolute & fixed don't work when there is offset used + if ("absolute".equalsIgnoreCase(position) + || "fixed".equalsIgnoreCase(position)) { + // FIXME #9261 need to figure out how to get absolute and fixed to + // position work when there is offset involved, like in Grid. + // The following hack with setting position to relative did not + // work, nor did clearing top/right/bottom/left. + } + + // for all other positions, set the position to relative and revert it + // in an animation frame + draggedElement.getStyle().setPosition(Position.RELATIVE); + AnimationScheduler.get().requestAnimationFrame(timestamp -> { + draggedElement.getStyle().setProperty("position", position); + }, draggedElement); + } + + /** * Creates data of type {@code "text"} for the {@code DataTransfer} object * of the given event. * @@ -215,13 +260,16 @@ public class DragSourceExtensionConnector extends AbstractExtensionConnector { * @param dragStartEvent * The drag start event. */ - protected void setDragImage(Event dragStartEvent) { + protected void setDragImage(NativeEvent dragStartEvent) { String imageUrl = getResourceUrl(DragSourceState.RESOURCE_DRAG_IMAGE); if (imageUrl != null && !imageUrl.isEmpty()) { Image dragImage = new Image( getConnection().translateVaadinUri(imageUrl)); - ((NativeEvent) dragStartEvent).getDataTransfer() + dragStartEvent.getDataTransfer() .setDragImage(dragImage.getElement(), 0, 0); + } else { + fixDragImageForSafari( + (Element) dragStartEvent.getCurrentEventTarget().cast()); } } |