aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/main/java
diff options
context:
space:
mode:
authorPekka Hyvönen <pekka@vaadin.com>2017-05-11 14:36:27 +0300
committerGitHub <noreply@github.com>2017-05-11 14:36:27 +0300
commitf72ac12fd257e218c370a4d686be4cc99c2a22d6 (patch)
treedf7937c1835dcd6517717332147cae383a27c05c /server/src/main/java
parente2e3058a497f43f34f2fcfadf6b63de9211be659 (diff)
downloadvaadin-framework-f72ac12fd257e218c370a4d686be4cc99c2a22d6.tar.gz
vaadin-framework-f72ac12fd257e218c370a4d686be4cc99c2a22d6.zip
Add mobile html5 dnd support using polyfill (#9282)
First step of mobile DND support. - Add mobile html5 dnd support using polyfill - Adds a switch for enabling mobile html5 dnd support - Adds polyfill only when needed - Ignore native Android Chrome drag start because doesn't work properly (no dragend event fired) - Add documentation on enabling mobile HTML5 DnD support - Add mention of drag-drop-polyfill license - Fixed issue in polyfill when not using "snapback" - Add mention of forked polyfill Fixes #9174
Diffstat (limited to 'server/src/main/java')
-rw-r--r--server/src/main/java/com/vaadin/server/Page.java46
-rw-r--r--server/src/main/java/com/vaadin/server/communication/UidlWriter.java7
-rw-r--r--server/src/main/java/com/vaadin/ui/UI.java74
3 files changed, 124 insertions, 3 deletions
diff --git a/server/src/main/java/com/vaadin/server/Page.java b/server/src/main/java/com/vaadin/server/Page.java
index 1cebe42802..385aa0bf9a 100644
--- a/server/src/main/java/com/vaadin/server/Page.java
+++ b/server/src/main/java/com/vaadin/server/Page.java
@@ -20,11 +20,15 @@ import java.io.Serializable;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.EventObject;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
+import com.vaadin.annotations.HtmlImport;
+import com.vaadin.annotations.StyleSheet;
import com.vaadin.event.EventRouter;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.BorderStyle;
@@ -33,6 +37,7 @@ import com.vaadin.shared.ui.ui.PageState;
import com.vaadin.shared.ui.ui.UIConstants;
import com.vaadin.shared.ui.ui.UIState;
import com.vaadin.shared.util.SharedUtil;
+import com.vaadin.ui.Dependency;
import com.vaadin.ui.JavaScript;
import com.vaadin.ui.LegacyWindow;
import com.vaadin.ui.Link;
@@ -560,6 +565,8 @@ public class Page implements Serializable {
private String newPushState;
private String newReplaceState;
+ private List<Dependency> pendingDependencies;
+
public Page(UI uI, PageState state) {
this.uI = uI;
this.state = state;
@@ -1426,4 +1433,43 @@ public class Page implements Serializable {
private boolean hasEventRouter() {
return eventRouter != null;
}
+
+ /**
+ * Add a dependency that should be added to the current page.
+ * <p>
+ * These dependencies are always added before the dependencies included by
+ * using the annotations {@link HtmlImport}, {@link JavaScript} and
+ * {@link StyleSheet} during the same request.
+ * <p>
+ * Please note that these dependencies are always sent to the client side
+ * and not filtered out by any {@link DependencyFilter}.
+ *
+ * @param dependency
+ * the dependency to add
+ * @since 8.1
+ */
+ public void addDependency(Dependency dependency) {
+ if (pendingDependencies == null) {
+ pendingDependencies = new ArrayList<>();
+ }
+ pendingDependencies.add(dependency);
+ }
+
+ /**
+ * Returns all pending dependencies.
+ * <p>
+ * For internal use only, calling this method will clear the pending
+ * dependencies.
+ *
+ * @return the pending dependencies to the current page
+ * @since 8.1
+ */
+ public Collection<Dependency> getPendingDependencies() {
+ ArrayList<Dependency> copy = new ArrayList<>();
+ if (pendingDependencies != null) {
+ copy.addAll(pendingDependencies);
+ }
+ pendingDependencies = null;
+ return copy;
+ }
}
diff --git a/server/src/main/java/com/vaadin/server/communication/UidlWriter.java b/server/src/main/java/com/vaadin/server/communication/UidlWriter.java
index 7b5f83000c..7511ccd7ec 100644
--- a/server/src/main/java/com/vaadin/server/communication/UidlWriter.java
+++ b/server/src/main/java/com/vaadin/server/communication/UidlWriter.java
@@ -283,9 +283,10 @@ public class UidlWriter implements Serializable {
}
});
- List<Dependency> dependencies = Dependency
- .findAndFilterDependencies(newConnectorTypes, manager,
- new FilterContext(session));
+ List<Dependency> dependencies = new ArrayList<>();
+ dependencies.addAll(ui.getPage().getPendingDependencies());
+ dependencies.addAll(Dependency.findAndFilterDependencies(
+ newConnectorTypes, manager, new FilterContext(session)));
// Include dependencies in output if there are any
if (!dependencies.isEmpty()) {
diff --git a/server/src/main/java/com/vaadin/ui/UI.java b/server/src/main/java/com/vaadin/ui/UI.java
index 536b2603dd..1928aabe87 100644
--- a/server/src/main/java/com/vaadin/ui/UI.java
+++ b/server/src/main/java/com/vaadin/ui/UI.java
@@ -45,6 +45,7 @@ import com.vaadin.event.UIEvents.PollEvent;
import com.vaadin.event.UIEvents.PollListener;
import com.vaadin.event.UIEvents.PollNotifier;
import com.vaadin.event.dnd.DragSourceExtension;
+import com.vaadin.event.dnd.DropTargetExtension;
import com.vaadin.navigator.Navigator;
import com.vaadin.server.ClientConnector;
import com.vaadin.server.ComponentSizeValidator;
@@ -63,6 +64,7 @@ import com.vaadin.server.VaadinServlet;
import com.vaadin.server.VaadinSession;
import com.vaadin.server.VaadinSession.State;
import com.vaadin.server.communication.PushConnection;
+import com.vaadin.shared.ApplicationConstants;
import com.vaadin.shared.Connector;
import com.vaadin.shared.EventId;
import com.vaadin.shared.MouseEventDetails;
@@ -71,12 +73,14 @@ import com.vaadin.shared.communication.PushMode;
import com.vaadin.shared.ui.WindowOrderRpc;
import com.vaadin.shared.ui.ui.DebugWindowClientRpc;
import com.vaadin.shared.ui.ui.DebugWindowServerRpc;
+import com.vaadin.shared.ui.ui.PageClientRpc;
import com.vaadin.shared.ui.ui.ScrollClientRpc;
import com.vaadin.shared.ui.ui.UIClientRpc;
import com.vaadin.shared.ui.ui.UIConstants;
import com.vaadin.shared.ui.ui.UIServerRpc;
import com.vaadin.shared.ui.ui.UIState;
import com.vaadin.ui.Component.Focusable;
+import com.vaadin.ui.Dependency.Type;
import com.vaadin.ui.Window.WindowOrderChangeListener;
import com.vaadin.ui.declarative.Design;
import com.vaadin.util.ConnectorHelper;
@@ -658,6 +662,8 @@ public abstract class UI extends AbstractSingleComponentContainer
private String embedId;
+ private boolean mobileHtml5DndPolyfillLoaded;
+
/**
* This method is used by Component.Focusable objects to request focus to
* themselves. Focus renders must be handled at window level (instead of
@@ -1834,6 +1840,74 @@ public abstract class UI extends AbstractSingleComponentContainer
}
/**
+ * Returns whether HTML5 DnD extensions {@link DragSourceExtension} and
+ * {@link DropTargetExtension} and alike should be enabled for mobile
+ * devices.
+ * <p>
+ * By default, it is disabled.
+ *
+ * @return {@code true} if enabled, {@code false} if not
+ * @since 8.1
+ * @see #setMobileHtml5DndEnabled(boolean)
+ */
+ public boolean isMobileHtml5DndEnabled() {
+ return getState(false).enableMobileHTML5DnD;
+ }
+
+ /**
+ * Enable or disable HTML5 DnD for mobile devices.
+ * <p>
+ * Usually you should enable the support in the {@link #init(VaadinRequest)}
+ * method. By default, it is disabled. This operation is NOOP when the user
+ * is not on a mobile device.
+ * <p>
+ * Changing this will effect all {@link DragSourceExtension} and
+ * {@link DropTargetExtension} (and subclasses) that have not yet been
+ * attached to the UI on the client side.
+ * <p>
+ * <em>NOTE: When disabling this after it has been enabled, it will not
+ * affect {@link DragSourceExtension} and {@link DropTargetExtension} (and
+ * subclasses) that have been previously added. Those extensions should be
+ * explicitly removed to make sure user cannot perform DnD operations
+ * anymore.</em>
+ *
+ * @param enabled
+ * {@code true} if enabled, {@code false} if not
+ * @since 8.1
+ */
+ public void setMobileHtml5DndEnabled(boolean enabled) {
+ if (getState(false).enableMobileHTML5DnD != enabled) {
+ getState().enableMobileHTML5DnD = enabled;
+
+ if (isMobileHtml5DndEnabled()) {
+ loadMobileHtml5DndPolyfill();
+ }
+ }
+ }
+
+ /**
+ * Load and initialize the mobile drag-drop-polyfill if needed and not yet
+ * done so.
+ */
+ private void loadMobileHtml5DndPolyfill() {
+ if (mobileHtml5DndPolyfillLoaded) {
+ return;
+ }
+ if (!getPage().getWebBrowser().isTouchDevice()) {
+ return;
+ }
+ mobileHtml5DndPolyfillLoaded = true;
+
+ String vaadinLocation = getSession().getService().getStaticFileLocation(
+ VaadinService.getCurrentRequest()) + "/VAADIN/";
+
+ getPage().addDependency(new Dependency(Type.JAVASCRIPT,
+ vaadinLocation + ApplicationConstants.MOBILE_DND_POLYFILL_JS));
+
+ getRpcProxy(PageClientRpc.class).initializeMobileHtml5DndPolyfill();
+ }
+
+ /**
* Event which is fired when the ordering of the windows is updated.
* <p>
* The other way to listen window position for specific window is