This is an automated email from the ASF dual-hosted git repository.

svenmeier pushed a commit to branch wicket-9.x
in repository https://gitbox.apache.org/repos/asf/wicket.git


The following commit(s) were added to refs/heads/wicket-9.x by this push:
     new 23c1584  WICKET-6902 allow prepend and append
23c1584 is described below

commit 23c1584636d374ee380a8f5b9fb25aef969ee3f8
Author: Sven Meier <svenme...@apache.org>
AuthorDate: Sat Jul 17 00:18:02 2021 +0200

    WICKET-6902 allow prepend and append
    
    up-to including #onAfterRespond()
---
 .../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 | 58 ++++++++++++++++------
 4 files changed, 98 insertions(+), 39 deletions(-)

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 -&gt; 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-&gt;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-&gt;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..f2c1236 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;
@@ -260,20 +264,24 @@ class AjaxRequestHandlerTest extends WicketTestCase
        }
 
        /**
-        * @see <a 
href="https://issues.apache.org/jira/browse/WICKET-3263";>WICKET-3263</a>
+        * WICKET-3263<br>
+        * WICKET-6902
         */
        @Test
        void globalAjaxRequestTargetListeners()
        {
-               final ValidatingAjaxRequestTargetListener listener = new 
ValidatingAjaxRequestTargetListener();
-
+               JavaScriptPrependerAppender listener = new 
JavaScriptPrependerAppender();
+               
                
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 +404,43 @@ class AjaxRequestHandlerTest extends WicketTestCase
                }
        }
 
-       private static class ValidatingAjaxRequestTargetListener implements 
AjaxRequestTarget.IListener
+       /**
+        * Listener to AjaxRequestTarget and RequestCycle to test prepending 
and appending of
+        * JavaScript.  
+        */
+       private static class JavaScriptPrependerAppender 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("appendJavaScript should not be 
allowed at this state");
+                               } catch (IllegalStateException 
javascriptFrozen) {
+                               }
+
+                               try {
+                                       ((AjaxRequestHandler) 
handler).prependJavaScript("FAIL");
+                                       
+                                       fail("prependJavaScript should not be 
allowed at this state");
+                               } catch (IllegalStateException 
javascriptFrozen) {
+                               }
+                       }
                }
        }
 

Reply via email to