This is an automated email from the ASF dual-hosted git repository. svenmeier pushed a commit to branch WICKET-6902-js-after-components in repository https://gitbox.apache.org/repos/asf/wicket.git
commit 1f2064274c8c5385e66a71ff3445bdf84871561a Author: Sven Meier <[email protected]> AuthorDate: Sat Jul 17 00:18:02 2021 +0200 WICKET-6902 allow prepend and append up-to including #onAfterRespond() --- pom.xml | 5 +++ .../org/apache/wicket/ajax/AjaxRequestHandler.java | 12 +----- .../org/apache/wicket/ajax/AjaxRequestTarget.java | 45 ++++++++++++++++------ .../org/apache/wicket/page/PartialPageUpdate.java | 22 ++++++++++- .../apache/wicket/ajax/AjaxRequestHandlerTest.java | 44 ++++++++++++++------- 5 files changed, 90 insertions(+), 38 deletions(-) diff --git a/pom.xml b/pom.xml index eb5088a..241d0a5 100644 --- a/pom.xml +++ b/pom.xml @@ -1153,6 +1153,11 @@ <className>org/apache/wicket/pageStore/IPageStore</className> <method>void end(org.apache.wicket.pageStore.IPageContext)</method> </difference> + <difference> + <differenceType>7012</differenceType> + <className>org/apache/wicket/ajax/AjaxRequestTarget$IListener</className> + <method>void onAfterRespond(java.util.Map, org.apache.wicket.ajax.AjaxRequestTarget)</method> + </difference> </ignored> </configuration> <executions> diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java index 78699bf..fd54daa 100644 --- a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java +++ b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestHandler.java @@ -145,19 +145,9 @@ public class AjaxRequestHandler extends AbstractPartialPageRequestHandler implem final Map<String, Component> components = Collections .unmodifiableMap(markupIdToComponent); - // create response that will be used by listeners to append javascript - final AjaxRequestTarget.IJavaScriptResponse jsresponse = new AjaxRequestTarget.IJavaScriptResponse() - { - @Override - public void addJavaScript(String script) - { - writeEvaluations(response, Collections.<CharSequence> singleton(script)); - } - }; - for (AjaxRequestTarget.IListener listener : listeners) { - listener.onAfterRespond(components, jsresponse); + listener.onAfterRespond(components, AjaxRequestHandler.this); } } } diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestTarget.java b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestTarget.java index 6c874dc..2e1efb6 100644 --- a/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestTarget.java +++ b/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxRequestTarget.java @@ -38,35 +38,54 @@ public interface AjaxRequestTarget extends IPartialPageRequestHandler, ILoggable interface IListener { /** - * Triggered before ajax request target begins its response cycle + * Triggered before the target begins writing components. * * @param map * modifiable map (markupId -> component) of components already added to the target * @param target * the target itself. Could be used to add components or to append/prepend - * javascript + * JavaScript * */ default void onBeforeRespond(Map<String, Component> map, AjaxRequestTarget target) {} /** - * Triggered after ajax request target is done with its response cycle. At this point only - * additional javascript can be output to the response using the provided - * {@link AjaxRequestTarget.IJavaScriptResponse} object + * Triggered after the target has written components. At this point only + * additional JavaScript can be added to the response. * - * NOTE: During this stage of processing any calls to target that manipulate the response - * (adding components, javascript) will have no effect + * NOTE: During this stage of processing any calls that manipulate components will result in + * an exception. * * @param map * read-only map:markupId->component of components already added to the target * @param response - * response object that can be used to output javascript + * response object that can be used to output JavaScript + * + * @deprecated implement {@link #onAfterRespond(Map, AjaxRequestTarget)} instead */ + @Deprecated default void onAfterRespond(Map<String, Component> map, AjaxRequestTarget.IJavaScriptResponse response) {} /** + * Triggered after the target has written components. At this point only + * additional JavaScript can be added to the response. + * + * NOTE: During this stage of processing any calls that manipulate components will result in + * an exception. After notification of all listeners no JavaScript can be added any longer. + * + * @param map + * read-only map:markupId->component of components already added to the target + * @param target + * the target itself. Could be used to append/prepend JavaScript + */ + default void onAfterRespond(Map<String, Component> map, AjaxRequestTarget target) + { + onAfterRespond(map, script -> target.appendJavaScript(script)); + } + + /** * Triggered for every Ajax behavior. Can be used to configure common settings. * * @param behavior @@ -80,19 +99,23 @@ public interface AjaxRequestTarget extends IPartialPageRequestHandler, ILoggable } /** - * An ajax javascript response that allows users to add javascript to be executed on the client + * An ajax JavaScript response that allows users to add JavaScript to be executed on the client * side * * @author ivaynberg + * + * @deprecated use {@link AjaxRequestTargetprependJavaScript(CharSequence)} and + * {@link AjaxRequestTarget#appendJavaScript(CharSequence)} instead */ + @Deprecated @FunctionalInterface interface IJavaScriptResponse { /** - * Adds more javascript to the ajax response that will be executed on the client side + * Adds more JavaScript to the ajax response that will be executed on the client side * * @param script - * javascript + * JavaScript */ void addJavaScript(String script); } diff --git a/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java b/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java index 1712dc8..f95c959 100644 --- a/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java +++ b/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java @@ -104,6 +104,12 @@ public abstract class PartialPageUpdate protected transient boolean componentsFrozen; /** + * A flag that indicates that javascripts cannot be added anymore. + * See https://issues.apache.org/jira/browse/WICKET-6902 + */ + protected transient boolean javascriptsFrozen; + + /** * Buffer of response body. */ protected final ResponseBuffer bodyBuffer; @@ -161,12 +167,14 @@ public abstract class PartialPageUpdate // process added components writeComponents(response, encoding); + onAfterRespond(response); + + javascriptsFrozen = true; + // queue up prepend javascripts. unlike other steps these are executed out of order so that // components can contribute them from during rendering. writePriorityEvaluations(response, prependJavaScripts); - onAfterRespond(response); - // execute the dom ready javascripts as first javascripts // after component replacement List<CharSequence> evaluationScripts = new ArrayList<>(); @@ -493,6 +501,11 @@ public abstract class PartialPageUpdate { Args.notNull(javascript, "javascript"); + if (javascriptsFrozen) + { + throw new IllegalStateException("A partial update of the page is being rendered, JavaScript can no longer be added"); + } + appendJavaScripts.add(javascript); } @@ -505,6 +518,11 @@ public abstract class PartialPageUpdate public final void prependJavaScript(CharSequence javascript) { Args.notNull(javascript, "javascript"); + + if (javascriptsFrozen) + { + throw new IllegalStateException("A partial update of the page is being rendered, JavaScript can no longer be added"); + } prependJavaScripts.add(javascript); } diff --git a/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxRequestHandlerTest.java b/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxRequestHandlerTest.java index 66cc73d..7a83db4 100644 --- a/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxRequestHandlerTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxRequestHandlerTest.java @@ -21,14 +21,15 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; + import java.io.IOException; import java.lang.reflect.Constructor; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; + import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; import org.apache.wicket.MockPageWithLink; @@ -38,6 +39,9 @@ import org.apache.wicket.event.IEvent; import org.apache.wicket.markup.IMarkupResourceStreamProvider; import org.apache.wicket.markup.html.WebComponent; import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.request.IRequestHandler; +import org.apache.wicket.request.cycle.IRequestCycleListener; +import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.util.encoding.UrlEncoder; import org.apache.wicket.util.resource.IResourceStream; import org.apache.wicket.util.resource.StringResourceStream; @@ -265,15 +269,18 @@ class AjaxRequestHandlerTest extends WicketTestCase @Test void globalAjaxRequestTargetListeners() { - final ValidatingAjaxRequestTargetListener listener = new ValidatingAjaxRequestTargetListener(); - + ValidatingListener listener = new ValidatingListener(); + tester.getApplication().getAjaxRequestTargetListeners().add(listener); + tester.getApplication().getRequestCycleListeners().add(listener); tester.startPage(TestEventPage.class); tester.clickLink(MockPageWithLinkAndComponent.LINK_ID, true); - assertTrue(listener.onBeforeRespondExecuted); - assertTrue(listener.onAfterRespondExecuted); + tester.assertContains("BEFORE_RESPOND_PREPEND"); + tester.assertContains("BEFORE_RESPOND_APPEND"); + tester.assertContains("AFTER_RESPOND_PREPEND"); + tester.assertContains("AFTER_RESPOND_APPEND"); } /** @@ -396,23 +403,32 @@ class AjaxRequestHandlerTest extends WicketTestCase } } - private static class ValidatingAjaxRequestTargetListener implements AjaxRequestTarget.IListener + private static class ValidatingListener implements AjaxRequestTarget.IListener, IRequestCycleListener { - boolean onBeforeRespondExecuted = false; - boolean onAfterRespondExecuted = false; - @Override public void onBeforeRespond(Map<String, Component> map, AjaxRequestTarget target) { - onBeforeRespondExecuted = true; - + target.prependJavaScript("BEFORE_RESPOND_PREPEND"); + target.appendJavaScript("BEFORE_RESPOND_APPEND"); } @Override - public void onAfterRespond(Map<String, Component> map, - AjaxRequestTarget.IJavaScriptResponse response) + public void onAfterRespond(Map<String, Component> map, AjaxRequestTarget target) { - onAfterRespondExecuted = true; + target.prependJavaScript("AFTER_RESPOND_PREPEND"); + target.appendJavaScript("AFTER_RESPOND_APPEND"); + } + + @Override + public void onRequestHandlerExecuted(RequestCycle cycle, IRequestHandler handler) { + if (handler instanceof AjaxRequestHandler) { + try { + ((AjaxRequestHandler) handler).appendJavaScript("FAIL"); + + fail(); + } catch (IllegalStateException javascriptFrozen) { + } + } } }
