WICKET-6286 support failure callback for NewWindow too
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/39908992 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/39908992 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/39908992 Branch: refs/heads/master Commit: 3990899278e2dc5a2c60eac9acf71af9716d018c Parents: a7c0109 Author: Sven Meier <svenme...@apache.org> Authored: Tue Mar 21 23:09:53 2017 +0100 Committer: Sven Meier <svenme...@apache.org> Committed: Tue Mar 21 23:23:17 2017 +0100 ---------------------------------------------------------------------- .../examples/ajax/builtin/AjaxDownloadPage.html | 18 +- .../examples/ajax/builtin/AjaxDownloadPage.java | 164 +++++++++++-------- wicket-examples/src/main/webapp/WEB-INF/web.xml | 21 --- .../wicket/extensions/ajax/AjaxDownload.java | 42 +++-- .../extensions/ajax/wicket-ajaxdownload.js | 54 ++++-- 5 files changed, 163 insertions(+), 136 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/39908992/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.html ---------------------------------------------------------------------- diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.html index 670c736..0be7fe2 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.html +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.html @@ -23,23 +23,19 @@ <wicket:extend> <p> -This example demonstrates a <a wicket:id="download">download</a> initiated via Ajax. + All links below initiate a download of a resource via Ajax (failing every third time): </p> -<p> -This download <a wicket:id="downloadFailure">fails</a>. -</p> - -<p> -A resource reference can be <a wicket:id="downloadReference">used too</a>. -</p> +<ul> + <li>via an <a wicket:id="download">iframe</a>.</li> + <li>in a <a wicket:id="downloadInNewWindow">new browser window</a>.</li> + <li>in the <a wicket:id="downloadInSameWindow">same window</a>.</li> +</ul> <p> - This example demonstrates a <a wicket:id="downloadInNewWindow">download</a> - initiated via Ajax and serving the response in a new browser window. + Alternatively a <a wicket:id="downloadReference">resource reference</a> can be used too. </p> - <div wicket:id="downloading" class="download-veil"><span>Preparing download ...</span></div> </wicket:extend> http://git-wip-us.apache.org/repos/asf/wicket/blob/39908992/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.java ---------------------------------------------------------------------- diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.java index b339b64..b589091 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.java @@ -16,6 +16,8 @@ */ package org.apache.wicket.examples.ajax.builtin; +import java.util.concurrent.TimeUnit; + import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.extensions.ajax.AjaxDownload; @@ -29,8 +31,6 @@ import org.apache.wicket.util.resource.IResourceStream; import org.apache.wicket.util.resource.StringResourceStream; import org.apache.wicket.util.time.Duration; -import java.util.concurrent.TimeUnit; - /** * Ajax download. * @@ -52,30 +52,26 @@ public class AjaxDownloadPage extends BasePage initDownload(); - initDownloadFailure(); + initDownloadInNewWindow(); - initDownloadReference(); + initDownloadInSameWindow(); - initDownloadInNewWindow(); + initDownloadReference(); } + @Override + protected void onConfigure() + { + super.onConfigure(); + + // download cannot continue on page refresh + downloadingContainer.setVisible(false); + } + private void initDownload() { - IResource resource = new ResourceStreamResource() { - protected IResourceStream getResourceStream() { - // simulate delay - try - { - TimeUnit.MILLISECONDS.sleep(5000); - } - catch (InterruptedException e) - { - } - - return new StringResourceStream("downloaded via ajax"); - }; - - }.setFileName("File-from-IResource.txt").setContentDisposition(ContentDisposition.ATTACHMENT).setCacheDuration(Duration.NONE); + IResource resource = new ExampleResource("downloaded via ajax") + .setContentDisposition(ContentDisposition.ATTACHMENT); final AjaxDownload download = new AjaxDownload(resource) { @@ -98,6 +94,8 @@ public class AjaxDownloadPage extends BasePage { downloadingContainer.setVisible(false); target.add(downloadingContainer); + + target.appendJavaScript("alert('Download failed');"); } }; add(download); @@ -112,25 +110,17 @@ public class AjaxDownloadPage extends BasePage }); } - private void initDownloadFailure() + private void initDownloadReference() { - IResource resource = new ResourceStreamResource() { - protected IResourceStream getResourceStream() { - // simulate delay - try - { - TimeUnit.MILLISECONDS.sleep(2000); - } - catch (InterruptedException e) - { - } - - throw new AbortWithHttpErrorCodeException(500); - }; - - }.setFileName("file").setContentDisposition(ContentDisposition.ATTACHMENT).setCacheDuration(Duration.NONE); + ResourceReference reference = new ResourceReference("referenceToResource") { + @Override + public IResource getResource() + { + return new StaticResource(); + } + }; - final AjaxDownload download = new AjaxDownload(resource) { + final AjaxDownload download = new AjaxDownload(reference) { @Override protected void onBeforeDownload(AjaxRequestTarget target) @@ -157,7 +147,7 @@ public class AjaxDownloadPage extends BasePage }; add(download); - add(new AjaxLink<Void>("downloadFailure") + add(new AjaxLink<Void>("downloadReference") { @Override public void onClick(AjaxRequestTarget target) @@ -166,19 +156,14 @@ public class AjaxDownloadPage extends BasePage } }); } - - private void initDownloadReference() + + private void initDownloadInNewWindow() { - ResourceReference reference = new ResourceReference("referenceToResource") { - @Override - public IResource getResource() - { - return new StaticResource(); - } - }; - - final AjaxDownload download = new AjaxDownload(reference) { - + IResource resource = new ExampleResource("downloaded via ajax in a new browser window") + .setContentDisposition(ContentDisposition.INLINE); + + final AjaxDownload download = new AjaxDownload(resource) { + @Override protected void onBeforeDownload(AjaxRequestTarget target) { @@ -192,17 +177,27 @@ public class AjaxDownloadPage extends BasePage downloadingContainer.setVisible(false); target.add(downloadingContainer); } - + @Override protected void onDownloadFailed(AjaxRequestTarget target) { downloadingContainer.setVisible(false); target.add(downloadingContainer); + + target.appendJavaScript("alert('Download failed');"); + } + + @Override + protected void onDownloadCompleted(AjaxRequestTarget target) + { + downloadingContainer.setVisible(false); + target.add(downloadingContainer); } }; + download.setLocation(AjaxDownload.Location.NewWindow); add(download); - - add(new AjaxLink<Void>("downloadReference") + + add(new AjaxLink<Void>("downloadInNewWindow") { @Override public void onClick(AjaxRequestTarget target) @@ -212,23 +207,10 @@ public class AjaxDownloadPage extends BasePage }); } - private void initDownloadInNewWindow() + private void initDownloadInSameWindow() { - IResource resource = new ResourceStreamResource() { - protected IResourceStream getResourceStream() { - // simulate delay - try - { - TimeUnit.MILLISECONDS.sleep(5000); - } - catch (InterruptedException e) - { - } - - return new StringResourceStream("downloaded via ajax in a new browser window"); - }; - - }.setFileName("File-from-IResource.txt").setContentDisposition(ContentDisposition.INLINE).setCacheDuration(Duration.NONE); + IResource resource = new ExampleResource("downloaded via ajax in same browser window") + .setContentDisposition(ContentDisposition.ATTACHMENT); final AjaxDownload download = new AjaxDownload(resource) { @@ -251,6 +233,8 @@ public class AjaxDownloadPage extends BasePage { downloadingContainer.setVisible(false); target.add(downloadingContainer); + + target.appendJavaScript("alert('Download failed');"); } @Override @@ -263,7 +247,7 @@ public class AjaxDownloadPage extends BasePage download.setLocation(AjaxDownload.Location.SameWindow); add(download); - add(new AjaxLink<Void>("downloadInNewWindow") + add(new AjaxLink<Void>("downloadInSameWindow") { @Override public void onClick(AjaxRequestTarget target) @@ -290,7 +274,7 @@ public class AjaxDownloadPage extends BasePage } @Override - protected IResourceStream getResourceStream() + protected IResourceStream getResourceStream(Attributes attributes) { // simulate delay try @@ -304,4 +288,40 @@ public class AjaxDownloadPage extends BasePage return new StringResourceStream("downloaded via ajax with resource reference"); } } -} + + private class ExampleResource extends ResourceStreamResource { + + private String content; + + private int count = 0; + + public ExampleResource(String content) + { + this.content = content; + + setFileName("File-from-IResource.txt"); + setCacheDuration(Duration.NONE); + } + + @Override + protected IResourceStream getResourceStream(Attributes attributes) { + // simulate delay + try + { + TimeUnit.MILLISECONDS.sleep(3000); + } + catch (InterruptedException e) + { + } + + count++; + if (count == 3) { + count = 0; + throw new AbortWithHttpErrorCodeException(400); + } + + return new StringResourceStream(content); + }; + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/wicket/blob/39908992/wicket-examples/src/main/webapp/WEB-INF/web.xml ---------------------------------------------------------------------- diff --git a/wicket-examples/src/main/webapp/WEB-INF/web.xml b/wicket-examples/src/main/webapp/WEB-INF/web.xml index e23b1a1..b26c571 100644 --- a/wicket-examples/src/main/webapp/WEB-INF/web.xml +++ b/wicket-examples/src/main/webapp/WEB-INF/web.xml @@ -796,27 +796,6 @@ </filter-mapping> - <!-- CDI EXAMPLE APPLICATION --> - <filter> - <filter-name>CdiApplication</filter-name> - <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class> - <init-param> - <param-name>applicationClassName</param-name> - <param-value>org.apache.wicket.examples.cdi.CdiApplication</param-value> - </init-param> - </filter> - <filter-mapping> - <filter-name>CdiApplication</filter-name> - <url-pattern>/cdi/*</url-pattern> - </filter-mapping> - - <listener> - <!-- initialize Weld in servlet environment --> - <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> - </listener> - <!-- END CDI EXAMPLE APPLICATION --> - - <!-- Bean Validation EXAMPLE APPLICATION --> <filter> <filter-name>BeanValidation</filter-name> http://git-wip-us.apache.org/repos/asf/wicket/blob/39908992/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownload.java ---------------------------------------------------------------------- diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownload.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownload.java index 34595e6..7e6c191 100644 --- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownload.java +++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownload.java @@ -16,16 +16,17 @@ */ package org.apache.wicket.extensions.ajax; +import java.util.Locale; + import javax.annotation.Resource; import javax.servlet.http.Cookie; import org.apache.wicket.Component; -import org.apache.wicket.IResourceListener; +import org.apache.wicket.IRequestListener; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.json.JSONObject; -import org.apache.wicket.ajax.json.JsonFunction; +import org.apache.wicket.ajax.json.JSONFunction; import org.apache.wicket.behavior.Behavior; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.JavaScriptHeaderItem; @@ -34,13 +35,14 @@ import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler; import org.apache.wicket.request.http.WebResponse; import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.request.resource.ContentDisposition; import org.apache.wicket.request.resource.IResource; import org.apache.wicket.request.resource.IResource.Attributes; import org.apache.wicket.request.resource.ResourceReference; import org.apache.wicket.resource.JQueryPluginResourceReference; import org.apache.wicket.util.lang.Args; -import java.util.Locale; +import com.github.openjson.JSONObject; /** * Download resources via Ajax. @@ -69,7 +71,9 @@ public class AjaxDownload extends AbstractDefaultAjaxBehavior public enum Location { /** - * The resource will be downloaded via a temporary created iframe. + * The resource will be downloaded via a temporary created iframe, the resource has to be a + * {@link ContentDisposition#ATTACHMENT}. + * <p> * This is recommended when there are resources in the DOM which will be * closed automatically on JavaScript <em>unload</em> event, like WebSockets. * Supports both <em>success</em> and <em>failure</em> callbacks! @@ -77,18 +81,18 @@ public class AjaxDownload extends AbstractDefaultAjaxBehavior IFrame, /** - * The resource will be downloaded by changing the location of the current DOM document. + * The resource will be downloaded by changing the location of the current DOM document, the resource has to be a + * {@link ContentDisposition#ATTACHMENT}. + * <p> * Note: This will trigger JavaScript <em>unload</em> event on the page! - * Supports only <em>success</em> callback, i.e. it is not possible to detect whether - * the download has finished successfully or not. + * Does not support {@link AjaxDownload#onDownloadFailed(AjaxRequestTarget)} callback, i.e. it is not possible to detect + * when the download has failed! */ SameWindow, /** - * The resource will be downloaded in a new browser window by using JavaScript - * <code>window.open()</code> API. - * Supports only <em>success</em> callback, i.e. it is not possible to detect whether - * the download has finished successfully or not. + * The resource will be downloaded in a new browser window by using JavaScript <code>window.open()</code> API, + * the resource has to be a {@link ContentDisposition#INLINE}. */ NewWindow } @@ -221,7 +225,7 @@ public class AjaxDownload extends AbstractDefaultAjaxBehavior } JSONObject settings = new JSONObject(); - settings.put("attributes", new JsonFunction(renderAjaxAttributes(getComponent()))); + settings.put("attributes", new JSONFunction(renderAjaxAttributes(getComponent()))); settings.put("name", getName()); settings.put("downloadUrl", url); settings.put("method", location.name().toLowerCase(Locale.ENGLISH)); @@ -304,7 +308,7 @@ public class AjaxDownload extends AbstractDefaultAjaxBehavior /** * The behavior responding with the actual resource. */ - private class ResourceBehavior extends Behavior implements IResourceListener + private class ResourceBehavior extends Behavior implements IRequestListener { private final IResource resource; @@ -314,7 +318,13 @@ public class AjaxDownload extends AbstractDefaultAjaxBehavior } @Override - public void onResourceRequested() + public boolean rendersPage() + { + return false; + } + + @Override + public void onRequest() { final RequestCycle requestCycle = RequestCycle.get(); final Response response = requestCycle.getResponse(); @@ -327,7 +337,7 @@ public class AjaxDownload extends AbstractDefaultAjaxBehavior public CharSequence getUrl() { - return getComponent().urlFor(this, IResourceListener.INTERFACE, null); + return getComponent().urlForListener(this, null); } } http://git-wip-us.apache.org/repos/asf/wicket/blob/39908992/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/wicket-ajaxdownload.js ---------------------------------------------------------------------- diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/wicket-ajaxdownload.js b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/wicket-ajaxdownload.js index 26de71e..0c232cf 100644 --- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/wicket-ajaxdownload.js +++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/wicket-ajaxdownload.js @@ -28,35 +28,31 @@ Wicket.AjaxDownload = { initiate : function(settings) { - var notifyServer = function (result) { + var notifyServer = function(result) { settings.attributes.ep = settings.attributes.ep || {}; settings.attributes.ep.result = result; Wicket.Ajax.ajax(settings.attributes); }; - var checkComplete = function (frame) { + var checkComplete = function(watcher) { var result; if (document.cookie.indexOf(settings.name + '=') > -1) { result = "success"; - } else if (frame) { - var html = frame.contents().find('body').html(); + } else { + var html = watcher.html(); if (html && html.length) { result = "failed"; } } if (result) { - if (frame) { - setTimeout(function () { - frame.remove(); - }, 0); - } - + watcher.dismiss(result); + notifyServer(result); } else { setTimeout(function() { - checkComplete(frame); + checkComplete(watcher); }, 100); } }; @@ -64,16 +60,42 @@ if (settings.method === 'samewindow') { setTimeout(function () { window.location.assign(settings.downloadUrl); - checkComplete(); + checkComplete({ + html: function() { + return jQuery(); + }, + + dismiss: function(result) { + } + }); }, 10); } else if (settings.method === 'newwindow') { - var wo = window.open(settings.downloadUrl, 'ajax-download'); - jQuery(wo).load(function(evt) { - notifyServer(undefined); + var wo = window.open(settings.downloadUrl); + checkComplete({ + html: function() { + return jQuery(wo ? wo.document : undefined).find('body').html(); + }, + + dismiss: function(result) { + if (result == "failed") { + wo.close(); + } + } }); } else { var frame = jQuery("<iframe></iframe>").hide().prop("src", settings.downloadUrl).appendTo("body"); - checkComplete(frame); + checkComplete({ + html: function() { + return frame.contents().find('body').html(); + }, + + dismiss: function() { + // don't remove iframe immediately + setTimeout(function () { + frame.remove(); + }, 0); + } + }); } } };