You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by sv...@apache.org on 2014/01/08 21:15:39 UTC

git commit: 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

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 <sv...@meiers.net>
Authored: Wed Jan 8 21:15:06 2014 +0100
Committer: svenmeier <sv...@meiers.net>
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