Updated Branches:
  refs/heads/wicket-6.x 84a3b04f3 -> ae9f4fe4a

WICKET-5439 backported from 7.x, but still update the hosting component
on restart as before; WICKET-5464 don't stop onRemove, just clear the
timer

Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/ae9f4fe4
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/ae9f4fe4
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/ae9f4fe4

Branch: refs/heads/wicket-6.x
Commit: ae9f4fe4afddbe9cc8804c7710cb336a2e0d6034
Parents: 84a3b04
Author: svenmeier <[email protected]>
Authored: Wed Jan 8 21:15:06 2014 +0100
Committer: svenmeier <[email protected]>
Committed: Wed Jan 8 21:15:06 2014 +0100

----------------------------------------------------------------------
 .../wicket/ajax/AbstractAjaxTimerBehavior.java  | 107 +++++--
 .../wicket/ajax/AjaxTimerBehaviorTest.java      | 292 +++++++++++--------
 2 files changed, 255 insertions(+), 144 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/ae9f4fe4/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxTimerBehavior.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxTimerBehavior.java
 
b/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxTimerBehavior.java
index f4acfc8..8582f43 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxTimerBehavior.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxTimerBehavior.java
@@ -22,7 +22,6 @@ import org.apache.wicket.core.util.string.JavaScriptUtils;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
 import org.apache.wicket.markup.head.OnLoadHeaderItem;
-import org.apache.wicket.request.http.WebRequest;
 import org.apache.wicket.util.time.Duration;
 
 /**
@@ -43,7 +42,10 @@ public abstract class AbstractAjaxTimerBehavior extends 
AbstractDefaultAjaxBehav
 
        private boolean stopped = false;
 
-       private boolean headRendered = false;
+       /**
+        * Is the timeout present in JavaScript already.
+        */
+       private boolean hasTimeout = false;
 
        /**
         * Construct.
@@ -86,15 +88,19 @@ public abstract class AbstractAjaxTimerBehavior extends 
AbstractDefaultAjaxBehav
        {
                super.renderHead(component, response);
 
-               response.render(JavaScriptHeaderItem.forScript("if 
(typeof(Wicket.TimerHandles) === 'undefined') {Wicket.TimerHandles = {}}",
+               response.render(JavaScriptHeaderItem.forScript(
+                               "if (typeof(Wicket.TimerHandles) === 
'undefined') {Wicket.TimerHandles = {}}",
                                WICKET_TIMERS_ID));
 
-               WebRequest request = (WebRequest) component.getRequest();
+               if (component.getRequestCycle().find(AjaxRequestTarget.class) 
== null)
+               {
+                       // complete page is rendered, so timeout has to be 
rendered again
+                       hasTimeout = false;
+               }
 
-               if (!isStopped() && (!headRendered || !request.isAjax()))
+               if (isStopped() == false)
                {
-                       headRendered = true;
-                       
response.render(OnLoadHeaderItem.forScript(getJsTimeoutCall(updateInterval)));
+                       addTimeout(response);
                }
        }
 
@@ -134,10 +140,16 @@ public abstract class AbstractAjaxTimerBehavior extends 
AbstractDefaultAjaxBehav
 
                        if (shouldTrigger())
                        {
-                               target.getHeaderResponse().render(
-                                       
OnLoadHeaderItem.forScript(getJsTimeoutCall(updateInterval)));
+                               // re-add timeout
+                               hasTimeout = false;
+
+                               addTimeout(target.getHeaderResponse());
+
+                               return;
                        }
                }
+
+               clearTimeout(target.getHeaderResponse());
        }
 
        /**
@@ -172,29 +184,77 @@ public abstract class AbstractAjaxTimerBehavior extends 
AbstractDefaultAjaxBehav
 
        /**
         * Re-enables the timer if already stopped
-        *
+        * 
         * @param target
+        *            may be null
         */
        public final void restart(final AjaxRequestTarget target)
        {
-               if (isStopped())
+               if (stopped == true)
                {
                        stopped = false;
-                       headRendered = false;
-                       target.add(getComponent());
+
+                       if (target != null)
+                       {
+                               addTimeout(target.getHeaderResponse());
+
+                               onRestart(target);
+                       }
+               }
+       }
+
+       /**
+        * Called when this timer is restarted  adds this component to the 
target on
+        * restart. <br>
+        * Note: This method will be removed in Wicket 7.x, thus the hosting
+        * component will no longer be updated on each restart.
+        * 
+        * @param target
+        *            current target
+        */
+       protected void onRestart(AjaxRequestTarget target)
+       {
+               target.add(getComponent());
+       }
+
+       private void addTimeout(IHeaderResponse headerResponse)
+       {
+               if (hasTimeout == false)
+               {
+                       hasTimeout = true;
+
+                       
headerResponse.render(OnLoadHeaderItem.forScript(getJsTimeoutCall(updateInterval)));
+               }
+       }
+
+       private void clearTimeout(IHeaderResponse headerResponse)
+       {
+               if (hasTimeout)
+               {
+                       hasTimeout = false;
+
+                       String timeoutHandle = getTimeoutHandle();
+                       
headerResponse.render(OnLoadHeaderItem.forScript("clearTimeout(" + timeoutHandle
+                                       + "); delete " + timeoutHandle + ";"));
                }
        }
 
        /**
-        * Stops the timer
+        * Stops the timer.
+        * 
+        * @param target
+        *            may be null
         */
        public final void stop(final AjaxRequestTarget target)
        {
-               if (headRendered && stopped == false)
+               if (stopped == false)
                {
                        stopped = true;
-                       String timeoutHandle = getTimeoutHandle();
-                       
target.prependJavaScript("clearTimeout("+timeoutHandle+"); delete 
"+timeoutHandle+";");
+
+                       if (target != null)
+                       {
+                               clearTimeout(target.getHeaderResponse());
+                       }
                }
        }
 
@@ -204,8 +264,17 @@ public abstract class AbstractAjaxTimerBehavior extends 
AbstractDefaultAjaxBehav
                AjaxRequestTarget target = 
component.getRequestCycle().find(AjaxRequestTarget.class);
                if (target != null)
                {
-                       stop(target);
+                       clearTimeout(target.getHeaderResponse());
+               }
+       }
+
+       @Override
+       protected void onUnbind()
+       {
+               AjaxRequestTarget target = 
getComponent().getRequestCycle().find(AjaxRequestTarget.class);
+               if (target != null)
+               {
+                       clearTimeout(target.getHeaderResponse());
                }
-               super.detach(component);
        }
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/ae9f4fe4/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxTimerBehaviorTest.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxTimerBehaviorTest.java 
b/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxTimerBehaviorTest.java
index 351c149..8adb45d 100644
--- 
a/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxTimerBehaviorTest.java
+++ 
b/wicket-core/src/test/java/org/apache/wicket/ajax/AjaxTimerBehaviorTest.java
@@ -16,9 +16,7 @@
  */
 package org.apache.wicket.ajax;
 
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
+import org.apache.wicket.Component;
 import org.apache.wicket.MockPageWithLinkAndComponent;
 import org.apache.wicket.WicketTestCase;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
@@ -47,13 +45,14 @@ public class AjaxTimerBehaviorTest extends WicketTestCase
         * Tests timer behavior in a component added to an AjaxRequestTarget
         */
        @Test
-       public void addToAjaxUpdate()
+       public void addedInAjaxSetsTimout()
        {
                Duration dur = Duration.seconds(20);
-               final MyAjaxSelfUpdatingTimerBehavior timer = new 
MyAjaxSelfUpdatingTimerBehavior(dur);
+               final AjaxSelfUpdatingTimerBehavior timer = new 
AjaxSelfUpdatingTimerBehavior(dur);
                final MockPageWithLinkAndComponent page = new 
MockPageWithLinkAndComponent();
 
-               page.add(new 
WebComponent(MockPageWithLinkAndComponent.COMPONENT_ID).setOutputMarkupId(true));
+               page.add(new 
WebComponent(MockPageWithLinkAndComponent.COMPONENT_ID)
+                               .setOutputMarkupId(true));
 
 
                page.add(new 
AjaxLink<Void>(MockPageWithLinkAndComponent.LINK_ID)
@@ -75,8 +74,12 @@ public class AjaxTimerBehaviorTest extends WicketTestCase
                tester.startPage(page);
                tester.clickLink(MockPageWithLinkAndComponent.LINK_ID);
 
-               validate(timer, false);
+               // first render sets timeout
+               assertMatches("setTimeout", 1);
+
+               tester.executeBehavior(timer);
 
+               assertMatches("setTimeout", 1);
        }
 
 
@@ -84,10 +87,10 @@ public class AjaxTimerBehaviorTest extends WicketTestCase
         * tests timer behavior in a WebPage.
         */
        @Test
-       public void addToWebPage()
+       public void pageRenderSetsTimeout()
        {
                Duration dur = Duration.seconds(20);
-               final MyAjaxSelfUpdatingTimerBehavior timer = new 
MyAjaxSelfUpdatingTimerBehavior(dur);
+               final AjaxSelfUpdatingTimerBehavior timer = new 
AjaxSelfUpdatingTimerBehavior(dur);
                final MockPageWithLinkAndComponent page = new 
MockPageWithLinkAndComponent();
                Label label = new 
Label(MockPageWithLinkAndComponent.COMPONENT_ID, "Hello");
                page.add(label);
@@ -106,21 +109,150 @@ public class AjaxTimerBehaviorTest extends WicketTestCase
 
                tester.startPage(page);
 
-               validate(timer, true);
+               assertMatches("setTimeout", 1);
+
+               tester.clickLink(MockPageWithLinkAndComponent.LINK_ID);
+
+               assertMatches("setTimeout", 1);
+
+               tester.executeBehavior(timer);
+
+               assertMatches("setTimeout", 1);
+       }
+
+       /**
+        * tests timer behavior in a WebPage.
+        */
+       @Test
+       public void ajaxUpdateDoesNotSetTimeout()
+       {
+               Duration dur = Duration.seconds(20);
+               final AjaxSelfUpdatingTimerBehavior timer = new 
AjaxSelfUpdatingTimerBehavior(dur);
+               final MockPageWithLinkAndComponent page = new 
MockPageWithLinkAndComponent();
+               final Label label = new 
Label(MockPageWithLinkAndComponent.COMPONENT_ID, "Hello");
+               page.add(label);
+               page.add(new 
AjaxLink<Void>(MockPageWithLinkAndComponent.LINK_ID)
+               {
+                       private static final long serialVersionUID = 1L;
+
+                       @Override
+                       public void onClick(AjaxRequestTarget target)
+                       {
+                               target.add(label);
+                       }
+               });
+               label.setOutputMarkupId(true);
+               label.add(timer);
+
+               tester.startPage(page);
+
+               assertMatches("setTimeout", 1);
+
+               tester.clickLink(MockPageWithLinkAndComponent.LINK_ID);
+
+               // ajax update does not set timeout
+               assertMatches("setTimeout", 0);
+
+               tester.executeBehavior(timer);
+
+               assertMatches("setTimeout", 1);
+       }
+
+
+       /**
+        */
+       @Test
+       public void setVisibleSetsTimeout()
+       {
+               Duration dur = Duration.seconds(20);
+               final AjaxSelfUpdatingTimerBehavior timer = new 
AjaxSelfUpdatingTimerBehavior(dur);
+               final MockPageWithLinkAndComponent page = new 
MockPageWithLinkAndComponent();
+               final Label label = new 
Label(MockPageWithLinkAndComponent.COMPONENT_ID, "Hello");
+               page.add(label);
+               page.add(new 
AjaxLink<Void>(MockPageWithLinkAndComponent.LINK_ID)
+               {
+                       private static final long serialVersionUID = 1L;
+
+                       @Override
+                       public void onClick(AjaxRequestTarget target)
+                       {
+                       }
+               });
+               label.setOutputMarkupId(true);
+               label.setVisible(false);
+               label.add(timer);
+
+               tester.startPage(page);
+
+               assertMatches("setTimeout", 0);
 
                tester.clickLink(MockPageWithLinkAndComponent.LINK_ID);
 
-               validate(timer, true);
+               assertMatches("setTimeout", 0);
+
+               label.setVisible(true);
 
+               tester.startPage(page);
+
+               // no visible, so timeout is set
+               assertMatches("setTimeout", 1);
        }
 
        /**
-        * Validates the response, then makes sure the timer injects itself 
again when called.
-        * Tests {@link AbstractAjaxTimerBehavior#restart(AjaxRequestTarget)} 
method
+        */
+       @Test
+       public void setDisabledClearsTimeout()
+       {
+               final AbstractAjaxTimerBehavior timer = new 
AbstractAjaxTimerBehavior(Duration.seconds(20))
+               {
+                       private boolean enabled = true;
 
+                       @Override
+                       protected void onTimer(AjaxRequestTarget target)
+                       {
+                               enabled = false;
+                       }
+
+                       @Override
+                       public boolean isEnabled(Component component)
+                       {
+                               return enabled;
+                       }
+               };
+               final MockPageWithLinkAndComponent page = new 
MockPageWithLinkAndComponent();
+               final Label label = new 
Label(MockPageWithLinkAndComponent.COMPONENT_ID, "Hello");
+               page.add(label);
+               page.add(new Link<Void>(MockPageWithLinkAndComponent.LINK_ID)
+               {
+                       private static final long serialVersionUID = 1L;
+
+                       @Override
+                       public void onClick()
+                       {
+                       }
+               });
+               label.setOutputMarkupId(true);
+               label.add(timer);
+
+               tester.startPage(page);
+
+               assertMatches("setTimeout", 1);
+
+               tester.executeBehavior(timer);
+
+               assertMatches("clearTimeout", 1);
+               assertMatches("setTimeout", 0);
+       }
+
+       /**
+        * Validates the response, then makes sure the timer injects itself 
again
+        * when called. Tests
+        * {@link AbstractAjaxTimerBehavior#restart(AjaxRequestTarget)} method
+        * 
         * WICKET-1525, WICKET-2152
         */
-       public void testRestartMethod()
+       @Test
+       public void restartResultsInAddTimeout()
        {
                final Integer labelInitialValue = Integer.valueOf(0);
 
@@ -190,6 +322,11 @@ public class AjaxTimerBehaviorTest extends WicketTestCase
                // restart the timer
                tester.clickLink(MockPageWithLinkAndComponent.LINK_ID);
 
+               assertMatches("setTimeout", 1);
+               // label is updated automatically (this will no longer be the 
case in
+               // Wicket 7.x)
+               assertMatches("wicket:id=\"component\"", 1);
+
                // increment to 2
                tester.executeBehavior(timerBehavior);
 
@@ -198,128 +335,33 @@ public class AjaxTimerBehaviorTest extends WicketTestCase
        }
 
        /**
-        * Validates the reponse, then makes sure the timer injects itself 
again when called.
+        * Validates the reponse, then makes sure the timer injects itself again
+        * when called.
         * 
         * @param timer
-        * @param inBodyOnLoad
+        * @param wasAjax
         */
-       private void validate(MyAjaxSelfUpdatingTimerBehavior timer, boolean 
inBodyOnLoad)
+       private void assertMatches(String string, int count)
        {
                String document = tester.getLastResponseAsString();
 
-               String updateScript = timer.getUpdateScript();
-
-               if (inBodyOnLoad)
-               {
-                       String bodyOnLoadUpdateScript = 
"Wicket.Event.add(window, \"load\", function(event) { \n" +
-                               updateScript + ";\n;});";
-                       validateTimerScript(document, bodyOnLoadUpdateScript);
-               }
-               else
-               {
-                       updateScript = updateScript.replaceAll("]", "]^");
-                       validateTimerScript(document, updateScript);
-               }
-
-               tester.executeBehavior(timer);
-
-               if (inBodyOnLoad)
-               {
-                       updateScript = timer.getUpdateScript();
-                       updateScript = updateScript.replaceAll("]", "]^");
-               }
-
-               // Validate the document
-               document = tester.getLastResponseAsString();
-               validateTimerScript(document, updateScript);
-       }
-
-       /**
-        * Checks that the timer javascript is in the document once and only 
once
-        * 
-        * @param document
-        *            the response from the Application
-        * @param updateScript
-        *            the timer script
-        */
-       private void validateTimerScript(String document, String updateScript)
-       {
                log.debug(document);
-               String quotedRegex;
-               quotedRegex = quote(updateScript);
-               Pattern pat = Pattern.compile(quotedRegex, Pattern.DOTALL);
-               Matcher mat = pat.matcher(document);
 
-               int count = 0;
-               while (mat.find())
+               int found = 0;
+               int lastIndex = 0;
+               while (true)
                {
-                       ++count;
-               }
-               // make sure there is only one match
-               assertEquals("There should be 1 and only 1 script in the markup 
for this behavior," +
-                       "but " + count + " were found", 1, count);
-       }
+                       lastIndex = document.indexOf(string, lastIndex);
 
-       // quick fix for JDK 5 method
-       private static final String quote(String s)
-       {
-               int slashEIndex = s.indexOf("\\E");
-               if (slashEIndex == -1)
-               {
-                       return "\\Q" + s + "\\E";
-               }
-
-               StringBuilder sb = new StringBuilder(s.length() * 2);
-               sb.append("\\Q");
-               slashEIndex = 0;
-               int current = 0;
-               while ((slashEIndex = s.indexOf("\\E", current)) != -1)
-               {
-                       sb.append(s.substring(current, slashEIndex));
-                       current = slashEIndex + 2;
-                       sb.append("\\E\\\\E\\Q");
-               }
-               sb.append(s.substring(current, s.length()));
-               sb.append("\\E");
-               return sb.toString();
-       }
-
-       static class MyAjaxSelfUpdatingTimerBehavior extends 
AjaxSelfUpdatingTimerBehavior
-       {
-
-               /**
-                * 
-                */
-               private static final long serialVersionUID = 1L;
-               private final Duration duration;
-               String updateScript;
-
-               /**
-                * Construct.
-                * 
-                * @param updateInterval
-                */
-               public MyAjaxSelfUpdatingTimerBehavior(Duration updateInterval)
-               {
-                       super(updateInterval);
-                       duration = updateInterval;
-               }
-
-               @Override
-               protected void onComponentRendered()
-               {
-                       super.onComponentRendered();
-                       updateScript = getJsTimeoutCall(duration);
-               }
+                       if (lastIndex == -1)
+                       {
+                               break;
+                       }
 
-               /**
-                * @return Update script
-                */
-               public String getUpdateScript()
-               {
-                       return updateScript;
+                       found++;
+                       lastIndex += string.length();
                }
 
-
+               assertEquals(count, found);
        }
-}
+}
\ No newline at end of file

Reply via email to