You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by kn...@apache.org on 2008/09/02 02:23:21 UTC

svn commit: r691085 - in /wicket/sandbox/knopp/experimental: wicket-examples/src/main/java/org/apache/wicket/ajax/ wicket/src/main/java/org/apache/wicket/ajaxng/ wicket/src/main/java/org/apache/wicket/ajaxng/form/ wicket/src/main/java/org/apache/wicket...

Author: knopp
Date: Mon Sep  1 17:23:20 2008
New Revision: 691085

URL: http://svn.apache.org/viewvc?rev=691085&view=rev
Log:
much easier customization

Added:
    wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/form/
    wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/form/AjaxFormSubmitBehavior.java   (with props)
Modified:
    wicket/sandbox/knopp/experimental/wicket-examples/src/main/java/org/apache/wicket/ajax/TestPage1.java
    wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxBehavior.java
    wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxEventBehavior.java
    wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxRequestAttributes.java
    wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxTimerBehavior.java
    wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/markup/html/AjaxLink.java

Modified: wicket/sandbox/knopp/experimental/wicket-examples/src/main/java/org/apache/wicket/ajax/TestPage1.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket-examples/src/main/java/org/apache/wicket/ajax/TestPage1.java?rev=691085&r1=691084&r2=691085&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket-examples/src/main/java/org/apache/wicket/ajax/TestPage1.java (original)
+++ wicket/sandbox/knopp/experimental/wicket-examples/src/main/java/org/apache/wicket/ajax/TestPage1.java Mon Sep  1 17:23:20 2008
@@ -16,15 +16,9 @@
  */
 package org.apache.wicket.ajax;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import org.apache.wicket.ajaxng.AjaxEventBehavior;
-import org.apache.wicket.ajaxng.AjaxRequestAttributes;
-import org.apache.wicket.ajaxng.AjaxRequestAttributesImpl;
-import org.apache.wicket.ajaxng.FunctionList;
-import org.apache.wicket.ajaxng.request.AjaxRequestTarget;
-import org.apache.wicket.ajaxng.request.AjaxRequestTarget.ComponentEntry;
+import org.apache.wicket.ajaxng.AjaxRequestTarget;
+import org.apache.wicket.ajaxng.AjaxRequestTarget.ComponentEntry;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.WebPage;
 
@@ -42,66 +36,9 @@
 		final WebMarkupContainer c1 = new WebMarkupContainer("c1");
 		c1.add(new AjaxEventBehavior("click")
 		{
-			/**
-			 * @see org.apache.wicket.ajaxng.AjaxBehavior#getAttributes()
-			 */
-			@Override
-			public AjaxRequestAttributes getAttributes()
-			{
-				if (true) {
-					return super.getAttributes();					
-				}
-				return new AjaxRequestAttributesImpl(super.getAttributes())
-				{
-					/**
-					 * @see org.apache.wicket.ajaxng.AjaxRequestAttributesImpl#getUrlArguments()
-					 */
-					@Override
-					public Map<String, Object> getUrlArguments()
-					{
-						Map<String, Object> args = new HashMap<String, Object>();
-						
-						args.put("key 1", "value\n\t1");
-						
-						return args;
-					}
-					/**
-					 * @see org.apache.wicket.ajaxng.AjaxRequestAttributesImpl#getBeforeHandlers()
-					 */
-					@Override
-					public FunctionList getBeforeHandlers()
-					{
-						return super.getBeforeHandlers().add("function(i) { W.Log.debug('before!'); }").add(0, "function(i) { W.Log.debug('b!'); }");
-					}
-					/**
-					 * @see org.apache.wicket.ajaxng.AjaxRequestAttributesImpl#getSuccessHandlers()
-					 */
-					@Override
-					public FunctionList getSuccessHandlers()
-					{
-						return super.getSuccessHandlers().add("function(i) { W.Log.debug('after!'); }");
-					}
-					/**
-					 * @see org.apache.wicket.ajaxng.AjaxRequestAttributesImpl#getPreconditions()
-					 */
-					@Override
-					public FunctionList getPreconditions()
-					{
-						return super.getPreconditions().add("function(i) { return true;}");
-					}
-					/**
-					 * @see org.apache.wicket.ajaxng.AjaxRequestAttributesImpl#getUrlArgumentMethods()
-					 */
-					@Override
-					public FunctionList getUrlArgumentMethods()
-					{
-						return super.getUrlArgumentMethods().add("function(i) { return { x:i.event.clientX,y:i.event.clientY }; }");
-					}
-				};
-			}
 			
 			/**
-			 * @see org.apache.wicket.ajaxng.AjaxBehavior#respond(org.apache.wicket.ajaxng.request.AjaxRequestTarget)
+			 * @see org.apache.wicket.ajaxng.AjaxBehavior#respond(org.apache.wicket.ajaxng.AjaxRequestTarget)
 			 */
 			@Override
 			public void onEvent(AjaxRequestTarget target)
@@ -122,11 +59,11 @@
 //			 * @see org.apache.wicket.ajax.AjaxEventBehavior#onEvent(org.apache.wicket.ajax.AjaxRequestTarget)
 //			 */
 //			@Override
-//			protected void onEvent(AjaxRequestTarget target)
+//			protected void onEvent(org.apache.wicket.ajax.AjaxRequestTarget target)
 //			{
 //			}
 //		});
-//		
+		
 	}		
 
 }

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxBehavior.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxBehavior.java?rev=691085&r1=691084&r2=691085&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxBehavior.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxBehavior.java Mon Sep  1 17:23:20 2008
@@ -33,6 +33,7 @@
 import org.apache.wicket.behavior.IBehavior;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.html.IHeaderResponse;
+import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.resources.JavascriptResourceReference;
 import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
 
@@ -229,12 +230,18 @@
 
 		o.put("b", behaviorIndex);
 
-		renderAttributes(component, getAttributes(), o);
+		renderAttributes(component, getAttributes(component), o);
 
 		if (allowAjaxIndicator())
 		{
-			o.put("i", findIndicatorId(component));	
-		}		
+			o.put("i", findIndicatorId(component));
+		}
+
+		Form<?> form = getForm(component);
+		if (form != null)
+		{
+			o.put("f", form.getMarkupId());
+		}
 
 		postprocessConfiguration(o, component);
 
@@ -285,9 +292,9 @@
 		}
 	}
 
-	private Object renderBoolean(Boolean b)
+	private Object renderBoolean(boolean b)
 	{
-		if (b != null && b == true)
+		if (b == true)
 		{
 			return 1;
 		}
@@ -300,13 +307,9 @@
 	private void renderAttributes(Component component, AjaxRequestAttributes attributes,
 		JSONObject o)
 	{
-		if (attributes.getForm() != null)
-		{
-			o.put("f", attributes.getForm().getMarkupId());
-		}
 		o.put("m", renderBoolean(attributes.isMultipart()));
 		o.put("fp", renderBoolean(attributes.isForcePost()));
-		o.put("rt", attributes.getRequesTimeout());
+		o.put("rt", attributes.getRequestTimeout());
 		o.put("pt", attributes.getProcessingTimeout());
 		o.put("t", attributes.getToken());
 		o.put("r", renderBoolean(attributes.isRemovePrevious()));
@@ -327,6 +330,7 @@
 			{
 				args.put(s, urlArguments.get(s));
 			}
+			o.put("u", args);
 		}
 
 		renderFunctionList(o, "ua", attributes.getUrlArgumentMethods());
@@ -337,6 +341,18 @@
 
 	}
 
+	/**
+	 * Form instance if the AJAX request should submit a form or <code>null</code> if the request
+	 * doesn't involve form submission.
+	 * 
+	 * @param component
+	 * @return form instance or <code>null</code>
+	 */
+	protected Form<?> getForm(Component component)
+	{
+		return null;
+	}
+
 	public void detach(Component component)
 	{
 	}
@@ -368,11 +384,14 @@
 	 * Utility function to decorate javascript.
 	 * 
 	 * @param script
+	 * @param component
+	 *            component for which the script is being rendered
+	 * 
 	 * @return decorated javacsript
 	 */
-	public CharSequence decorateScript(CharSequence script)
+	public CharSequence decorateScript(CharSequence script, Component component)
 	{
-		ChainingList<ExpressionDecorator> decoratorList = getAttributes().getExpressionDecorators();
+		ChainingList<ExpressionDecorator> decoratorList = getAttributes(component).getExpressionDecorators();
 		if (decoratorList != null)
 		{
 			for (ExpressionDecorator d : decoratorList)
@@ -384,24 +403,23 @@
 	}
 
 	/**
-	 * Creates {@link AjaxRequestAttributes} instance. If behavior needs to change the behaviors,
-	 * this is the method to override and wrap the attributes.
-	 * 
-	 * @return {@link AjaxRequestAttributes} instance.
-	 */
-	public AjaxRequestAttributes initAttributes()
-	{
-		return new AjaxRequestAttributes();
-	}
-
-	/**
 	 * Returns attributes for Ajax Request.
 	 * 
+	 * @param component
+	 * 
 	 * @return {@link AjaxRequestAttributes} instance
 	 */
-	public AjaxRequestAttributes getAttributes()
+	public final AjaxRequestAttributes getAttributes(Component component)
 	{
-		return initAttributes();
+		AjaxRequestAttributes attributes = new AjaxRequestAttributes();
+		updateAttributes(attributes, component);
+		return attributes;
+		
+	}
+	
+	protected void updateAttributes(AjaxRequestAttributes attributes, Component component)
+	{
+		
 	}
 
 	protected String getAjaxIndicatorMarkupId()
@@ -413,7 +431,7 @@
 	{
 		return true;
 	}
-	
+
 	private String findIndicatorId(Component component)
 	{
 		String id = getAjaxIndicatorMarkupId();

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxEventBehavior.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxEventBehavior.java?rev=691085&r1=691084&r2=691085&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxEventBehavior.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxEventBehavior.java Mon Sep  1 17:23:20 2008
@@ -59,14 +59,14 @@
 		js.append("',");
 		js.append(renderAttributes(component));
 		
-		boolean allowDefault = getAttributes().isAllowDefault(); 
+		boolean allowDefault = getAttributes(component).isAllowDefault(); 
 		if (allowDefault)
 		{
 			js.append("," + allowDefault);
 		}
 		js.append(")");				
 
-		response.renderOnDomReadyJavascript(decorateScript(js).toString());
+		response.renderOnDomReadyJavascript(decorateScript(js, component).toString());
 	}
 	
 }

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxRequestAttributes.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxRequestAttributes.java?rev=691085&r1=691084&r2=691085&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxRequestAttributes.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxRequestAttributes.java Mon Sep  1 17:23:20 2008
@@ -19,31 +19,9 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.wicket.markup.html.form.Form;
-
 /**
  * Attributes of an Ajax Request.
  * 
- * This class supports delegating the calls to another {@link AjaxRequestAttributes} instance if one
- * is specified. To extend attributes from behavior or component the following pattern can be used:
- * 
- * <pre>
- * // add a precondition to super attirbutes
- * class MyBehavior extends AjaxBehavior
- * {
- * 	public AjaxRequestAttributes getAttributes()
- *          {
- *              return new AjaxRequestAttributesImpl(super.getAttributes) 
- *              {
- *                  public FunctionList getPreconditions()
- *                  {
- *                      return super.getPreconditions().add(&quot;function(requestQueueItem) { return true; }&quot;;);
- *                  }
- *              }
- *          }
- * }
- * </pre>
- * 
  * <hr>
  * 
  * <p>
@@ -78,131 +56,143 @@
  * 
  * @author Matej Knopp
  */
-public class AjaxRequestAttributes
+public final class AjaxRequestAttributes
 {
-	private final AjaxRequestAttributes delegate;
-
-	/**
-	 * Construct.
-	 * 
-	 * @param delegate
-	 */
-	public AjaxRequestAttributes(AjaxRequestAttributes delegate)
-	{
-		this.delegate = delegate;
-	}
-
 	/**
 	 * 
 	 * Construct.
 	 */
 	public AjaxRequestAttributes()
 	{
-		this(null);
+
 	}
 
+	private boolean multipart = false;
+	private boolean forcePost = false;
+	private Integer requestTimeout;
+	private Integer processingTimeout;
+	private String token;
+	private boolean removePrevious = false;
+	private Integer throttle;
+	private boolean throttlePostpone = false;
+	private boolean allowDefault = false;
+
+	private final FunctionList preconditions = new FunctionList();
+	private final FunctionList beforeHandlers = new FunctionList();
+	private final FunctionList successHandlers = new FunctionList();
+	private final FunctionList errorHandlers = new FunctionList();
+	private final Map<String, Object> urlArguments = new HashMap<String, Object>();
+	private final FunctionList urlArgumentMethods = new FunctionList();
+	private final FunctionList requestQueueItemCreationListeners = new FunctionList();
+	private final ChainingList<ExpressionDecorator> expressionDecorators = new ChainingList<ExpressionDecorator>();
+
 	/**
-	 * Form instance if the AJAX request should submit a form or <code>null</code> if the request
-	 * doesn't involve form submission.
+	 * Returns whether the form submit is multipart.
+	 * <p>
+	 * Note that for multipart AJAX requests a hidden IFRAME will be used and that can have negative
+	 * impact on error detection.
 	 * 
-	 * @return form instance or <code>null</code>
+	 * @return <code>true</code> if the form submit should be multipart, <code>false</code>
+	 *         otherwise
 	 */
-	public Form<?> getForm()
+	public boolean isMultipart()
 	{
-		if (delegate != null)
-		{
-			return delegate.getForm();
-		}
-		else
-		{
-			return null;
-		}
+		return multipart;
 	}
 
-
 	/**
-	 * Returns whether the form submit is multipart.
+	 * Determines whether the form submit is multipart.
+	 * 
 	 * <p>
 	 * Note that for multipart AJAX requests a hidden IFRAME will be used and that can have negative
 	 * impact on error detection.
 	 * 
-	 * @return <code>true</code> if the form submit should be multipart, <code>false</code>
-	 *         otherwise
+	 * @param multipart
 	 */
-	public Boolean isMultipart()
+	public void setMultipart(boolean multipart)
 	{
-		if (delegate != null)
-		{
-			return delegate.isMultipart();
-		}
-		else
-		{
-			return null;
-		}
+		this.multipart = multipart;
 	}
 
 	/**
 	 * Returns whether the Ajax request should be a <code>POST</code> regardless of whether a form
 	 * is being submitted.
-	 * <p> 
+	 * <p>
 	 * For a <code>POST</code>request all URL arguments are submitted as body. This can be useful
 	 * if the URL parameters are longer than maximal URL length.
 	 * 
 	 * @return <code>true</code> if the request should be post, <code>false</code> otherwise.
 	 */
-	public Boolean isForcePost()
+	public boolean isForcePost()
 	{
-		if (delegate != null)
-		{
-			return delegate.isForcePost();
-		}
-		else
-		{
-			return null;
-		}
+		return forcePost;
 	}
 
 	/**
-	 * Timeout in milliseconds for the AJAX request. This only involves the actual communication and
-	 * not the processing afterwards. Can be <code>null</code> in which case the default request
-	 * timeout will be used.
+	 * Determines whether the Ajax request should be a <code>POST</code> regardless of whether a
+	 * form is being submitted.
+	 * <p>
+	 * For a <code>POST</code>request all URL arguments are submitted as body. This can be useful
+	 * if the URL parameters are longer than maximal URL length.
+	 * 
+	 * @param forcePost
+	 */
+	public void setForcePost(boolean forcePost)
+	{
+		this.forcePost = forcePost;
+	}
+
+	/**
+	 * Returns the timeout in milliseconds for the AJAX request. This only involves the actual
+	 * communication and not the processing afterwards. Can be <code>null</code> in which case the
+	 * default request timeout will be used.
 	 * 
 	 * @return request timeout in milliseconds or <code>null<code> for default timeout
 	 */
-	public Integer getRequesTimeout()
+	public Integer getRequestTimeout()
 	{
-		if (delegate != null)
-		{
-			return delegate.getRequesTimeout();
-		}
-		else
-		{
-			return null;
-		}
+		return requestTimeout;
 	}
 
 	/**
-	 * Timeout for the response processing. In case the response processing takes more than the
-	 * timeout it won't block the request queue. Can be <code>null</code> in which case the
-	 * default processing timeout will be used.
+	 * Sets the timeout in milliseconds for the AJAX request. This only involves the actual
+	 * communication and not the processing afterwards. Can be <code>null</code> in which case the
+	 * default request timeout will be used.
+	 * 
+	 * @param requestTimeout
+	 */
+	public void setRequestTimeout(Integer requestTimeout)
+	{
+		this.requestTimeout = requestTimeout;
+	}
+
+	/**
+	 * Returns the timeout for the response processing. In case the response processing takes more
+	 * than the timeout it won't block the request queue. Can be <code>null</code> in which case
+	 * the default processing timeout will be used.
 	 * 
 	 * @return processing timeout in milliseconds or <code>null</code> for default timeout
 	 */
 	public Integer getProcessingTimeout()
 	{
-		if (delegate != null)
-		{
-			return delegate.getProcessingTimeout();
-		}
-		else
-		{
-			return null;
-		}
+		return processingTimeout;
+	}
+
+	/**
+	 * Sets the timeout for the response processing. In case the response processing takes more than
+	 * the timeout it won't block the request queue. Can be <code>null</code> in which case the
+	 * default processing timeout will be used.
+	 * 
+	 * @param processingTimeout
+	 */
+	public void setProcessingTimeout(Integer processingTimeout)
+	{
+		this.processingTimeout = processingTimeout;
 	}
 
 	/**
-	 * Optional string identifying related items in request queue. Used to identify previous items
-	 * (items with same token) that will be removed when this item is added and
+	 * Returns optional string identifying related items in request queue. Used to identify previous
+	 * items (items with same token) that will be removed when this item is added and
 	 * {@link #isRemovePrevious()} returns <code>true</code>. Also required when throttling is
 	 * enabled.
 	 * 
@@ -213,14 +203,23 @@
 	 */
 	public String getToken()
 	{
-		if (delegate != null)
-		{
-			return delegate.getToken();
-		}
-		else
-		{
-			return null;
-		}
+		return token;
+	}
+
+	/**
+	 * Sets optional string identifying related items in request queue. Used to identify previous
+	 * items (items with same token) that will be removed when this item is added and
+	 * {@link #isRemovePrevious()} returns <code>true</code>. Also required when throttling is
+	 * enabled.
+	 * 
+	 * @see #getThrottle()
+	 * @see #isRemovePrevious()
+	 * 
+	 * @param token
+	 */
+	public void setToken(String token)
+	{
+		this.token = token;
 	}
 
 	/**
@@ -239,14 +238,24 @@
 	 */
 	public Boolean isRemovePrevious()
 	{
-		if (delegate != null)
-		{
-			return delegate.isRemovePrevious();
-		}
-		else
-		{
-			return null;
-		}
+		return removePrevious;
+	}
+
+	/**
+	 * If there are previous items with same token in the queue they will be removed if
+	 * {@link #setRemovePrevious(boolean)} is set to <code>true</code>. This can be useful when
+	 * the items are added in queue faster than they are processed and only the latest request
+	 * matters.
+	 * <p>
+	 * An example of this could be periodically updated component. There is no point of having
+	 * multiple refreshing requests stored in the queue for such component because only the last
+	 * request is relevant. Alternative to this is throttling.
+	 * 
+	 * @param removePrevious
+	 */
+	public void setRemovePrevious(boolean removePrevious)
+	{
+		this.removePrevious = removePrevious;
 	}
 
 	/**
@@ -262,14 +271,23 @@
 	 */
 	public Integer getThrottle()
 	{
-		if (delegate != null)
-		{
-			return delegate.getThrottle();
-		}
-		else
-		{
-			return null;
-		}
+		return throttle;
+	}
+
+	/**
+	 * Limits adding items with same token to at most one item per n milliseconds where n is the
+	 * return value.
+	 * <p>
+	 * Useful to limit the number of AJAX requests that are triggered by a user action such as
+	 * typing into a text field. Throttle attribute only applies when token is specified.
+	 * 
+	 * @see #getToken()
+	 * 
+	 * @param throttle
+	 */
+	public void setThrottle(Integer throttle)
+	{
+		this.throttle = throttle;
 	}
 
 	/**
@@ -283,16 +301,22 @@
 	 * 
 	 * @return boolean value or <code>null</code>
 	 */
-	public Boolean isThrottlePostpone()
+	public boolean isThrottlePostpone()
+	{
+		return throttlePostpone;
+	}
+
+	/**
+	 * When set to true causes the throttle timer reset each time item with same token is being
+	 * added to queue.
+	 * 
+	 * @see #isThrottlePostpone()
+	 * 
+	 * @param throttlePostpone
+	 */
+	public void setThrottlePostpone(boolean throttlePostpone)
 	{
-		if (delegate != null)
-		{
-			return delegate.isThrottlePostpone();
-		}
-		else
-		{
-			return null;
-		}
+		this.throttlePostpone = throttlePostpone;
 	}
 
 	/**
@@ -343,16 +367,7 @@
 	 */
 	public FunctionList getPreconditions()
 	{
-		FunctionList result = null;
-		if (delegate != null)
-		{
-			result = delegate.getPreconditions();
-		}
-		if (result == null)
-		{
-			result = new FunctionList();
-		}
-		return result;
+		return preconditions;
 	}
 
 	/**
@@ -375,16 +390,7 @@
 	 */
 	public FunctionList getBeforeHandlers()
 	{
-		FunctionList result = null;
-		if (delegate != null)
-		{
-			result = delegate.getBeforeHandlers();
-		}
-		if (result == null)
-		{
-			result = new FunctionList();
-		}
-		return result;
+		return beforeHandlers;
 	}
 
 	/**
@@ -404,16 +410,7 @@
 	 */
 	public FunctionList getSuccessHandlers()
 	{
-		FunctionList result = null;
-		if (delegate != null)
-		{
-			result = delegate.getSuccessHandlers();
-		}
-		if (result == null)
-		{
-			result = new FunctionList();
-		}
-		return result;
+		return successHandlers;
 	}
 
 	/**
@@ -438,16 +435,7 @@
 	 */
 	public FunctionList getErrorHandlers()
 	{
-		FunctionList result = null;
-		if (delegate != null)
-		{
-			result = delegate.getErrorHandlers();
-		}
-		if (result == null)
-		{
-			result = new FunctionList();
-		}
-		return result;
+		return errorHandlers;
 	}
 
 	/**
@@ -458,16 +446,7 @@
 	 */
 	public Map<String, Object> getUrlArguments()
 	{
-		Map<String, Object> result = null;
-		if (delegate != null)
-		{
-			result = delegate.getUrlArguments();
-		}
-		if (result == null)
-		{
-			result = new HashMap<String, Object>();
-		}
-		return result;
+		return urlArguments;
 	}
 
 	/**
@@ -489,16 +468,7 @@
 	 */
 	public FunctionList getUrlArgumentMethods()
 	{
-		FunctionList result = null;
-		if (delegate != null)
-		{
-			result = delegate.getUrlArgumentMethods();
-		}
-		if (result == null)
-		{
-			result = new FunctionList();
-		}
-		return result;
+		return urlArgumentMethods;
 	}
 
 	/**
@@ -509,16 +479,7 @@
 	 */
 	public FunctionList getRequestQueueItemCreationListeners()
 	{
-		FunctionList result = null;
-		if (delegate != null)
-		{
-			result = delegate.getRequestQueueItemCreationListeners();
-		}
-		if (result == null)
-		{
-			result = new FunctionList();
-		}
-		return result;
+		return requestQueueItemCreationListeners;
 	}
 
 	/**
@@ -535,16 +496,7 @@
 	 */
 	public ChainingList<ExpressionDecorator> getExpressionDecorators()
 	{
-		ChainingList<ExpressionDecorator> result = null;
-		if (delegate != null)
-		{
-			result = delegate.getExpressionDecorators();
-		}
-		if (result == null)
-		{
-			result = new ChainingList<ExpressionDecorator>();
-		}
-		return result;
+		return expressionDecorators;
 	}
 
 	/**
@@ -559,13 +511,19 @@
 	 */
 	public boolean isAllowDefault()
 	{
-		if (delegate != null)
-		{
-			return delegate.isAllowDefault();
-		}
-		else
-		{
-			return false;
-		}
-	}	
+		return allowDefault;
+	}
+
+	/**
+	 * Only applies for event behaviors. Determines whether the behavior should allow the default
+	 * event handler to be invoked.
+	 * 
+	 * @see #isAllowDefault()
+	 * 
+	 * @param allowDefault
+	 */
+	public void setAllowDefault(boolean allowDefault)
+	{
+		this.allowDefault = allowDefault;
+	}
 }

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxTimerBehavior.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxTimerBehavior.java?rev=691085&r1=691084&r2=691085&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxTimerBehavior.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/AjaxTimerBehavior.java Mon Sep  1 17:23:20 2008
@@ -240,22 +240,9 @@
 	}
 
 	@Override
-	public AjaxRequestAttributes initAttributes()
+	protected void updateAttributes(AjaxRequestAttributes attributes, Component component)
 	{
-		return new AjaxRequestAttributes(super.initAttributes())
-		{
-			@Override
-			public Boolean isRemovePrevious()
-			{
-				// Do not queue the requests on client
-				return true;
-			}
-
-			@Override
-			public String getToken()
-			{				
-				return getId();
-			}
-		};
-	}
+		attributes.setRemovePrevious(true);
+		attributes.setToken(getId());
+	}	
 }

Added: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/form/AjaxFormSubmitBehavior.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/form/AjaxFormSubmitBehavior.java?rev=691085&view=auto
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/form/AjaxFormSubmitBehavior.java (added)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/form/AjaxFormSubmitBehavior.java Mon Sep  1 17:23:20 2008
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.ajaxng.form;
+
+import java.util.Map;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.ajaxng.AjaxEventBehavior;
+import org.apache.wicket.ajaxng.AjaxRequestAttributes;
+import org.apache.wicket.ajaxng.AjaxRequestTarget;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.IFormSubmittingComponent;
+import org.apache.wicket.markup.html.panel.FeedbackPanel;
+
+public abstract class AjaxFormSubmitBehavior extends AjaxEventBehavior
+{
+	private static final long serialVersionUID = 1L;
+
+	private Form<?> form;
+
+	public AjaxFormSubmitBehavior(String event)
+	{
+		this(null, event);
+	}
+
+	public AjaxFormSubmitBehavior(Form<?> form, String event)
+	{
+		super(event);
+		this.form = form;
+	}
+
+	/**
+	 * @return Form that will be submitted by this behavior
+	 */
+	@Override
+	protected Form<?> getForm(Component component)
+	{
+		if (form == null)
+		{
+			// try to find form in the hierarchy of owning component
+			form = component.findParent(Form.class);
+			if (form == null)
+			{
+				throw new IllegalStateException(
+					"form was not specified in the constructor and cannot "
+						+ "be found in the hierarchy of the component this behavior "
+						+ "is attached to");
+			}
+		}
+		return form;
+	}
+
+	protected Form<?> getForm()
+	{
+		Component component = getBoundComponents().iterator().next();
+		return getForm(component);
+	}
+	
+	@Override
+	protected void onEvent(AjaxRequestTarget target)
+	{
+		getForm().getRootForm().onFormSubmitted();
+		if (!getForm().isSubmitted())
+		{ // only process the form submission if the form was actually submitted -> needs to be
+			// enabled and visible
+			return;
+		}
+		if (!getForm().hasError())
+		{
+			onSubmit(target);
+		}
+		if (form.findParent(Page.class) != null)
+		{
+			/*
+			 * there can be cases when a form is replaced with another component in the onsubmit()
+			 * handler of this behavior. in that case form no longer has a page and so calling
+			 * .hasError on it will cause an exception, thus the check above.
+			 */
+			if (getForm().hasError())
+			{
+				onError(target);
+			}
+		}
+		
+		updateFeedback(target);
+	}
+	
+	@Override
+	protected void updateAttributes(AjaxRequestAttributes attributes, Component component)
+	{
+		super.updateAttributes(attributes, component);
+		
+		if (component instanceof IFormSubmittingComponent)
+		{
+			attributes.getUrlArguments().put(((IFormSubmittingComponent)component).getInputName(), 1);
+		}
+	}
+	
+	/**
+	 * Listener method that is invoked after the form has been submitted and processed without
+	 * errors
+	 * 
+	 * @param target
+	 */
+	protected abstract void onSubmit(AjaxRequestTarget target);
+
+	/**
+	 * Listener method invoked when the form has been processed and errors occurred
+	 * 
+	 * @param target
+	 * 
+	 */
+	protected abstract void onError(AjaxRequestTarget target);
+
+	/**
+	 * Convenience method that is called whether the form submit succeeds or not. Useful for
+	 * refreshing components that should be updated regardless of whether the form failed to
+	 * validate or not, such as {@link FeedbackPanel}s.
+	 * 
+	 * @param target
+	 */
+	protected void updateFeedback(AjaxRequestTarget target)
+	{
+	}
+}

Propchange: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/form/AjaxFormSubmitBehavior.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/markup/html/AjaxLink.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/markup/html/AjaxLink.java?rev=691085&r1=691084&r2=691085&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/markup/html/AjaxLink.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/ajaxng/markup/html/AjaxLink.java Mon Sep  1 17:23:20 2008
@@ -48,8 +48,6 @@
 		this(id, null);
 	}
 
-	private final AjaxEventBehavior behavior;
-	
 	/**
 	 * Construct.
 	 * 
@@ -60,7 +58,7 @@
 	{
 		super(id, model);
 
-		add(behavior = new AjaxEventBehavior("click")
+		add(new AjaxEventBehavior("click")
 		{
 			private static final long serialVersionUID = 1L;
 
@@ -78,23 +76,19 @@
 			}
 			
 			@Override
-			public AjaxRequestAttributes getAttributes()
+			protected void updateAttributes(AjaxRequestAttributes attributes, Component component)
 			{
-				return AjaxLink.this.getAttributes();
+				super.updateAttributes(attributes, component);
+				AjaxLink.this.updateAttributes(attributes);
 			}
 		});
 	}
-
-	/**
-	 * Returns {@link AjaxRequestAttributes} object for this link.
-	 * 
-	 * @return {@link AjaxRequestAttributes} instance
-	 */
-	public AjaxRequestAttributes getAttributes()
+	
+	protected void updateAttributes(AjaxRequestAttributes attributes)
 	{
-		return behavior.initAttributes();
+		
 	}
-	
+		
 	@Override
 	protected void onComponentTag(ComponentTag tag)
 	{