diff options
author | Pekka Hyvönen <pekka@vaadin.com> | 2017-05-11 14:36:27 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-11 14:36:27 +0300 |
commit | f72ac12fd257e218c370a4d686be4cc99c2a22d6 (patch) | |
tree | df7937c1835dcd6517717332147cae383a27c05c /server/src/main/java | |
parent | e2e3058a497f43f34f2fcfadf6b63de9211be659 (diff) | |
download | vaadin-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.java | 46 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/server/communication/UidlWriter.java | 7 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/ui/UI.java | 74 |
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 |