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 2018/01/26 23:04:06 UTC

[01/16] wicket git commit: WICKET-6503 beforeRender clean-up [Forced Update!]

Repository: wicket
Updated Branches:
  refs/heads/WICKET-6523-ajax-timers cdfffcb6f -> ffcb8cfec (forced update)


WICKET-6503 beforeRender clean-up

- prepare all components before writing them to Ajax response
- simplified delayed preparation of feedbacks
- clean-up internal component API an flags

this closes #250


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: c27a57b31a0e519ef15dfe08b425d85f9a24f685
Parents: c787470
Author: Sven Meier <sv...@apache.org>
Authored: Thu Dec 14 07:55:53 2017 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Wed Jan 17 22:26:11 2018 +0100

----------------------------------------------------------------------
 .../main/java/org/apache/wicket/Component.java  | 332 ++++++-------------
 .../java/org/apache/wicket/MarkupContainer.java |  22 --
 .../src/main/java/org/apache/wicket/Page.java   |  36 +-
 .../ComponentRenderingRequestHandler.java       |   9 +-
 .../handler/PageAndComponentProvider.java       |   2 +-
 .../core/util/string/ComponentRenderer.java     |   3 +-
 .../apache/wicket/feedback/FeedbackDelay.java   | 119 +++++++
 .../org/apache/wicket/feedback/IFeedback.java   |   5 +-
 .../apache/wicket/page/PartialPageUpdate.java   |  74 ++++-
 .../wicket/page/XmlPartialPageUpdate.java       |  50 +--
 .../wicket/feedback/FeedbackRenderTest.java     |  22 +-
 .../apache/wicket/feedback/FeedbacksPage.html   |  16 +-
 .../apache/wicket/feedback/FeedbacksPage.java   |  31 +-
 .../markup/html/internal/EnclosurePage_1.java   |  50 ++-
 .../markup/html/internal/EnclosureTest.java     |   4 +
 15 files changed, 422 insertions(+), 353 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/main/java/org/apache/wicket/Component.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/Component.java b/wicket-core/src/main/java/org/apache/wicket/Component.java
index 7240a13..fc32b09 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Component.java
+++ b/wicket-core/src/main/java/org/apache/wicket/Component.java
@@ -17,11 +17,11 @@
 package org.apache.wicket;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Optional;
 
 import org.apache.wicket.ajax.IAjaxRegionMarkupIdProvider;
 import org.apache.wicket.application.IComponentInstantiationListener;
@@ -40,6 +40,7 @@ import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.event.IEvent;
 import org.apache.wicket.event.IEventSink;
 import org.apache.wicket.event.IEventSource;
+import org.apache.wicket.feedback.FeedbackDelay;
 import org.apache.wicket.feedback.FeedbackMessage;
 import org.apache.wicket.feedback.FeedbackMessages;
 import org.apache.wicket.feedback.IFeedback;
@@ -86,7 +87,6 @@ import org.apache.wicket.util.lang.Classes;
 import org.apache.wicket.util.string.PrependingStringBuffer;
 import org.apache.wicket.util.string.Strings;
 import org.apache.wicket.util.value.ValueMap;
-import org.apache.wicket.util.visit.IVisit;
 import org.apache.wicket.util.visit.IVisitFilter;
 import org.apache.wicket.util.visit.IVisitor;
 import org.apache.wicket.util.visit.Visit;
@@ -312,12 +312,6 @@ public abstract class Component
 		}
 	};
 
-	/** an unused flag */
-	private static final int FLAG_UNUSED0 = 0x20000000;
-	private static final int FLAG_UNUSED1 = 0x800000;
-	private static final int FLAG_UNUSED2 = 0x1000000;
-	private static final int FLAG_UNUSED3 = 0x10000000;
-
 	/** True when a component is being auto-added */
 	private static final int FLAG_AUTO = 0x0001;
 
@@ -389,17 +383,6 @@ public abstract class Component
 	 */
 	private static final int FLAG_MODEL_SET = 0x100000;
 
-	/** True when a component is being removed from the hierarchy */
-	protected static final int FLAG_REMOVING_FROM_HIERARCHY = 0x200000;
-
-	/**
-	 * Flag that makes we are in before-render callback phase Set after component.onBeforeRender is
-	 * invoked (right before invoking beforeRender on children)
-	 */
-	protected static final int FLAG_RENDERING = 0x2000000;
-	protected static final int FLAG_PREPARED_FOR_RENDER = 0x4000000;
-	protected static final int FLAG_AFTER_RENDERING = 0x8000000;
-
 	/**
 	 * Flag that restricts visibility of a component when set to true. This is usually used when a
 	 * component wants to restrict visibility of another component. Calling
@@ -408,8 +391,6 @@ public abstract class Component
 	 */
 	private static final int FLAG_VISIBILITY_ALLOWED = 0x40000000;
 
-	private static final int FLAG_DETACHING = 0x80000000;
-	
 	/**
 	 * The name of attribute that will hold markup id
 	 */
@@ -447,6 +428,16 @@ public abstract class Component
 	private static final short RFLAG_INITIALIZE_SUPER_CALL_VERIFIED = 0x40;
 	protected static final short RFLAG_CONTAINER_DEQUEING = 0x80;
 	private static final short RFLAG_ON_RE_ADD_SUPER_CALL_VERIFIED = 0x100;
+	/**
+	 * Flag that makes we are in before-render callback phase Set after component.onBeforeRender is
+	 * invoked (right before invoking beforeRender on children)
+	 */
+	private static final short RFLAG_RENDERING = 0x200;
+	private static final short RFLAG_PREPARED_FOR_RENDER = 0x400;
+	private static final short RFLAG_AFTER_RENDERING = 0x800;
+	private static final short RFLAG_DETACHING = 0x1000;	
+	/** True when a component is being removed from the hierarchy */
+	private static final short RFLAG_REMOVING_FROM_HIERARCHY = 0x2000;
 
 	/**
 	 * Flags that only keep their value during the request. Useful for cache markers, etc. At the
@@ -789,7 +780,7 @@ public abstract class Component
 	}
 
 	/**
-	 * Called once per request on components before they are about to be rendered. This method
+	 * Called on all components before any component is rendered. This method
 	 * should be used to configure such things as visibility and enabled flags.
 	 * <p>
 	 * Overrides must call {@code super.onConfigure()}, usually before any other code
@@ -857,7 +848,7 @@ public abstract class Component
 	}
 
 	/**
-	 * THIS METHOD IS NOT PART OF THE PUBLIC API, DO NOT CALL IT
+	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
 	 * 
 	 * Used to call {@link #onInitialize()}
 	 */
@@ -903,22 +894,19 @@ public abstract class Component
 	}
 
 	/**
-	 * Called on every component after the page is rendered. It will call onAfterRender for it self
-	 * and its children.
+	 * Called on every component after the page is rendered. Calls hook {@link #onAfterRender()}.
 	 */
-	public final void afterRender()
+	final void afterRender()
 	{
+		setRequestFlag(RFLAG_PREPARED_FOR_RENDER, false);
+		
 		try
 		{
-			setFlag(FLAG_AFTER_RENDERING, true);
-
-			// always detach children because components can be attached
-			// independently of their parents
-			onAfterRenderChildren();
+			setRequestFlag(RFLAG_AFTER_RENDERING, true);
 
 			onAfterRender();
 			getApplication().getComponentOnAfterRenderListeners().onAfterRender(this);
-			if (getFlag(FLAG_AFTER_RENDERING))
+			if (getRequestFlag(RFLAG_AFTER_RENDERING))
 			{
 				throw new IllegalStateException(Component.class.getName() +
 					" has not been properly detached. Something in the hierarchy of " +
@@ -929,91 +917,53 @@ public abstract class Component
 		finally
 		{
 			// this flag must always be set to false.
-			markRendering(false);
+			setRequestFlag(RFLAG_RENDERING, false);
 		}
 	}
 
-	private void internalBeforeRender()
-	{
-		configure();
-
-		if ((determineVisibility()) && !getFlag(FLAG_RENDERING) &&
-			!getFlag(FLAG_PREPARED_FOR_RENDER))
-		{
-			setRequestFlag(RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED, false);
-
-			Application application = getApplication();
-			application.getComponentPreOnBeforeRenderListeners().onBeforeRender(this);
-
-			onBeforeRender();
-			application.getComponentPostOnBeforeRenderListeners().onBeforeRender(this);
-
-			if (!getRequestFlag(RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED))
-			{
-				throw new IllegalStateException(Component.class.getName() +
-					" has not been properly rendered. Something in the hierarchy of " +
-					getClass().getName() +
-					" has not called super.onBeforeRender() in the override of onBeforeRender() method");
-			}
-		}
-	}
-
-	/**
-	 * We need to postpone calling beforeRender() on components that implement {@link IFeedback}, to
-	 * be sure that all other component's beforeRender() has been already called, so that IFeedbacks
-	 * can collect all feedback messages. This is the key under list of postponed {@link IFeedback}
-	 * is stored to request cycle metadata. The List is then iterated over in
-	 * {@link #prepareForRender()} after calling {@link #beforeRender()}, to initialize postponed
-	 * components.
-	 */
-	private static final MetaDataKey<List<Component>> FEEDBACK_LIST = new MetaDataKey<List<Component>>()
-	{
-		private static final long serialVersionUID = 1L;
-	};
-
 	/**
-	 * Called for every component when the page is getting to be rendered. it will call
-	 * {@link #configure()} and {@link #onBeforeRender()} for this component and all the child
-	 * components
+	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
+	 * 
+	 * Called on all components before any component is rendered. Calls hooks
+	 * {@link #configure()} and (if visible) {@link #onBeforeRender()}
+	 * and delegates to {@link #beforeRender()} of all child components.
 	 */
 	public final void beforeRender()
 	{
 		if (this instanceof IFeedback)
 		{
-			// this component is a feedback. Feedback must be initialized last, so that
-			// they can collect messages from other components
-			List<Component> feedbacks = getRequestCycle().getMetaData(FEEDBACK_LIST);
-			if (feedbacks == null)
-			{
-				feedbacks = new ArrayList<>();
-				getRequestCycle().setMetaData(FEEDBACK_LIST, feedbacks);
+			Optional<FeedbackDelay> delay = FeedbackDelay.get(getRequestCycle());
+			if (delay.isPresent()) {
+				delay.get().postpone((IFeedback)this);
+				return;
 			}
+		}
 
-			if (this instanceof MarkupContainer)
-			{
-				((MarkupContainer)this).visitChildren(IFeedback.class,
-					new IVisitor<Component, Void>()
-					{
-						@Override
-						public void component(Component feedback, IVisit<Void> visit)
-						{
-							feedback.beforeRender();
-
-							// don't need to go deeper,
-							// as the feedback will visit its children on its own
-							visit.dontGoDeeper();
-						}
-					});
-			}
+		configure();
 
-			if (!feedbacks.contains(this))
-			{
-				feedbacks.add(this);
-			}
-		}
-		else
+		if ((determineVisibility()) && !getRequestFlag(RFLAG_RENDERING) &&
+			!getRequestFlag(RFLAG_PREPARED_FOR_RENDER))
 		{
-			internalBeforeRender();
+			try {
+				setRequestFlag(RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED, false);
+
+				Application application = getApplication();
+				application.getComponentPreOnBeforeRenderListeners().onBeforeRender(this);
+
+				onBeforeRender();
+				application.getComponentPostOnBeforeRenderListeners().onBeforeRender(this);
+
+				if (!getRequestFlag(RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED))
+				{
+					throw new IllegalStateException(Component.class.getName() +
+						" has not been properly rendered. Something in the hierarchy of " +
+						getClass().getName() +
+						" has not called super.onBeforeRender() in the override of onBeforeRender() method");
+				}
+			} catch (RuntimeException ex) {
+				setRequestFlag(RFLAG_PREPARED_FOR_RENDER, false);
+				throw ex;
+			}
 		}
 	}
 
@@ -1072,9 +1022,6 @@ public abstract class Component
 	}
 
 	/**
-	 * 
-	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
-	 * 
 	 * Called after the {@link #onConfigure()}, but before {@link #onBeforeRender()}
 	 */
 	void internalOnAfterConfigure()
@@ -1134,10 +1081,10 @@ public abstract class Component
 	 */
 	final void internalOnRemove()
 	{
-		setFlag(FLAG_REMOVING_FROM_HIERARCHY, true);
+		setRequestFlag(RFLAG_REMOVING_FROM_HIERARCHY, true);
 		onRemove();
 		setFlag(FLAG_REMOVED, true);
-		if (getFlag(FLAG_REMOVING_FROM_HIERARCHY))
+		if (getRequestFlag(RFLAG_REMOVING_FROM_HIERARCHY))
 		{
 			throw new IllegalStateException(Component.class.getName() +
 				" has not been properly removed from hierachy. Something in the hierarchy of " +
@@ -1157,9 +1104,9 @@ public abstract class Component
 	{
 		try
 		{
-			setFlag(FLAG_DETACHING, true);
+			setRequestFlag(RFLAG_DETACHING, true);
 			onDetach();
-			if (getFlag(FLAG_DETACHING))
+			if (getRequestFlag(RFLAG_DETACHING))
 			{
 				throw new IllegalStateException(Component.class.getName() +
 						" has not been properly detached. Something in the hierarchy of " +
@@ -1469,7 +1416,7 @@ public abstract class Component
 	}
 
 	/**
-	 * THIS IS WICKET INTERNAL ONLY. DO NOT USE IT.
+	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
 	 * 
 	 * Get a copy of the markup's attributes which are associated with the component.
 	 * <p>
@@ -2170,23 +2117,6 @@ public abstract class Component
 	}
 
 	/**
-	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
-	 * 
-	 * Sets the RENDERING flag and removes the PREPARED_FOR_RENDER flag on component and it's
-	 * children.
-	 * 
-	 * @param setRenderingFlag
-	 *            if this is false only the PREPARED_FOR_RENDER flag is removed from component, the
-	 *            RENDERING flag is not set.
-	 * 
-	 * @see #internalPrepareForRender(boolean)
-	 */
-	public final void markRendering(boolean setRenderingFlag)
-	{
-		internalMarkRendering(setRenderingFlag);
-	}
-
-	/**
 	 * Called to indicate that the model content for this component has been changed
 	 */
 	public final void modelChanged()
@@ -2215,62 +2145,6 @@ public abstract class Component
 	}
 
 	/**
-	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
-	 * <p>
-	 * Prepares the component and it's children for rendering. On whole page render this method must
-	 * be called on the page. On AJAX request, this method must be called on the updated component.
-	 * 
-	 * @param setRenderingFlag
-	 *            Whether to set the rendering flag. This must be true if the page is about to be
-	 *            rendered. However, there are usecases to call this method without an immediate
-	 *            render (e.g. on stateless listener request target to build the component
-	 *            hierarchy), in that case setRenderingFlag should be false.
-	 */
-	public void internalPrepareForRender(boolean setRenderingFlag)
-	{
-		beforeRender();
-
-		if (setRenderingFlag)
-		{
-			// only process feedback panel when we are about to be rendered.
-			// setRenderingFlag is false in case prepareForRender is called only to build component
-			// hierarchy (i.e. in BookmarkableListenerRequestHandler).
-			// prepareForRender(true) is always called before the actual rendering is done so
-			// that's where feedback panels gather the messages
-
-			List<Component> feedbacks = getRequestCycle().getMetaData(FEEDBACK_LIST);
-			if (feedbacks != null)
-			{
-				// iterate over a copy because a IFeedback may add more IFeedback children
-// (WICKET-4687)
-				Component[] feedbacksCopy = feedbacks.toArray(new Component[feedbacks.size()]);
-				for (Component feedback : feedbacksCopy)
-				{
-					// render it only if it is still in the page hierarchy (WICKET-4895)
-					if (feedback.findPage() != null)
-					{
-						feedback.internalBeforeRender();
-					}
-				}
-			}
-			getRequestCycle().setMetaData(FEEDBACK_LIST, null);
-		}
-
-		markRendering(setRenderingFlag);
-	}
-
-	/**
-	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
-	 * 
-	 * Prepares the component and it's children for rendering. On whole page render this method must
-	 * be called on the page. On AJAX request, this method must be called on updated component.
-	 */
-	public final void prepareForRender()
-	{
-		internalPrepareForRender(true);
-	}
-
-	/**
 	 * Redirects browser to an intermediate page such as a sign-in page. The current request's url
 	 * is saved for future use by method continueToOriginalDestination(); Only use this method when
 	 * you plan to continue to the current url at some later time; otherwise just use
@@ -2303,24 +2177,42 @@ public abstract class Component
 		parent.remove(this);
 	}
 
+	/**
+	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
+	 * <p>
+	 * Renders this component as a part of a response - the caller has to
+	 * make sure that this component is prepared for render.
+	 * 
+	 * @see #beforeRender()
+	 */
+	public final void renderPart() {
+		Page page = getPage();
+
+		page.startComponentRender(this);
+
+		render();
+		
+		page.endComponentRender(this);
+	}
 
 	/**
-	 * Render the Component.
+	 * Render this component and all its children. Always calls hook {@link #onAfterRender()}
+	 * regardless of any exception.
 	 */
 	public final void render()
 	{
-		RuntimeException exception = null;
+		if (isAuto())
+		{
+			// auto components are prepared when rendered
+			beforeRender();
+		}
 
+		// Do the render
+		RuntimeException exception = null;
 		try
 		{
-			// Invoke prepareForRender only if this is the root component to be rendered
-			MarkupContainer parent = getParent();
-			if ((parent == null) || (parent.getFlag(FLAG_RENDERING) == false) || isAuto())
-			{
-				internalPrepareForRender(true);
-			}
-
-			// Do the render
+			setRequestFlag(RFLAG_RENDERING, true);
+			
 			internalRender();
 		}
 		catch (final RuntimeException ex)
@@ -2367,9 +2259,6 @@ public abstract class Component
 		// MarkupStream is an Iterator for the markup
 		MarkupStream markupStream = new MarkupStream(markup);
 
-		// Flag: we started the render process
-		markRendering(true);
-
 		MarkupElement elem = markup.get(0);
 		if (elem instanceof ComponentTag)
 		{
@@ -2513,13 +2402,13 @@ public abstract class Component
 
 
 	/**
-	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT.
+	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
 	 * <p>
 	 * Renders the component at the current position in the given markup stream. The method
 	 * onComponentTag() is called to allow the component to mutate the start tag. The method
 	 * onComponentTagBody() is then called to permit the component to render its body.
 	 */
-	public final void internalRenderComponent()
+	protected final void internalRenderComponent()
 	{
 		final IMarkupFragment markup = getMarkup();
 		if (markup == null)
@@ -2698,7 +2587,7 @@ public abstract class Component
 	}
 
 	/**
-	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT.
+	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
 	 * 
 	 * Print to the web response what ever the component wants to contribute to the head section.
 	 * Make sure that all attached behaviors are asked as well.
@@ -3645,7 +3534,7 @@ public abstract class Component
 	protected void checkHierarchyChange(final Component component)
 	{
 		// Throw exception if modification is attempted during rendering
-		if (getFlag(FLAG_RENDERING) && !component.isAuto())
+		if (getRequestFlag(RFLAG_RENDERING) && !component.isAuto())
 		{
 			throw new WicketRuntimeException(
 				"Cannot modify component hierarchy after render phase has started (page version cant change then anymore)");
@@ -3876,15 +3765,16 @@ public abstract class Component
 	}
 
 	/**
-	 * Called just after a component is rendered.
+	 * Called immediately after a component and all its children have been rendered,
+	 * regardless of any exception.
 	 */
 	protected void onAfterRender()
 	{
-		setFlag(FLAG_AFTER_RENDERING, false);
+		setRequestFlag(RFLAG_AFTER_RENDERING, false);
 	}
 
 	/**
-	 * Called just before a component is rendered only if the component is visible.
+	 * Called on all visible components before any component is rendered.
 	 * <p>
 	 * <strong>NOTE</strong>: If you override this, you *must* call super.onBeforeRender() within
 	 * your implementation.
@@ -3900,7 +3790,6 @@ public abstract class Component
 	 */
 	protected void onBeforeRender()
 	{
-		setFlag(FLAG_PREPARED_FOR_RENDER, true);
 		onBeforeRenderChildren();
 		setRequestFlag(RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED, true);
 	}
@@ -3958,7 +3847,7 @@ public abstract class Component
 	 */
 	protected void onDetach()
 	{
-		setFlag(FLAG_DETACHING, false);
+		setRequestFlag(RFLAG_DETACHING, false);
 	}
 
 	/**
@@ -3969,7 +3858,7 @@ public abstract class Component
 	 */
 	protected void onRemove()
 	{
-		setFlag(FLAG_REMOVING_FROM_HIERARCHY, false);
+		setRequestFlag(RFLAG_REMOVING_FROM_HIERARCHY, false);
 	}
 
 	/**
@@ -4161,14 +4050,12 @@ public abstract class Component
 	}
 
 	/**
-	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
-	 * 
 	 * @param flag
 	 *            The flag to set
 	 * @param set
 	 *            True to turn the flag on, false to turn it off
 	 */
-	protected final Component setRequestFlag(final short flag, final boolean set)
+	final Component setRequestFlag(final short flag, final boolean set)
 	{
 		if (set)
 		{
@@ -4245,18 +4132,6 @@ public abstract class Component
 	}
 
 	/**
-	 * @param setRenderingFlag
-	 *            rendering flag
-	 */
-	void internalMarkRendering(boolean setRenderingFlag)
-	{
-		// WICKET-5460 no longer prepared for render
-		setFlag(FLAG_PREPARED_FOR_RENDER, false);
-
-		setFlag(FLAG_RENDERING, setRenderingFlag);
-	}
-
-	/**
 	 * @return True if this component or any of its parents is in auto-add mode
 	 */
 	public final boolean isAuto()
@@ -4278,14 +4153,7 @@ public abstract class Component
 	 */
 	boolean isPreparedForRender()
 	{
-		return getFlag(FLAG_PREPARED_FOR_RENDER);
-	}
-
-	/**
-	 * 
-	 */
-	protected void onAfterRenderChildren()
-	{
+		return getRequestFlag(RFLAG_PREPARED_FOR_RENDER);
 	}
 
 	/**
@@ -4474,7 +4342,7 @@ public abstract class Component
 	 */
 	public final boolean isRendering()
 	{
-		return getFlag(FLAG_RENDERING);
+		return getRequestFlag(RFLAG_RENDERING);
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
index 36b7684..aad0aac 100644
--- a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
+++ b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
@@ -1694,17 +1694,6 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp
 		}
 	}
 
-	@Override
-	void internalMarkRendering(boolean setRenderingFlag)
-	{
-		super.internalMarkRendering(setRenderingFlag);
-
-		for (Component child : this)
-		{
-			child.internalMarkRendering(setRenderingFlag);
-		}
-	}
-
 	/**
 	 * @return a copy of the children array.
 	 */
@@ -1793,17 +1782,6 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp
 	}
 
 	@Override
-	protected void onAfterRenderChildren()
-	{
-		for (Component child : this)
-		{
-			// set RENDERING_FLAG to false for auto-component's children (like Enclosure)
-			child.markRendering(false);
-		}
-		super.onAfterRenderChildren();
-	}
-
-	@Override
 	protected void onDetach()
 	{
 		super.onDetach();

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/main/java/org/apache/wicket/Page.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/Page.java b/wicket-core/src/main/java/org/apache/wicket/Page.java
index fb4f04d..9b8dc7f 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Page.java
+++ b/wicket-core/src/main/java/org/apache/wicket/Page.java
@@ -24,6 +24,7 @@ import java.util.Set;
 
 import org.apache.wicket.authorization.UnauthorizedActionException;
 import org.apache.wicket.core.util.lang.WicketObjects;
+import org.apache.wicket.feedback.FeedbackDelay;
 import org.apache.wicket.markup.MarkupException;
 import org.apache.wicket.markup.MarkupStream;
 import org.apache.wicket.markup.MarkupType;
@@ -229,14 +230,15 @@ public abstract class Page extends MarkupContainer
 	}
 
 	@Override
-	public void internalPrepareForRender(boolean setRenderingFlag)
+	protected void onConfigure()
 	{
 		if (!isInitialized())
 		{
 			// initialize the page if not yet initialized
 			internalInitialize();
 		}
-		super.internalPrepareForRender(setRenderingFlag);
+		
+		super.onConfigure();
 	}
 
 	/**
@@ -300,14 +302,14 @@ public abstract class Page extends MarkupContainer
 	}
 
 	/**
-	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL.
-	 * 
-	 * This method is called when a component was rendered standalone. If it is a <code>
+	 * This method is called when a component was rendered as a part. If it is a <code>
 	 * MarkupContainer</code> then the rendering for that container is checked.
 	 * 
 	 * @param component
+	 * 
+	 * @see Component#renderPart()
 	 */
-	public final void endComponentRender(Component component)
+	final void endComponentRender(Component component)
 	{
 		if (component instanceof MarkupContainer)
 		{
@@ -527,14 +529,13 @@ public abstract class Page extends MarkupContainer
 	}
 
 	/**
-	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL.
-	 * 
-	 * This method is called when a component will be rendered standalone.
+	 * This method is called when a component will be rendered as a part.
 	 * 
 	 * @param component
 	 * 
+	 * @see Component#renderPart()
 	 */
-	public final void startComponentRender(Component component)
+	final void startComponentRender(Component component)
 	{
 		renderedComponents = null;
 	}
@@ -984,9 +985,17 @@ public abstract class Page extends MarkupContainer
 		try
 		{
 			++renderCount;
-			render();
 
-			// stateless = null;
+			FeedbackDelay delay = new FeedbackDelay(getRequestCycle());
+			try {
+				beforeRender();
+				
+				delay.beforeRender();
+			} finally {
+				delay.release();
+			}
+
+			render();
 		}
 		finally
 		{
@@ -1004,5 +1013,4 @@ public abstract class Page extends MarkupContainer
 	{
 		return renderedComponents != null && renderedComponents.contains(component);
 	}
-
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/main/java/org/apache/wicket/core/request/handler/ComponentRenderingRequestHandler.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/ComponentRenderingRequestHandler.java b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/ComponentRenderingRequestHandler.java
index 1636707..e6d5874 100644
--- a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/ComponentRenderingRequestHandler.java
+++ b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/ComponentRenderingRequestHandler.java
@@ -64,13 +64,8 @@ public class ComponentRenderingRequestHandler implements IComponentRequestHandle
 			response.disableCaching();
 		}
 
-		Page page = component.getPage();
-
-		page.startComponentRender(component);
-
-		component.render();
-
-		page.endComponentRender(component);
+		component.beforeRender();
+		component.renderPart();
 	}
 
 	@Override

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/main/java/org/apache/wicket/core/request/handler/PageAndComponentProvider.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/PageAndComponentProvider.java b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/PageAndComponentProvider.java
index 8bdfa93..de59ecc 100644
--- a/wicket-core/src/main/java/org/apache/wicket/core/request/handler/PageAndComponentProvider.java
+++ b/wicket-core/src/main/java/org/apache/wicket/core/request/handler/PageAndComponentProvider.java
@@ -169,7 +169,7 @@ public class PageAndComponentProvider extends PageProvider implements IPageAndCo
 				{
 					Page p = (Page)page;
 					p.internalInitialize();
-					p.internalPrepareForRender(false);
+					p.beforeRender();
 					component = page.get(componentPath);
 				}
 			}

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/main/java/org/apache/wicket/core/util/string/ComponentRenderer.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/string/ComponentRenderer.java b/wicket-core/src/main/java/org/apache/wicket/core/util/string/ComponentRenderer.java
index d583057..9104eb9 100644
--- a/wicket-core/src/main/java/org/apache/wicket/core/util/string/ComponentRenderer.java
+++ b/wicket-core/src/main/java/org/apache/wicket/core/util/string/ComponentRenderer.java
@@ -416,7 +416,8 @@ public class ComponentRenderer
 			RenderPage page = new RenderPage(component);
 			page.internalInitialize();
 
-			component.render();
+			component.beforeRender();
+			component.renderPart();
 		}
 		finally
 		{

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/main/java/org/apache/wicket/feedback/FeedbackDelay.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/feedback/FeedbackDelay.java b/wicket-core/src/main/java/org/apache/wicket/feedback/FeedbackDelay.java
new file mode 100644
index 0000000..4d0ef30
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/feedback/FeedbackDelay.java
@@ -0,0 +1,119 @@
+/*
+ * 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.feedback;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.Page;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.request.cycle.RequestCycle;
+
+/**
+ * Postpone calling {@link IFeedback#beforeRender()} after other components.
+ * <p>
+ * This gives other {@link Component#beforeRender()} the possibility to report feedbacks,
+ * which can then be collected by {@link IFeedback}s afterwards.
+ */
+public class FeedbackDelay implements Serializable
+{
+	private static final MetaDataKey<FeedbackDelay> KEY = new MetaDataKey<FeedbackDelay>()
+	{
+		private static final long serialVersionUID = 1L;
+	};
+	
+	private List<IFeedback> feedbacks = new ArrayList<>();
+
+	private RequestCycle cycle;
+	
+	/**
+	 * Delay all feedbacks for the given cycle.
+	 * <p>
+	 * All postponed feedbacks will be prepared for render with {@link #beforeRender()}.
+	 * 
+	 * @param cycle
+	 *            request cycle
+	 */
+	public FeedbackDelay(RequestCycle cycle) {
+		if (get(cycle).isPresent()) {
+			throw new WicketRuntimeException("feedbacks are already delayed");
+		}
+		
+		cycle.setMetaData(KEY, this);
+		
+		this.cycle = cycle;
+	}
+	
+	/**
+	 * Get the current delay.
+	 * 
+	 * @param cycle
+	 * @return optional delay
+	 */
+	public static Optional<FeedbackDelay> get(RequestCycle cycle) {
+		return Optional.ofNullable(cycle.getMetaData(KEY));
+	}
+
+	/**
+	 * Postpone {@link Component#beforeRender()} on the given feedback.
+	 * 
+	 * @param feedback
+	 * @return
+	 */
+	public FeedbackDelay postpone(IFeedback feedback) {
+		feedbacks.add(feedback);
+		
+		return this;
+	}
+
+	/**
+	 * Prepares all postponed feedbacks for render.
+	 * 
+	 * @see IFeedback#beforeRender()
+	 */
+	public void beforeRender() {
+		cycle.setMetaData(KEY, null);
+		cycle = null;
+		
+		for (IFeedback feedback : feedbacks)
+		{
+			if (feedback instanceof Component) {
+				Component component = (Component)feedback;
+				
+				// render only if it is still in the page hierarchy (WICKET-4895)
+				if (component.findParent(Page.class) == null)
+				{
+					continue;
+				}			
+			}
+		
+			feedback.beforeRender();
+		}
+	}
+	
+	public void release() {
+		if (cycle != null) {
+			cycle.setMetaData(KEY, null);
+			cycle = null;
+			feedbacks.clear();
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/main/java/org/apache/wicket/feedback/IFeedback.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/feedback/IFeedback.java b/wicket-core/src/main/java/org/apache/wicket/feedback/IFeedback.java
index a1bd08c..6e0085e 100644
--- a/wicket-core/src/main/java/org/apache/wicket/feedback/IFeedback.java
+++ b/wicket-core/src/main/java/org/apache/wicket/feedback/IFeedback.java
@@ -20,12 +20,13 @@ package org.apache.wicket.feedback;
  * Interface for components that present some kind of feedback to the user, normally based on the
  * feedback messages attached to various components on a given page.
  * 
- * This is basically a marker interface that tells Wicket that this component's onBeforeRender
- * method must be called after all non feedback components have been initialized.
+ * This is tells Wicket that a component's {@link Component#beforeRender()} must be called after all non
+ * feedback components have been initialized.
  * 
  * @author Jonathan Locke
  * @author Eelco Hillenius
  */
 public interface IFeedback
 {
+	void beforeRender();
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/main/java/org/apache/wicket/page/PartialPageUpdate.java
----------------------------------------------------------------------
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 2bef5e2..caec116 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
@@ -28,6 +28,7 @@ import javax.servlet.http.Cookie;
 
 import org.apache.wicket.Component;
 import org.apache.wicket.Page;
+import org.apache.wicket.feedback.FeedbackDelay;
 import org.apache.wicket.markup.head.HeaderItem;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.IWrappedHeaderItem;
@@ -238,19 +239,36 @@ public abstract class PartialPageUpdate
 	{
 		componentsFrozen = true;
 
-		// process component markup
-		for (Map.Entry<String, Component> stringComponentEntry : markupIdToComponent.entrySet())
-		{
-			final Component component = stringComponentEntry.getValue();
-
-			if (!containsAncestorFor(component))
+		List<Component> prepared = new ArrayList<>(markupIdToComponent.size());
+		
+		// prepare components
+		FeedbackDelay delay = new FeedbackDelay(RequestCycle.get());
+		try {
+			for (Component component : markupIdToComponent.values())
 			{
-				writeComponent(response, component.getAjaxRegionMarkupId(), component, encoding);
+				if (!containsAncestorFor(component))
+				{
+					prepareComponent(component);
+					prepared.add(component);
+				}
 			}
+
+			// .. now prepare all postponed feedbacks
+			delay.beforeRender();
+		} finally {
+			delay.release();
+		}
+
+		// write components
+		for (Component component : prepared)
+		{
+			writeComponent(response, component.getAjaxRegionMarkupId(), component, encoding);
 		}
 
 		if (header != null)
 		{
+			RequestCycle cycle = RequestCycle.get();
+			
 			// some header responses buffer all calls to render*** until close is called.
 			// when they are closed, they do something (i.e. aggregate all JS resource urls to a
 			// single url), and then "flush" (by writing to the real response) before closing.
@@ -258,14 +276,14 @@ public abstract class PartialPageUpdate
 			// tag, which we do here:
 			headerRendering = true;
 			// save old response, set new
-			Response oldResponse = RequestCycle.get().setResponse(headerBuffer);
+			Response oldResponse = cycle.setResponse(headerBuffer);
 			headerBuffer.reset();
 
 			// now, close the response (which may render things)
 			header.getHeaderResponse().close();
 
 			// revert to old response
-			RequestCycle.get().setResponse(oldResponse);
+			cycle.setResponse(oldResponse);
 
 			// write the XML tags and we're done
 			writeHeaderContribution(response);
@@ -274,6 +292,44 @@ public abstract class PartialPageUpdate
 	}
 
 	/**
+	 * Prepare a single component
+	 *
+	 * @param component
+	 *      the component to prepare
+	 */
+	protected void prepareComponent(Component component)
+	{
+		if (component.getRenderBodyOnly() == true)
+		{
+			throw new IllegalStateException(
+					"A partial update is not possible for a component that has renderBodyOnly enabled. Component: " +
+							component.toString());
+		}
+
+		component.setOutputMarkupId(true);
+
+		// Initialize temporary variables
+		final Page page = component.findParent(Page.class);
+		if (page == null)
+		{
+			// dont throw an exception but just ignore this component, somehow
+			// it got removed from the page.
+			LOG.warn("Component '{}' not rendered because it was already removed from page", component);
+			return;
+		}
+
+		try
+		{
+			component.beforeRender();
+		}
+		catch (RuntimeException e)
+		{
+			bodyBuffer.reset();
+			throw e;
+		}
+	}
+
+	/**
 	 * Writes a single component
 	 *
 	 * @param response

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/main/java/org/apache/wicket/page/XmlPartialPageUpdate.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/XmlPartialPageUpdate.java b/wicket-core/src/main/java/org/apache/wicket/page/XmlPartialPageUpdate.java
index 28c2ffa..5f78ef3 100644
--- a/wicket-core/src/main/java/org/apache/wicket/page/XmlPartialPageUpdate.java
+++ b/wicket-core/src/main/java/org/apache/wicket/page/XmlPartialPageUpdate.java
@@ -59,29 +59,11 @@ public class XmlPartialPageUpdate extends PartialPageUpdate
 		response.write("\"?>");
 		response.write(START_ROOT_ELEMENT);
 	}
-
+	
 	@Override
 	protected void writeComponent(Response response, String markupId, Component component, String encoding)
 	{
-		if (component.getRenderBodyOnly() == true)
-		{
-			throw new IllegalStateException(
-					"A partial update is not possible for a component that has renderBodyOnly enabled. Component: " +
-							component.toString());
-		}
-
-		component.setOutputMarkupId(true);
-
-		// Initialize temporary variables
 		final Page page = component.findParent(Page.class);
-		if (page == null)
-		{
-			// dont throw an exception but just ignore this component, somehow
-			// it got removed from the page.
-			LOG.warn("Component '{}' with markupid: '{}' not rendered because it was already removed from page",
-					component, markupId);
-			return;
-		}
 
 		// substitute our encoding response for the old one so we can capture
 		// component's markup in a manner safe for transport inside CDATA block
@@ -89,42 +71,20 @@ public class XmlPartialPageUpdate extends PartialPageUpdate
 
 		try
 		{
+			// render any associated headers of the component
+			writeHeaderContribution(response, component);
+			
 			bodyBuffer.reset();
 			
-			page.startComponentRender(component);
-
-			try
-			{
-				component.prepareForRender();
-
-				// render any associated headers of the component
-				writeHeaderContribution(response, component);
-			}
-			catch (RuntimeException e)
-			{
-				try
-				{
-					component.afterRender();
-				}
-				catch (RuntimeException e2)
-				{
-					// ignore this one could be a result off.
-				}
-				bodyBuffer.reset();
-				throw e;
-			}
-
 			try
 			{
-				component.render();
+				component.renderPart();
 			}
 			catch (RuntimeException e)
 			{
 				bodyBuffer.reset();
 				throw e;
 			}
-
-			page.endComponentRender(component);
 		}
 		finally
 		{

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbackRenderTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbackRenderTest.java b/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbackRenderTest.java
index 8f0f7cb..c12fb2a 100644
--- a/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbackRenderTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbackRenderTest.java
@@ -36,7 +36,25 @@ public class FeedbackRenderTest extends WicketTestCase
 
 		tester.startPage(page);
 
-		// non-IFeedback first, then IFeedback from nested to top
-		assertEquals("|id4|id3|id2|id1", page.onBeforeRenderOrder.toString());
+		// non-IFeedback first, then IFeedback top-down
+		assertEquals("|id4|id1|id2|id3", page.onBeforeRenderOrder.toString());
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	@Test
+	public void testAjax() throws Exception
+	{
+		final FeedbacksPage page = new FeedbacksPage();
+
+		tester.startPage(page);
+		
+		page.onBeforeRenderOrder.setLength(0);
+
+		tester.executeAjaxEvent(page.getAjaxLink(), "click");
+		
+		// non-IFeedback first, then IFeedback top-down
+		assertEquals("|id4|id1|id2|id3", page.onBeforeRenderOrder.toString());
 	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbacksPage.html
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbacksPage.html b/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbacksPage.html
index 8d9000f..bc6c4f1 100644
--- a/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbacksPage.html
+++ b/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbacksPage.html
@@ -14,14 +14,20 @@
 -->
 <html>
 <body>
-<span wicket:id="id1">
-	<span wicket:id="id2">
-		<span wicket:id="id3">
+<span wicket:id="feedbacks">
+	<span wicket:id="id1">
+		<span wicket:id="id2">
+			<span wicket:id="id3">
+			</span>
 		</span>
-	</span>
-</span>	
+	</span>	
+</span>
 
 <span wicket:id="id4">
 </span>
+
+<span wicket:id="ajax">
+</span>
+
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbacksPage.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbacksPage.java b/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbacksPage.java
index 840495c..50c920f 100644
--- a/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbacksPage.java
+++ b/wicket-core/src/test/java/org/apache/wicket/feedback/FeedbacksPage.java
@@ -16,6 +16,8 @@
  */
 package org.apache.wicket.feedback;
 
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.WebPage;
 
@@ -28,13 +30,18 @@ public class FeedbacksPage extends WebPage
 
 	public final StringBuilder onBeforeRenderOrder = new StringBuilder();
 
+	private AjaxLink<Void> ajaxLink;
+
 	/**
 	 */
 	public FeedbacksPage()
 	{
-
+		WebMarkupContainer feedbacks = new WebMarkupContainer("feedbacks");
+		feedbacks.setOutputMarkupId(true);
+		add(feedbacks);
+		
 		Impl impl1 = new FeedbackImpl("id1");
-		add(impl1);
+		feedbacks.add(impl1);
 
 		Impl impl2 = new FeedbackImpl("id2");
 		impl1.add(impl2);
@@ -43,7 +50,25 @@ public class FeedbacksPage extends WebPage
 		impl2.add(impl3);
 
 		Impl impl4 = new Impl("id4");
+		impl4.setOutputMarkupId(true);
 		add(impl4);
+		
+		ajaxLink = new AjaxLink<Void>("ajax")
+		{
+			@Override
+			public void onClick(AjaxRequestTarget target)
+			{
+				// feedbacks added first, but should be prepared last
+				target.add(feedbacks);
+				target.add(impl4);
+			}
+		};
+		add(ajaxLink);
+	}
+	
+	public AjaxLink<Void> getAjaxLink()
+	{
+		return ajaxLink;
 	}
 
 	private class Impl extends WebMarkupContainer
@@ -76,4 +101,4 @@ public class FeedbacksPage extends WebPage
 			super(id);
 		}
 	}
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/EnclosurePage_1.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/EnclosurePage_1.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/EnclosurePage_1.java
index 650bdbf..22a4a3f 100644
--- a/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/EnclosurePage_1.java
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/EnclosurePage_1.java
@@ -29,23 +29,53 @@ import org.apache.wicket.markup.html.basic.Label;
 public class EnclosurePage_1 extends WebPage
 {
 	private static final long serialVersionUID = 1L;
+	
+	public int pendingAfterRenderCount = 0; 
 
 	/**
 	 * Construct.
 	 */
 	public EnclosurePage_1()
 	{
-		add(new Label("label1", "Test Label 1"));
-		add(new Label("label2", "Test Label 2"));
-		add(new Label("label3", "Test Label 3").setVisible(false));
-		add(new Label("label4", "Test Label 2"));
-		add(new Label("label5", "Test Label 2"));
-		add(new Label("label6", "Test Label 2"));
-		add(new Label("label7", "Test Label 2"));
+		add(new AfterRenderCountingLabel("label1", "Test Label 1"));
+		add(new AfterRenderCountingLabel("label2", "Test Label 2"));
+		add(new AfterRenderCountingLabel("label3", "Test Label 3").setVisible(false));
+		add(new AfterRenderCountingLabel("label4", "Test Label 2"));
+		add(new AfterRenderCountingLabel("label5", "Test Label 2"));
+		add(new AfterRenderCountingLabel("label6", "Test Label 2"));
+		add(new AfterRenderCountingLabel("label7", "Test Label 2"));
+		
 		WebMarkupContainer container = new WebMarkupContainer("container");
 		add(container);
-		container.add(new Label("label8", "Test Label 2"));
-		add(new Label("label9", "Test Label 2"));
-		add(new Label("label10", "Test Label 3"));
+		
+		container.add(new AfterRenderCountingLabel("label8", "Test Label 2"));
+		
+		add(new AfterRenderCountingLabel("label9", "Test Label 2"));
+		add(new AfterRenderCountingLabel("label10", "Test Label 3"));
+	}
+	
+	class AfterRenderCountingLabel extends Label {
+
+		public AfterRenderCountingLabel(String id, String model)
+		{
+			super(id, model);
+		}
+		
+		@Override
+		protected void onBeforeRender()
+		{
+			super.onBeforeRender();
+			
+			
+			pendingAfterRenderCount++;
+		}
+		
+		@Override
+		protected void onAfterRender()
+		{
+			super.onAfterRender();
+			
+			pendingAfterRenderCount--;
+		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/c27a57b3/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/EnclosureTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/EnclosureTest.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/EnclosureTest.java
index a34ea5c..7067c7d 100644
--- a/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/EnclosureTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/EnclosureTest.java
@@ -52,6 +52,10 @@ public class EnclosureTest extends WicketTestCase
 	public void testRenderHomePage() throws Exception
 	{
 		executeTest(EnclosurePage_1.class, "EnclosurePageExpectedResult_1.html");
+		
+		EnclosurePage_1 page = (EnclosurePage_1)tester.getLastRenderedPage();
+		
+		assertEquals(0, page.pendingAfterRenderCount);
 	}
 
 	/**


[10/16] wicket git commit: WICKET-6517 new AjaxFileDropBehavior

Posted by sv...@apache.org.
WICKET-6517 new AjaxFileDropBehavior


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 237147fee94e7fb2c0e91216aee0e4a51b448c30
Parents: 44fb374
Author: Sven Meier <sv...@apache.org>
Authored: Wed Jan 17 09:23:27 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Fri Jan 26 23:09:37 2018 +0100

----------------------------------------------------------------------
 .../examples/ajax/builtin/FileUploadPage.java   |   4 +-
 .../ajax/markup/html/AjaxFileDropBehavior.java  | 160 +++++++++++++++++++
 .../markup/html/AjaxFileUploadBehavior.java     | 156 ------------------
 3 files changed, 162 insertions(+), 158 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/237147fe/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
----------------------------------------------------------------------
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
index ca6dc70..7399301 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
@@ -21,7 +21,7 @@ import java.util.List;
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
-import org.apache.wicket.extensions.ajax.markup.html.AjaxFileUploadBehavior;
+import org.apache.wicket.extensions.ajax.markup.html.AjaxFileDropBehavior;
 import org.apache.wicket.extensions.ajax.markup.html.form.upload.UploadProgressBar;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
@@ -116,7 +116,7 @@ public class FileUploadPage extends BasePage
 		});
 		
 		WebMarkupContainer drop = new WebMarkupContainer("drop");
-		drop.add(new AjaxFileUploadBehavior() {
+		drop.add(new AjaxFileDropBehavior() {
 			protected void onFileUpload(AjaxRequestTarget target, List<FileUpload> files) {
 			    
 				// display uploaded info

http://git-wip-us.apache.org/repos/asf/wicket/blob/237147fe/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
new file mode 100644
index 0000000..9073cd3
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
@@ -0,0 +1,160 @@
+/*
+ * 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.extensions.ajax.markup.html;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.markup.html.form.upload.FileUpload;
+import org.apache.wicket.protocol.http.servlet.MultipartServletWebRequest;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.request.resource.PackageResourceReference;
+import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.lang.Bytes;
+
+/**
+ * Uploads files from a drop event.
+ *
+ * @author Andrew Kondratev
+ * @author svenmeier
+ */
+public class AjaxFileDropBehavior extends AjaxEventBehavior
+{
+
+	private static final ResourceReference JS = new PackageResourceReference(AjaxFileDropBehavior.class, "datatransfer.js");
+
+	/**
+	 *  Maximum size of all uploaded files in bytes in a request.
+	 */
+	private Bytes maxSize;
+
+	/**
+	 *  Maximum size of file of upload in bytes (if there are more than one) in a request.
+	 */
+	private Bytes fileMaxSize;
+
+	private String parameterName = "f";
+	
+	public AjaxFileDropBehavior()
+	{
+		super("drop");
+	}
+	
+	@Override
+	public void renderHead(Component component, IHeaderResponse response)
+	{
+		super.renderHead(component, response);
+		
+		response.render(JavaScriptHeaderItem.forReference(JS));
+		
+		// default must be prevented for dragover event, otherwise browser will consume the dataTransfer
+		response.render(OnDomReadyHeaderItem.forScript(String.format("jQuery('#%s').on('dragover', function(e) { e.preventDefault(); });", component.getMarkupId())));
+	}
+
+	@Override
+	protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
+	{
+		super.updateAjaxAttributes(attributes);
+
+		attributes.setMultipart(true);
+		attributes.setMethod(Method.POST);
+		// default must be prevented, otherwise browser will consume the dataTransfer
+		attributes.setPreventDefault(true);
+
+		attributes.getDynamicExtraParameters().add(
+			String.format("return Wicket.DataTransfer.getFilesAsParamArray(attrs.event.originalEvent, '%s');", parameterName)
+		);
+	}
+
+	@Override
+	protected void onEvent(AjaxRequestTarget target)
+	{
+		try
+		{
+			ServletWebRequest request = (ServletWebRequest)getComponent().getRequest();
+			final MultipartServletWebRequest multipartWebRequest = request.newMultipartWebRequest(
+				getMaxSize(), getComponent().getPage().getId());
+			multipartWebRequest.setFileMaxSize(getFileMaxSize());
+			multipartWebRequest.parseFileParts();
+
+			// TODO: Can't this be detected from header?
+			getComponent().getRequestCycle().setRequest(multipartWebRequest);
+			
+			ArrayList<FileUpload> fileUploads = new ArrayList<>();
+
+			// Get the item for the path
+			final List<FileItem> fileItems = multipartWebRequest.getFile(parameterName);
+
+			if (fileItems != null)
+			{
+				for (FileItem item : fileItems)
+				{
+					fileUploads.add(new FileUpload(item));
+				}
+			}
+			
+			onFileUpload(target, fileUploads);
+		}
+		catch (final FileUploadException fux)
+		{
+			onError(fux);
+		}
+	}
+
+	public Bytes getMaxSize()
+	{
+		if (maxSize == null) {
+			maxSize = getComponent().getApplication().getApplicationSettings().getDefaultMaximumUploadSize();
+		}
+		return maxSize;
+	}
+
+	public void setMaxSize(Bytes maxSize)
+	{
+		Args.notNull(maxSize, "maxSize");
+		this.maxSize = maxSize;
+	}
+
+	public Bytes getFileMaxSize()
+	{
+		return fileMaxSize;
+	}
+
+	public void setFileMaxSize(Bytes fileMaxSize)
+	{
+		this.fileMaxSize = fileMaxSize;
+	}
+	
+	protected void onFileUpload(AjaxRequestTarget target, List<FileUpload> files)
+	{
+	}
+
+	protected void onError(FileUploadException fux)
+	{
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/237147fe/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileUploadBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileUploadBehavior.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileUploadBehavior.java
deleted file mode 100644
index 3801c62..0000000
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileUploadBehavior.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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.extensions.ajax.markup.html;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.FileUploadException;
-import org.apache.wicket.Component;
-import org.apache.wicket.ajax.AjaxEventBehavior;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
-import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.JavaScriptHeaderItem;
-import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
-import org.apache.wicket.markup.html.form.upload.FileUpload;
-import org.apache.wicket.protocol.http.servlet.MultipartServletWebRequest;
-import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
-import org.apache.wicket.request.resource.PackageResourceReference;
-import org.apache.wicket.request.resource.ResourceReference;
-import org.apache.wicket.util.lang.Args;
-import org.apache.wicket.util.lang.Bytes;
-
-/**
- * Uploads files from a drop event.
- * 
- * @author svenmeier
- */
-public class AjaxFileUploadBehavior extends AjaxEventBehavior
-{
-
-	private static final ResourceReference JS = new PackageResourceReference(AjaxFileUploadBehavior.class, "datatransfer.js");
-
-	/**
-	 *  Maximum size of all uploaded files in bytes in a request.
-	 */
-	private Bytes maxSize;
-
-	/**
-	 *  Maximum size of file of upload in bytes (if there are more than one) in a request.
-	 */
-	private Bytes fileMaxSize;
-
-	private String parameterName = "f";
-	
-	public AjaxFileUploadBehavior()
-	{
-		super("drop");
-	}
-	
-	@Override
-	public void renderHead(Component component, IHeaderResponse response)
-	{
-		super.renderHead(component, response);
-		
-		response.render(JavaScriptHeaderItem.forReference(JS));
-		
-		// default must be prevented for dragover event, otherwise browser will consume the dataTransfer
-		response.render(OnDomReadyHeaderItem.forScript(String.format("jQuery('#%s').on('dragover', function(e) { e.preventDefault(); });", component.getMarkupId())));
-	}
-
-	@Override
-	protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
-	{
-		super.updateAjaxAttributes(attributes);
-
-		attributes.setMultipart(true);
-		attributes.setMethod(Method.POST);
-		// default must be prevented, otherwise browser will consume the dataTransfer
-		attributes.setPreventDefault(true);
-
-		attributes.getDynamicExtraParameters().add(
-			String.format("return Wicket.DataTransfer.getFilesAsParamArray(attrs.event.originalEvent, '%s');", parameterName)
-		);
-	}
-
-	@Override
-	protected void onEvent(AjaxRequestTarget target)
-	{
-		try
-		{
-			ServletWebRequest request = (ServletWebRequest)getComponent().getRequest();
-			final MultipartServletWebRequest multipartWebRequest = request.newMultipartWebRequest(
-				getMaxSize(), getComponent().getPage().getId());
-			multipartWebRequest.setFileMaxSize(getFileMaxSize());
-			multipartWebRequest.parseFileParts();
-
-			// TODO: Can't this be detected from header?
-			getComponent().getRequestCycle().setRequest(multipartWebRequest);
-			
-			ArrayList<FileUpload> fileUploads = new ArrayList<>();
-
-			// Get the item for the path
-			final List<FileItem> fileItems = multipartWebRequest.getFile(parameterName);
-
-			if (fileItems != null)
-			{
-				for (FileItem item : fileItems)
-				{
-					fileUploads.add(new FileUpload(item));
-				}
-			}
-			
-			onFileUpload(target, fileUploads);
-		}
-		catch (final FileUploadException fux)
-		{
-			onError(fux);
-		}
-	}
-
-	public Bytes getMaxSize()
-	{
-		return maxSize;
-	}
-
-	public void setMaxSize(Bytes maxSize)
-	{
-		Args.notNull(maxSize, "maxSize");
-		this.maxSize = maxSize;
-	}
-
-	public Bytes getFileMaxSize()
-	{
-		return fileMaxSize;
-	}
-
-	public void setFileMaxSize(Bytes fileMaxSize)
-	{
-		this.fileMaxSize = fileMaxSize;
-	}
-	
-	protected void onFileUpload(AjaxRequestTarget target, List<FileUpload> files)
-	{
-	}
-
-	protected void onError(FileUploadException fux)
-	{
-	}
-}
\ No newline at end of file


[04/16] wicket git commit: WICKET-6503 update component lifecycle

Posted by sv...@apache.org.
WICKET-6503 update component lifecycle


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: eb9f6c9cf3f5b644f9107558751cc38c0a47abc8
Parents: 1617e2b
Author: Sven Meier <sv...@apache.org>
Authored: Fri Jan 19 16:54:19 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Fri Jan 19 16:54:36 2018 +0100

----------------------------------------------------------------------
 .../componentLifecycle_1.adoc                   |  11 +++++----
 .../componentLifecycle_2.adoc                   |   9 ++++----
 .../componentLifecycle_3.adoc                   |   6 +++--
 .../componentLifecycle_4.adoc                   |  23 +++++++++++++++----
 .../componentLifecycle_5.adoc                   |   6 ++---
 .../componentLifecycle_6.adoc                   |   3 ++-
 .../componentLifecycle_7.adoc                   |   5 ++++
 .../main/asciidoc/img/component-lifecycle.png   | Bin 10587 -> 34960 bytes
 wicket-user-guide/src/main/asciidoc/single.adoc |   8 +++++--
 9 files changed, 49 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/eb9f6c9c/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_1.adoc
----------------------------------------------------------------------
diff --git a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_1.adoc b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_1.adoc
index bc38266..a2c778a 100644
--- a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_1.adoc
+++ b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_1.adoc
@@ -1,17 +1,18 @@
 
 
 
-During its life a Wicket component goes through three basic stages:
+During its life a Wicket component goes through the following stages:
 
-1. *Initialization:* a component is instantiated by Wicket and prepared for the rendering phase.
-2. *Rendering:* in this stage Wicket generates component markup. If a component contains children (i.e. is a subclass of _MarkupContainer_) it must first wait for them to be rendered before starting its own rendering. 
-3. *Removing:* this stage is triggered when a component is explicitly removed from its component hierarchy, i.e. when its parent invokes _remove(component)_ on it. This stage is facultative and is never triggered for pages.
+1. *Initialization:* a component is instantiated and initialized by Wicket.
+2. *Rendering:* components are prepared for rendering and generate markup. If a component contains children (i.e. is a subclass of _MarkupContainer_) their rendering result is included in the resulting markup.
+3. *Removed:* this stage is triggered when a component is explicitly removed from its component hierarchy, i.e. when its parent invokes _remove(component)_ on it. This stage is facultative and is never triggered for pages.
+3. *Detached:* after request processing has ended all components are notified to detach any state that is no longer needed. 
 
 The following picture shows the state diagram of component lifecycle:
 
 image::../img/component-lifecycle.png[]
 
-Once a component has been removed it can be added again to a container, but the initialization stage won't be executed again.
+Once a component has been removed it could be added again to a container, but the initialization stage won't be executed again - it is easier to just create a new component instance instead.
 
 NOTE: If you read the JavaDoc of class _Component_ you will find a more detailed description of component lifecycle.
 However this description introduces some advanced topics we didn't covered yet hence, to avoid confusion, in this chapter some details have been omitted and they will be covered later in the next chapters. 

http://git-wip-us.apache.org/repos/asf/wicket/blob/eb9f6c9c/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_2.adoc
----------------------------------------------------------------------
diff --git a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_2.adoc b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_2.adoc
index 7eda2e2..0224dbd 100644
--- a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_2.adoc
+++ b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_2.adoc
@@ -6,9 +6,10 @@ In the following table these methods are grouped according to the stage in which
 
 |===
 |*Cycle stage* | *Involved methods*
-|Initialization | onInitialize
-|Rendering | onConfigure, onBeforeRender, onRender, onComponentTag, onComponentTagBody, onAfterRenderChildren, onAfterRender
-|Removing | onRemove
+|Initialization | constructor, onInitialize()
+|Rendering | onConfigure(), onBeforeRender(), renderHead(), onRender(), onComponentTag(), onComponentTagBody(), onAfterRender()
+|Removed | onRemove()
+|Detached | onDetach()
 |===
 
-Now let's take a closer look at each stage and to at hook methods.
+Now let's take a closer look at each stage and its hook methods.

http://git-wip-us.apache.org/repos/asf/wicket/blob/eb9f6c9c/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_3.adoc
----------------------------------------------------------------------
diff --git a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_3.adoc b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_3.adoc
index cb6593b..5c7a6cd 100644
--- a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_3.adoc
+++ b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_3.adoc
@@ -1,6 +1,8 @@
 
 
 
-This stage is performed at the beginning of the component lifecycle. During initialization, the component has already been inserted into its component hierarchy so we can safely access to its parent container or to its page with methods _getParent()_ or _getPage()_. The only method triggered during this stage is _onInitialize()_. This method is a sort of “special” constructor where we can execute a custom initialization of our component.   
+This stage is the beginning of the component lifecycle.
 
-Since _onInitialize_ is similar to a regular constructor, when we override this method we have to call _super.onInitialize_ inside its body, usually as first instruction.
+A component is instantiated by application code (or by Wicket in case of bookmarkable page) and added to a parental component. As soon as the component is contained in a component tree rooted in a page, a “post”-constructor _onInitialize()_ is called where we can execute custom initialization of our component.
+
+When we override this method we have to call _super.onInitialize()_, usually before anything else in that method.

http://git-wip-us.apache.org/repos/asf/wicket/blob/eb9f6c9c/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_4.adoc
----------------------------------------------------------------------
diff --git a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_4.adoc b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_4.adoc
index a5425d8..4cdd672 100644
--- a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_4.adoc
+++ b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_4.adoc
@@ -1,15 +1,17 @@
 
-This stage is triggered each time a component is rendered by Wicket, typically when its page is requested or when it is refreshed via AJAX.
+This stage is reached each time a component is rendered, typically when a page is requested or when the component or one of its ancestors is refreshed via AJAX.
 
 === Method onConfigure
 
-Method _onConfigure()_ has been introduced in order to provide a good point to manage the component states such as its visibility or enabled state. This method is called before the render phase starts. As stated in <<_hiding_or_disabling_a_component,chapter 6.1>>, _isVisible_ and _isEnabled_ are called multiple times when a page or a component is rendered, so it's highly recommended not to directly override these method, but rather to use _onConfigure_ to change component states. On the contrary method _onBeforeRender_ (see the next paragraph) is not indicated for this task because it will not be invoked if component visibility is set to false.
+Method _onConfigure()_ has been introduced in order to provide a good point to manage the component states such as its visibility or enabled state. This method is called an all components whose parent is visible.
+
+As stated in <<_hiding_or_disabling_a_component,chapter 6.1>>, _isVisible()_ and _isEnabled()_ are called multiple times when a page or a component is rendered, so it's highly recommended not to directly override these method, but rather to use _onConfigure()_ to change component states. On the contrary method _onBeforeRender_ (see the next paragraph) is not indicated for this task because it will not be invoked if component visibility is set to false.
 
 === Method onBeforeRender
 
-The most important hook method of this stage is probably _onBeforeRender()_. This method is called before a component starts its rendering phase and it is our last chance to change its children hierarchy.
+The most important hook method of this stage is probably _onBeforeRender()_. This method is called on all visible components before any of them are rendered. It is our last chance to change a component's state prior to rendering - no change to a component's state is allowed afterwards.
 
-If we want add/remove children components this is the right place to do it. In the next example (project LifeCycleStages) we will create a page which alternately displays two different labels, swapping between them each time it is rendered:
+If we want to add/remove child components this is the right place to do it. In the next example (project LifeCycleStages) we will create a page which alternately displays two different labels, swapping between them each time it is rendered:
 
 [source,java]
 ----
@@ -51,10 +53,17 @@ Please note that in the example above we can trigger the rendering stage pressin
 WARNING: If we forget to call superclass version of methods _onInitialize()_ or _onBeforeRender()_, Wicket will throw an _IllegalStateException_ with the following message: +
 `_java.lang.IllegalStateException: org.apache.wicket.Component has not been properly initialized. Something in the hierarchy of <page class name> has not called super.onInitialize()/onBeforeRender() in the override of onInitialize()/ onBeforeRender() method_`
 
+=== Method renderHead
+
+This method gives all components the possibility to add items to the page header through its argument of type _org.apache.wicket.markup.head.IHeaderResponse_
+
+=== Method onRender
+
+This method does the actual rendering - you will rarely have to implement it, since most components already contain a specific implementation to produce their markup.
 
 === Method onComponentTag
 
-Method _onComponentTag(ComponentTag)_ is called to process component tag, which can be freely manipulated through its argument of type _org.apache.wicket.markup.ComponentTag_. For example we can add/remove tag attributes with methods _put(String key, String value)_ and _remove(String key)_, or we can even decide to change the tag or rename it with method _setName(String)_ (the following code is taken from project OnComponentTagExample):
+Method _onComponentTag(ComponentTag)_ is called to process a component tag, which can be freely manipulated through its argument of type _org.apache.wicket.markup.ComponentTag_. For example we can add/remove tag attributes with methods _put(String key, String value)_ and _remove(String key)_, or we can even decide to change the tag or rename it with method _setName(String)_ (the following code is taken from project OnComponentTagExample):
 
 *Markup code:*
 
@@ -132,3 +141,7 @@ public class HomePage extends WebPage {
 ----
 
 Note that the original version of _onComponentTagBody_ is invoked only when we want to preserve the standard rendering mechanism for the tag's body (in our example this happens when the component is enabled).
+
+=== Methods onAfterRender
+
+Called on each rendered component immediately after it has been rendered - _onAfterRender()_ will even be called when rendering failed with an exception.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/eb9f6c9c/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_5.adoc
----------------------------------------------------------------------
diff --git a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_5.adoc b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_5.adoc
index 5f13e16..c08351b 100644
--- a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_5.adoc
+++ b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_5.adoc
@@ -1,8 +1,8 @@
 
 
 
-This stage is triggered when a component is removed from its container hierarchy. The only hook method for this phase is _onRemove()_. If our component still holds some resources needed during rendering phase, we can override this method to release them.
+This stage is entered when a component is removed from its container hierarchy. The only hook method for this phase is _onRemove()_. If our component still holds some resources needed during rendering phase, we can override this method to release them.
 
-Once a component has been removed we are free to add it again to the same container or to a different one. Starting from version 6.18.0 Wicket added a further hook method called _onReAdd()_ which is triggered every time a previously removed component is re-added to a cointainer.
-Please note that while _onInitialize_ is called only the very first time a component is added, _onReAdd_ is called every time it is re-added after having been removed.
+Once a component has been removed we are free to add it again to the same container or to a different one. Starting from version 6.18.0 Wicket added a further hook method called _onReAdd()_ which is triggered every time a previously removed component is re-added to a container.
+Please note that while _onInitialize()_ is called only the very first time a component is added, _onReAdd()_ is called every time it is re-added after having been removed.
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/eb9f6c9c/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_6.adoc
----------------------------------------------------------------------
diff --git a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_6.adoc b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_6.adoc
index 50fbb17..ff1da28 100644
--- a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_6.adoc
+++ b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_6.adoc
@@ -1,5 +1,6 @@
 
 
 
-In this chapter we have seen which stages compose the lifecycle of Wicket components and which hook methods they provide. Overriding these methods we can dynamically modify the component hierarchy and we can enrich the behavior of our custom components.
+When a request has finished, the page and all its contained components move a the detached stage:
 
+The hook method _onDetach()_ notifies each component that it should release all held resources no longer needed until the next request.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/eb9f6c9c/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_7.adoc
----------------------------------------------------------------------
diff --git a/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_7.adoc b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_7.adoc
new file mode 100644
index 0000000..50fbb17
--- /dev/null
+++ b/wicket-user-guide/src/main/asciidoc/componentLifecycle/componentLifecycle_7.adoc
@@ -0,0 +1,5 @@
+
+
+
+In this chapter we have seen which stages compose the lifecycle of Wicket components and which hook methods they provide. Overriding these methods we can dynamically modify the component hierarchy and we can enrich the behavior of our custom components.
+

http://git-wip-us.apache.org/repos/asf/wicket/blob/eb9f6c9c/wicket-user-guide/src/main/asciidoc/img/component-lifecycle.png
----------------------------------------------------------------------
diff --git a/wicket-user-guide/src/main/asciidoc/img/component-lifecycle.png b/wicket-user-guide/src/main/asciidoc/img/component-lifecycle.png
index 52e09fd..601639a 100644
Binary files a/wicket-user-guide/src/main/asciidoc/img/component-lifecycle.png and b/wicket-user-guide/src/main/asciidoc/img/component-lifecycle.png differ

http://git-wip-us.apache.org/repos/asf/wicket/blob/eb9f6c9c/wicket-user-guide/src/main/asciidoc/single.adoc
----------------------------------------------------------------------
diff --git a/wicket-user-guide/src/main/asciidoc/single.adoc b/wicket-user-guide/src/main/asciidoc/single.adoc
index 4fc1464..0974694 100644
--- a/wicket-user-guide/src/main/asciidoc/single.adoc
+++ b/wicket-user-guide/src/main/asciidoc/single.adoc
@@ -153,14 +153,18 @@ include::componentLifecycle/componentLifecycle_3.adoc[leveloffset=+1]
 
 include::componentLifecycle/componentLifecycle_4.adoc[leveloffset=+1]
 
-=== Removing stage
+=== Removed stage
 
 include::componentLifecycle/componentLifecycle_5.adoc[leveloffset=+1]
 
-=== Summary
+=== Detached stage
 
 include::componentLifecycle/componentLifecycle_6.adoc[leveloffset=+1]
 
+=== Summary
+
+include::componentLifecycle/componentLifecycle_7.adoc[leveloffset=+1]
+
 == Page versioning and caching
 
 include::versioningCaching.adoc[]


[12/16] wicket git commit: WICKET-6523 use behaviorId for timerId

Posted by sv...@apache.org.
WICKET-6523 use behaviorId for timerId


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 23b7a0f5cc27031625f01da8a65ad21b1eae449c
Parents: 15aa06f
Author: Sven Meier <sv...@apache.org>
Authored: Wed Jan 24 22:15:09 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Sat Jan 27 00:02:58 2018 +0100

----------------------------------------------------------------------
 .../wicket/ajax/AbstractAjaxTimerBehavior.java  | 28 +++++++++++++++-----
 .../wicket/ajax/AjaxTimerBehaviorTest.java      |  2 +-
 .../SimpleTestPageExpectedResult-1.html         |  2 +-
 .../SimpleTestPageExpectedResult.html           |  2 +-
 4 files changed, 25 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/23b7a0f5/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 d193691..94407ad 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
@@ -44,6 +44,11 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 	private Duration updateInterval;
 
 	private boolean stopped = false;
+	
+	/**
+	 * Id of timer in JavaScript.
+	 */
+	private String timerId;
 
 	/**
 	 * Construct.
@@ -100,9 +105,13 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 	protected final String getJsTimeoutCall(final Duration updateInterval)
 	{
 		CharSequence js = getCallbackScript();
+		
+		Component component = getComponent();
+		// remember id for timer
+		timerId = component.getMarkupId() + "." + component.getBehaviorId(this);
 
 		return String.format("Wicket.Timer.set('%s', function(){%s}, %d);",
-				getComponent().getMarkupId(), js, updateInterval.getMilliseconds());
+			timerId, js, updateInterval.getMilliseconds());
 	}
 
 	/**
@@ -112,6 +121,9 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 	@Override
 	protected final void respond(final AjaxRequestTarget target)
 	{
+		// timerId is no longer valid after Ajax request
+		timerId = null;
+		
 		if (shouldTrigger())
 		{
 			onTimer(target);
@@ -174,9 +186,13 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 		headerResponse.render(OnLoadHeaderItem.forScript(getJsTimeoutCall(updateInterval)));
 	}
 
-	private void clearTimeout(Component component, IHeaderResponse headerResponse)
+	private void clearTimeout(IHeaderResponse headerResponse)
 	{
-		headerResponse.render(OnLoadHeaderItem.forScript("Wicket.Timer.clear('" + component.getMarkupId() + "');"));
+		if (timerId != null) {
+			headerResponse.render(OnLoadHeaderItem.forScript("Wicket.Timer.clear('" + timerId + "');"));
+						
+			timerId = null; 
+		}
 	}
 
 	/**
@@ -193,7 +209,7 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 
 			if (target != null)
 			{
-				clearTimeout(getComponent(), target.getHeaderResponse());
+				clearTimeout(target.getHeaderResponse());
 			}
 		}
 	}
@@ -201,7 +217,7 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 	@Override
 	public void onRemove(Component component)
 	{
-		component.getRequestCycle().find(IPartialPageRequestHandler.class).ifPresent(target -> clearTimeout(component, target.getHeaderResponse()));
+		component.getRequestCycle().find(IPartialPageRequestHandler.class).ifPresent(target -> clearTimeout(target.getHeaderResponse()));
 	}
 
 	@Override
@@ -209,7 +225,7 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 	{
 		Component component = getComponent();
 		
-		component.getRequestCycle().find(IPartialPageRequestHandler.class).ifPresent(target -> clearTimeout(component, target.getHeaderResponse()));
+		component.getRequestCycle().find(IPartialPageRequestHandler.class).ifPresent(target -> clearTimeout(target.getHeaderResponse()));
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/wicket/blob/23b7a0f5/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 be26eb6..d8c2392 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
@@ -239,7 +239,7 @@ public class AjaxTimerBehaviorTest extends WicketTestCase
 
 		tester.executeBehavior(timer);
 
-		assertMatches("Wicket.Timer.clear", 1);
+		assertMatches("Wicket.Timer.clear", 0);
 		assertMatches("Wicket.Timer.set", 0);
 	}
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/23b7a0f5/wicket-core/src/test/java/org/apache/wicket/ajax/markup/html/componentMap/SimpleTestPageExpectedResult-1.html
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/ajax/markup/html/componentMap/SimpleTestPageExpectedResult-1.html b/wicket-core/src/test/java/org/apache/wicket/ajax/markup/html/componentMap/SimpleTestPageExpectedResult-1.html
index 9a8f5f0..d837064 100644
--- a/wicket-core/src/test/java/org/apache/wicket/ajax/markup/html/componentMap/SimpleTestPageExpectedResult-1.html
+++ b/wicket-core/src/test/java/org/apache/wicket/ajax/markup/html/componentMap/SimpleTestPageExpectedResult-1.html
@@ -11,4 +11,4 @@ Wicket.Ajax.DebugWindow.enabled=true;
 Wicket.Ajax.baseUrl="wicket/bookmarkable/org.apache.wicket.ajax.markup.html.componentMap.SimpleTestPage?0-1.0-testPanel-baseSpan-linja1";
 /*]]]]><![CDATA[>*/
 </script>
-</head>]]></header-contribution><evaluate><![CDATA[(function(){Wicket.Timer.set('linja11', function(){Wicket.Ajax.ajax({"u":"./org.apache.wicket.ajax.markup.html.componentMap.SimpleTestPage?0-1.0-testPanel-baseSpan-linja1","c":"linja11"});}, 2000);})();]]></evaluate></ajax-response>
\ No newline at end of file
+</head>]]></header-contribution><evaluate><![CDATA[(function(){Wicket.Timer.set('linja11.0', function(){Wicket.Ajax.ajax({"u":"./org.apache.wicket.ajax.markup.html.componentMap.SimpleTestPage?0-1.0-testPanel-baseSpan-linja1","c":"linja11"});}, 2000);})();]]></evaluate></ajax-response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/23b7a0f5/wicket-core/src/test/java/org/apache/wicket/ajax/markup/html/componentMap/SimpleTestPageExpectedResult.html
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/ajax/markup/html/componentMap/SimpleTestPageExpectedResult.html b/wicket-core/src/test/java/org/apache/wicket/ajax/markup/html/componentMap/SimpleTestPageExpectedResult.html
index 0eae403..617d53f 100644
--- a/wicket-core/src/test/java/org/apache/wicket/ajax/markup/html/componentMap/SimpleTestPageExpectedResult.html
+++ b/wicket-core/src/test/java/org/apache/wicket/ajax/markup/html/componentMap/SimpleTestPageExpectedResult.html
@@ -17,7 +17,7 @@ Wicket.Ajax.baseUrl="wicket/bookmarkable/org.apache.wicket.ajax.markup.html.comp
 <script type="text/javascript" >
 /*<![CDATA[*/
 Wicket.Event.add(window, "load", function(event) { 
-Wicket.Timer.set('linja11', function(){Wicket.Ajax.ajax({"u":"./org.apache.wicket.ajax.markup.html.componentMap.SimpleTestPage?0-1.0-testPanel-baseSpan-linja1","c":"linja11"});}, 2000);;
+Wicket.Timer.set('linja11.0', function(){Wicket.Ajax.ajax({"u":"./org.apache.wicket.ajax.markup.html.componentMap.SimpleTestPage?0-1.0-testPanel-baseSpan-linja1","c":"linja11"});}, 2000);;
 ;});
 /*]]>*/
 </script>


[14/16] wicket git commit: WICKET-6523 timerId can no longer be used

Posted by sv...@apache.org.
WICKET-6523 timerId can no longer be used

to search for markup owning a timer, but timers will be removed by onRemove() callback anyway


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 63c4ae8d50cb5f119c8a3c772e2fa26c33165125
Parents: 23b7a0f
Author: Sven Meier <sv...@apache.org>
Authored: Wed Jan 24 22:30:31 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Sat Jan 27 00:02:58 2018 +0100

----------------------------------------------------------------------
 .../wicket/ajax/res/js/wicket-ajax-jquery.js    | 48 +++++---------------
 1 file changed, 12 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/63c4ae8d/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
index 67c9a2c..794ccd6 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
@@ -2565,6 +2565,17 @@
 					clearTimeout(Wicket.TimerHandles[timerId]);
 					delete Wicket.TimerHandles[timerId];
 				}
+			},
+			
+			clearAll: function(timerId) {
+				var WTH = Wicket.TimerHandles;
+				if (WTH) {
+					for (var th in WTH) {
+						if (WTH.hasOwnProperty(th)) {
+							Wicket.Timer.clear(th)
+						}
+					}
+				}
 			}
 		}
 	});
@@ -2939,42 +2950,7 @@
 	 * Clear any scheduled Ajax timers when leaving the current page
 	 */
 	Wicket.Event.add(window, "unload", function() {
-		var WTH = Wicket.TimerHandles;
-		if (WTH) {
-			for (var th in WTH) {
-				if (WTH.hasOwnProperty(th)) {
-					window.clearTimeout(WTH[th]);
-					delete WTH[th];
-				}
-			}
-		}
-	});
-
-	/**
-	 * Remove any scheduled timers on the removed element.
-	 * This wont remove the timer for elements which are children of the removed one.
-	 */
-	Wicket.Event.subscribe('/dom/node/removing', function(jqEvent, element) {
-		var id = element.id;
-		if (Wicket.TimerHandles && Wicket.TimerHandles[id]) {
-			window.clearTimeout(Wicket.TimerHandles[id]);
-			delete Wicket.TimerHandles[id];
-		}
-	});
-
-	/**
-	 * Remove any scheduled timers on elements which are no more in the DOM document.
-	 * This removes the timers for all elements which parents have been removed from the DOM.
-	 */
-	Wicket.Event.subscribe('/dom/node/added', function() {
-		if (Wicket.TimerHandles) {
-			for (var timerHandle in Wicket.TimerHandles) {
-				if (Wicket.$$(timerHandle) === false) {
-					window.clearTimeout(timerHandle);
-					delete Wicket.TimerHandles[timerHandle];
-				}
-			}
-		}
+		Wicket.Timer.clearAll();
 	});
 
 })(jQuery);


[08/16] wicket git commit: WICKET-6517 use FormData, removed submitMultipartForm

Posted by sv...@apache.org.
WICKET-6517 use FormData, removed submitMultipartForm


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: f642f4ad4266319731b200e517eadf53fef5a56b
Parents: 1d20044
Author: Sven Meier <sv...@apache.org>
Authored: Fri Jan 12 12:45:55 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Fri Jan 26 23:09:37 2018 +0100

----------------------------------------------------------------------
 .../wicket/ajax/res/js/wicket-ajax-jquery.js    | 234 +++----------------
 wicket-core/src/test/js/ajax.js                 |  28 +--
 2 files changed, 28 insertions(+), 234 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/f642f4ad/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
index d4f3100..801a47d 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
@@ -643,11 +643,6 @@
 
 			we.publish(topic.AJAX_CALL_PRECONDITION, attrs);
 
-			if (attrs.mp) { // multipart form. jQuery.ajax() doesn't help here ...
-				var ret = self.submitMultipartForm(context);
-				return ret;
-			}
-
 			if (attrs.f) {
 				// serialize the form with id == attrs.f
 				var form = Wicket.$(attrs.f);
@@ -658,23 +653,36 @@
 					var scName = attrs.sc;
 					data = data.concat({name: scName, value: 1});
 				}
-
 			} else if (attrs.c && !jQuery.isWindow(attrs.c)) {
 				// serialize just the form component with id == attrs.c
 				var el = Wicket.$(attrs.c);
 				data = data.concat(Wicket.Form.serializeElement(el, attrs.sr));
 			}
 
-			// convert to URL encoded string
-			data = jQuery.param(data);
+			var wwwFormUrlEncoded = undefined; // default
+			if (attrs.mp) {
+				try {
+					var formData = new FormData();
+					for (var i = 0; i < data.length; i++) {
+						formData.append(data[i].name, data[i].value);
+					}
+					
+					data = formData;
+					wwwFormUrlEncoded = false;
+				} catch (exception) {
+					Wicket.Log.error("Ajax multipat not supported:" + exception);
+				}
+			}
 
 			// execute the request
 			var jqXHR = jQuery.ajax({
 				url: attrs.u,
 				type: attrs.m,
 				context: self,
+				processData: wwwFormUrlEncoded,
+				contentType: wwwFormUrlEncoded,
+				
 				beforeSend: function (jqXHR, settings) {
-
 					// collect the dynamic extra parameters
 					if (jQuery.isArray(attrs.dep)) {
 						var queryString,
@@ -831,203 +839,6 @@
 			}
 		},
 
-		/**
-		 * This method serializes a form and sends it as POST body. If the form contains multipart content
-		 * this function will post the form using an iframe instead of the regular ajax call
-		 * and bridge the output - transparently making this work  as if it was an ajax call.
-		 *
-		 * @param {Object} context - the context for the ajax call (request attributes + steps)
-		 */
-		submitMultipartForm: function (context) {
-
-			var attrs = context.attrs;
-
-			var form = Wicket.$(attrs.f);
-			if (!form) {
-				Wicket.Log.error("Wicket.Ajax.Call.submitForm: Trying to submit form with id '" + attrs.f + "' that is not in document.");
-				return;
-			}
-
-			// find root form
-			if (form.tagName.toLowerCase() !== "form") {
-				do {
-					form = form.parentNode;
-				} while(form.tagName.toLowerCase() !== "form" && form !== document.body);
-			}
-
-			if (form.tagName.toLowerCase() !== "form") {
-				Wicket.Log.error("Cannot submit form with id " + attrs.f + " because there is no form element in the hierarchy.");
-				return false;
-			}
-
-			var submittingAttribute = 'data-wicket-submitting';
-
-			if (form.onsubmit && !form.getAttribute(submittingAttribute)) {
-				form.setAttribute(submittingAttribute, submittingAttribute);
-				var retValue = true;
-				try {
-					retValue = form.onsubmit();
-				} finally {
-					form.removeAttribute(submittingAttribute);
-				}
-				if (!retValue) {
-					return;
-				}
-			}
-
-			var originalFormAction = form.action;
-			var originalFormTarget = form.target;
-			var originalFormMethod = form.method;
-			var originalFormEnctype = form.enctype;
-			var originalFormEncoding = form.encoding;
-
-			var iframeName = "wicket-submit-" + ("" + Math.random()).substr(2);
-
-			var iframe = createIFrame(iframeName);
-
-			document.body.appendChild(iframe);
-
-			// reconfigure the form
-			form.target = iframe.name;
-			var separator = (attrs.u.indexOf("?")>-1 ? "&" : "?");
-			form.action = attrs.u + separator + "wicket-ajax=true&wicket-ajax-baseurl=" + Wicket.Form.encode(getAjaxBaseUrl());
-
-			// add the static extra parameters
-			if (attrs.ep) {
-				var extraParametersArray = this._asParamArray(attrs.ep);
-				if (extraParametersArray.length > 0) {
-					var extraParametersQueryString = jQuery.param(extraParametersArray);
-					form.action = form.action + '&' + extraParametersQueryString;
-				}
-			}
-
-			// add the dynamic extra parameters
-			if (jQuery.isArray(attrs.dep)) {
-				var dynamicExtraParameters = this._calculateDynamicParameters(attrs);
-				if (dynamicExtraParameters) {
-					form.action = form.action + '&' + dynamicExtraParameters;
-				}
-			}
-			form.method = 'post';
-			form.enctype = "multipart/form-data";
-			form.encoding = "multipart/form-data";
-
-			// create submitting button element
-			if (attrs.sc) {
-				var $btn = jQuery("<input type='hidden' name='" + attrs.sc + "' id='" + iframe.id + "-btn' value='1'/>");
-				form.appendChild($btn[0]);
-			}
-
-			var we = Wicket.Event;
-			var topic = we.Topic;
-
-			this._executeHandlers(attrs.bsh, attrs, null, null);
-			we.publish(topic.AJAX_CALL_BEFORE_SEND, attrs, null, null);
-
-			if (attrs.i) {
-				// show the indicator
-				Wicket.DOM.showIncrementally(attrs.i);
-			}
-
-			//submit the form into the iframe, response will be handled by the onload callback
-			form.submit();
-
-			this._executeHandlers(attrs.ah, attrs);
-			we.publish(topic.AJAX_CALL_AFTER, attrs);
-
-			// a step to execute in both successful and erroneous completion
-			context.endStep = jQuery.proxy(function(notify) {
-				// remove the iframe and button elements
-				setTimeout(function() {
-					jQuery('#'+iframe.id + '-btn').remove();
-					jQuery(iframe).remove();
-				}, 0);
-
-				var attrs = context.attrs;
-				if (attrs.i && context.isRedirecting !== true) {
-					// hide the indicator
-					Wicket.DOM.hideIncrementally(attrs.i);
-				}
-
-				this._executeHandlers(attrs.coh, attrs, null, null);
-				Wicket.Event.publish(Wicket.Event.Topic.AJAX_CALL_COMPLETE, attrs, null, null);
-
-				this.done(attrs);
-				return FunctionsExecuter.DONE;
-			}, this);
-
-			// an error handler that is used when the connection to the server fails for any reason
-			if (attrs.rt) {
-				context.errorHandle = setTimeout(jQuery.proxy(function () {
-					this.failure(context, null, "No XML response in the IFrame document", "Failure");
-
-					context.steps.push(context.endStep);
-					var executer = new FunctionsExecuter(context.steps);
-					executer.start();
-				}, this), attrs.rt);
-			} else {
-				Wicket.Log.info("Submitting a multipart form without a timeout. " +
-					"Use AjaxRequestAttributes.setRequestTimeout(duration) if need to handle connection timeouts.");
-			}
-
-			// install handler to deal with the ajax response
-			// ... we add the onload event after form submit because chrome fires it prematurely
-			we.add(iframe, "load.handleMultipartComplete", jQuery.proxy(this.handleMultipartComplete, this), context);
-
-
-			// handled, restore state and return true
-			form.action = originalFormAction;
-			form.target = originalFormTarget;
-			form.method = originalFormMethod;
-			form.enctype = originalFormEnctype;
-			form.encoding = originalFormEncoding;
-
-			return true;
-		},
-
-		/**
-		 * Completes the multipart ajax handling started via handleMultipart()
-		 * @param {jQuery.Event} event
-		 */
-		handleMultipartComplete: function (event) {
-
-			var context = event.data,
-				iframe = event.target,
-				envelope;
-
-			if (!isUndef(context.errorHandle)) {
-				clearTimeout(context.errorHandle);
-			}
-
-			// stop the event
-			event.stopPropagation();
-
-			// remove the event
-			jQuery(iframe).off("load.handleMultipartComplete");
-
-			try {
-				envelope = iframe.contentWindow.document;
-			} catch (e) {
-				Wicket.Log.error("Cannot read Ajax response for multipart form submit: " + e);
-			}
-
-			if (isUndef(envelope)) {
-				this.failure(context, null, "No XML response in the IFrame document", "Failure");
-			}
-			else {
-				if (envelope.XMLDocument) {
-					envelope = envelope.XMLDocument;
-				}
-
-				// process the response
-				this.loadedCallback(envelope, context);
-			}
-
-			context.steps.push(context.endStep);
-			var executer = new FunctionsExecuter(context.steps);
-			executer.start();
-		},
-
 		// Processes the response
 		loadedCallback: function (envelope, context) {
 			// To process the response, we go through the xml document and add a function for every action (step).
@@ -1488,9 +1299,16 @@
 			 */
 			serializeInput: function (input) {
 				var result = [];
-				if (input && input.type && !(input.type === 'image' || input.type === 'submit')) {
+				if (input && input.type) {
 					var $input = jQuery(input);
-					result = $input.serializeArray();
+					
+					if (input.type === 'file') {
+						for (var f = 0; f < input.files.length; f++) {
+							result.push({"name" : input.name, "value" : input.files[f]});
+						}
+					} else if (!(input.type === 'image' || input.type === 'submit')) {
+						result = $input.serializeArray();
+					}
 				}
 				return result;
 			},

http://git-wip-us.apache.org/repos/asf/wicket/blob/f642f4ad/wicket-core/src/test/js/ajax.js
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/js/ajax.js b/wicket-core/src/test/js/ajax.js
index 71f9fce..982aa47 100644
--- a/wicket-core/src/test/js/ajax.js
+++ b/wicket-core/src/test/js/ajax.js
@@ -1042,7 +1042,7 @@ jQuery(document).ready(function() {
 		 */
 		asyncTest('Submit nested form - success scenario.', function () {
 
-			expect(13);
+			expect(9);
 
 			var attrs = {
 				f:  "innerForm", // the id of the form to submit
@@ -1056,18 +1056,6 @@ jQuery(document).ready(function() {
 				pre: [ function(attrs) {ok(true, "Precondition executed"); return true; } ],
 				bsh: [ function(attrs) {
 					ok(true, "BeforeSend handler executed");
-
-					var form = Wicket.$(attrs.f);
-					if (form.tagName.toLowerCase() !== "form") {
-						do {
-							form = form.parentNode;
-						} while(form.tagName.toLowerCase() !== "form" && form !== document.body);
-					}
-					var formUrl = form.action;
-					ok(formUrl.indexOf('dynamicEPName') > -1, "Dynamic extra parameter name is in the request query string");
-					ok(formUrl.indexOf('dynamicEPValue') > -1, "Dynamic extra parameter value is in the request query string");
-					ok(formUrl.indexOf('extraParamName') > -1, "Static extra parameter name is in the request query string");
-					ok(formUrl.indexOf('extraParamValue') > -1, "Static extra parameter value is in the request query string");
 				} ],
 				ah: [ function(attrs) { ok(true, "After handler executed"); } ],
 				sh: [ function(attrs) { ok(true, "Success handler executed"); } ],
@@ -1101,7 +1089,7 @@ jQuery(document).ready(function() {
 		 */
 		asyncTest('Submit nested form - failure scenario.', function () {
 
-			expect(12);
+			expect(8);
 
 			var attrs = {
 				f:  "innerForm", // the id of the form to submit
@@ -1115,18 +1103,6 @@ jQuery(document).ready(function() {
 				pre: [ function(attrs) {ok(true, "Precondition executed"); return true; } ],
 				bsh: [ function(attrs) {
 					ok(true, "BeforeSend handler executed");
-
-					var form = Wicket.$(attrs.f);
-					if (form.tagName.toLowerCase() !== "form") {
-						do {
-							form = form.parentNode;
-						} while(form.tagName.toLowerCase() !== "form" && form !== document.body);
-					}
-					var formUrl = form.action;
-					ok(formUrl.indexOf('dynamicEPName') > -1, "Dynamic extra parameter name is in the request query string");
-					ok(formUrl.indexOf('dynamicEPValue') > -1, "Dynamic extra parameter value is in the request query string");
-					ok(formUrl.indexOf('extraParamName') > -1, "Static extra parameter name is in the request query string");
-					ok(formUrl.indexOf('extraParamValue') > -1, "Static extra parameter value is in the request query string");
 				} ],
 				ah: [ function(attrs) { ok(true, "After handler executed"); } ],
 				sh: [ function(attrs) { ok(false, "Success handler should not be executed"); } ],


[13/16] wicket git commit: WICKET-6523 browser auto start; fixed version parameter

Posted by sv...@apache.org.
WICKET-6523 browser auto start; fixed version parameter

when choosing from modules or filtering


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: ffcb8cfecd0ffa65a771af5d677725d985bfc6bf
Parents: 63c4ae8
Author: Sven Meier <sv...@apache.org>
Authored: Thu Jan 25 17:09:16 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Sat Jan 27 00:02:58 2018 +0100

----------------------------------------------------------------------
 .../testing/jstest/StartJavaScriptTests.java       | 17 +++++++++++++++++
 wicket-core/src/test/js/ajax.js                    |  8 +-------
 wicket-core/src/test/js/all.html                   |  5 ++++-
 3 files changed, 22 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/ffcb8cfe/testing/wicket-js-tests/src/test/java/org/apache/wicket/testing/jstest/StartJavaScriptTests.java
----------------------------------------------------------------------
diff --git a/testing/wicket-js-tests/src/test/java/org/apache/wicket/testing/jstest/StartJavaScriptTests.java b/testing/wicket-js-tests/src/test/java/org/apache/wicket/testing/jstest/StartJavaScriptTests.java
index 3197a95..ee9ae3c 100644
--- a/testing/wicket-js-tests/src/test/java/org/apache/wicket/testing/jstest/StartJavaScriptTests.java
+++ b/testing/wicket-js-tests/src/test/java/org/apache/wicket/testing/jstest/StartJavaScriptTests.java
@@ -16,7 +16,9 @@
  */
 package org.apache.wicket.testing.jstest;
 
+import java.awt.Desktop;
 import java.lang.management.ManagementFactory;
+import java.net.URI;
 
 import javax.management.MBeanServer;
 
@@ -112,6 +114,9 @@ public class StartJavaScriptTests
 		try
 		{
 			server.start();
+			
+			browse();
+			
 			server.join();
 		}
 		catch (Exception e)
@@ -121,6 +126,18 @@ public class StartJavaScriptTests
 		}
 	}
 
+	private static void browse() 
+	{
+		try
+		{
+			Desktop.getDesktop().browse(new URI("http://localhost:8080/ajax-tests/test/js/all.html?2.2.4"));
+		}
+		catch (Exception e)
+		{
+			System.out.println("can not open browser " + e);
+		}
+	}
+
 	/**
 	 * Construct.
 	 */

http://git-wip-us.apache.org/repos/asf/wicket/blob/ffcb8cfe/wicket-core/src/test/js/ajax.js
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/js/ajax.js b/wicket-core/src/test/js/ajax.js
index 982aa47..dae4b48 100644
--- a/wicket-core/src/test/js/ajax.js
+++ b/wicket-core/src/test/js/ajax.js
@@ -31,13 +31,7 @@
 
 		 </Directory>
 
-	... or tweak wicket-examples' StartExamples.java like so:
-
-		bb.setContextPath("/ajax-tests");
-		bb.setWar("../wicket-core/src");
-
-	then run it by opening "http://localhost/ajax-tests/test/js/all.html" in the browser
-
+	Or start StartJavaScriptTests.java in project wicket-js-tests. 
  */
 
 /*global ok: true, start: true, asyncTest: true, test: true, equal: true, deepEqual: true,

http://git-wip-us.apache.org/repos/asf/wicket/blob/ffcb8cfe/wicket-core/src/test/js/all.html
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/js/all.html b/wicket-core/src/test/js/all.html
index 081c370..b5d8beb 100644
--- a/wicket-core/src/test/js/all.html
+++ b/wicket-core/src/test/js/all.html
@@ -6,7 +6,10 @@
 	<meta http-equiv="content-type" content="text/html; charset=UTF-8">
 	<link rel="stylesheet" href="qunit/qunit.css" type="text/css" media="screen" />
     <script>
-        document.write("<scr"+"ipt src='../../main/java/org/apache/wicket/resource/jquery/jquery-"+location.search.substring(1)+".js'></scr"+"ipt>");
+    	// version lies between question mark and first ampersand (or end)  
+    	var version = location.search.match(/\?(.*?)(&|$)/)[1];
+    	
+        document.write("<scr"+"ipt src='../../main/java/org/apache/wicket/resource/jquery/jquery-"+version+".js'></scr"+"ipt>");
     </script>
     <!--<script src="https://code.jquery.com/jquery-migrate-3.0.0.js"></script>-->
 	<script src="../../main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js"></script>


[11/16] wicket git commit: WICKET-6517 moved behavior out of markup package

Posted by sv...@apache.org.
WICKET-6517 moved behavior out of markup package

This closes #256


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 29d2775c05e8084ff3a01c2f2da27efcaa6d4b03
Parents: f1dd096
Author: Sven Meier <sv...@apache.org>
Authored: Fri Jan 19 09:22:35 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Fri Jan 26 23:51:35 2018 +0100

----------------------------------------------------------------------
 .../examples/ajax/builtin/FileUploadPage.html   |   2 +-
 .../examples/ajax/builtin/FileUploadPage.java   |   2 +-
 .../extensions/ajax/AjaxFileDropBehavior.java   | 211 +++++++++++++++++++
 .../ajax/markup/html/AjaxFileDropBehavior.java  | 211 -------------------
 .../extensions/ajax/markup/html/datatransfer.js |  54 -----
 .../wicket/extensions/ajax/wicket-ajaxupload.js |  54 +++++
 6 files changed, 267 insertions(+), 267 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/29d2775c/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
----------------------------------------------------------------------
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
index 2ed083d..18d2bfb 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<html>
+<html xmlns:wicket="http://wicket.apache.org">
 <head>
 	<wicket:head>
 		<style>

http://git-wip-us.apache.org/repos/asf/wicket/blob/29d2775c/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
----------------------------------------------------------------------
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
index f7a473c..598efee 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
@@ -22,7 +22,7 @@ import org.apache.commons.fileupload.FileUploadException;
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
-import org.apache.wicket.extensions.ajax.markup.html.AjaxFileDropBehavior;
+import org.apache.wicket.extensions.ajax.AjaxFileDropBehavior;
 import org.apache.wicket.extensions.ajax.markup.html.form.upload.UploadProgressBar;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;

http://git-wip-us.apache.org/repos/asf/wicket/blob/29d2775c/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxFileDropBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxFileDropBehavior.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxFileDropBehavior.java
new file mode 100644
index 0000000..0501610
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxFileDropBehavior.java
@@ -0,0 +1,211 @@
+/*
+ * 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.extensions.ajax;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.wicket.Component;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
+import org.apache.wicket.core.util.string.CssUtils;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.markup.html.form.upload.FileUpload;
+import org.apache.wicket.protocol.http.servlet.MultipartServletWebRequest;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.request.resource.PackageResourceReference;
+import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.lang.Bytes;
+
+/**
+ * Uploads files from a drop event.
+ *
+ * @author Andrew Kondratev
+ * @author svenmeier
+ */
+public class AjaxFileDropBehavior extends AjaxEventBehavior
+{
+
+	public static final String DRAG_OVER_CLASS_KEY = CssUtils.key(AjaxFileDropBehavior.class, "dragover");
+
+	private static final ResourceReference JS = new PackageResourceReference(
+		AjaxFileDropBehavior.class, "wicket-ajaxupload.js");
+
+	/**
+	 * Maximum size of all uploaded files in bytes in a request.
+	 */
+	private Bytes maxSize;
+
+	/**
+	 * Maximum size of file of upload in bytes (if there are more than one) in a request.
+	 */
+	private Bytes fileMaxSize;
+
+	private String parameterName = "f";
+
+	/**
+	 * Listen for 'dragover' and 'drop' events and prevent them, only 'drop' will initiate
+	 * an Ajax request.
+	 */
+	public AjaxFileDropBehavior()
+	{
+		super("dragenter dragover dragleave drop");
+	}
+
+	@Override
+	public void renderHead(Component component, IHeaderResponse response)
+	{
+		super.renderHead(component, response);
+
+		response.render(JavaScriptHeaderItem.forReference(JS));
+	}
+
+	@Override
+	protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
+	{
+		super.updateAjaxAttributes(attributes);
+
+		attributes.setMultipart(true);
+		attributes.setMethod(Method.POST);
+		// default must be prevented, otherwise browser will consume the dataTransfer
+		attributes.setPreventDefault(true);
+
+		attributes.getAjaxCallListeners().add(new AjaxCallListener() {
+			@Override
+			public CharSequence getPrecondition(Component component)
+			{
+				String css = getComponent().getString(DRAG_OVER_CLASS_KEY);
+				
+				return String.format("jQuery('#' + attrs.c).toggleClass('%s', attrs.event.type === 'dragover'); return (attrs.event.type === 'drop');", css);
+			}
+		});
+		
+		attributes.getDynamicExtraParameters()
+			.add(String.format(
+				"return Wicket.DataTransfer.getFilesAsParamArray(attrs.event.originalEvent, '%s');",
+				parameterName));
+	}
+
+	@Override
+	protected void onEvent(AjaxRequestTarget target)
+	{
+		try
+		{
+			ServletWebRequest request = (ServletWebRequest)getComponent().getRequest();
+			final MultipartServletWebRequest multipartWebRequest = request
+				.newMultipartWebRequest(getMaxSize(), getComponent().getPage().getId());
+			multipartWebRequest.setFileMaxSize(getFileMaxSize());
+			multipartWebRequest.parseFileParts();
+
+			// TODO: Can't this be detected from header?
+			getComponent().getRequestCycle().setRequest(multipartWebRequest);
+
+			ArrayList<FileUpload> fileUploads = new ArrayList<>();
+
+			// Get the item for the path
+			final List<FileItem> fileItems = multipartWebRequest.getFile(parameterName);
+
+			if (fileItems != null)
+			{
+				for (FileItem item : fileItems)
+				{
+					fileUploads.add(new FileUpload(item));
+				}
+			}
+
+			onFileUpload(target, fileUploads);
+		}
+		catch (final FileUploadException fux)
+		{
+			onError(target, fux);
+		}
+	}
+
+	public Bytes getMaxSize()
+	{
+		if (maxSize == null)
+		{
+			maxSize = getComponent().getApplication().getApplicationSettings()
+				.getDefaultMaximumUploadSize();
+		}
+		return maxSize;
+	}
+
+	/**
+	 * Set the maximum upload size.
+	 * 
+	 * @param maxSize maximum size, must not be null
+	 */
+	public void setMaxSize(Bytes maxSize)
+	{
+		Args.notNull(maxSize, "maxSize");
+		this.maxSize = maxSize;
+	}
+
+	public Bytes getFileMaxSize()
+	{
+		return fileMaxSize;
+	}
+
+	/**
+	 * Set an optional maximum size per file.
+	 * 
+	 * @param fileMaxSize maximum size for each uploaded file
+	 */
+	public void setFileMaxSize(Bytes fileMaxSize)
+	{
+		this.fileMaxSize = fileMaxSize;
+	}
+
+	/**
+	 * Hook method called after a file was uploaded.
+	 * <p>
+	 * Note: {@link #onError(AjaxRequestTarget, FileUploadException)} is called instead when
+	 * uploading failed
+	 * 
+	 * @param target
+	 *            the current request handler
+	 * @param files
+	 *            uploaded files
+	 */
+	protected void onFileUpload(AjaxRequestTarget target, List<FileUpload> files)
+	{
+	}
+
+	/**
+	 * Hook method called to handle any error during uploading of the file.
+	 * <p>
+	 * Default implementation re-throws the exception. 
+	 *
+	 * @param target
+	 *            the current request handler
+	 * @param e
+	 *            the error that occurred
+	 */
+	protected void onError(AjaxRequestTarget target, FileUploadException fux)
+	{
+		throw new WicketRuntimeException(fux);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/29d2775c/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
deleted file mode 100644
index 817c2f4..0000000
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 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.extensions.ajax.markup.html;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.FileUploadException;
-import org.apache.wicket.Component;
-import org.apache.wicket.WicketRuntimeException;
-import org.apache.wicket.ajax.AjaxEventBehavior;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.attributes.AjaxCallListener;
-import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
-import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
-import org.apache.wicket.core.util.string.CssUtils;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.JavaScriptHeaderItem;
-import org.apache.wicket.markup.html.form.upload.FileUpload;
-import org.apache.wicket.protocol.http.servlet.MultipartServletWebRequest;
-import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
-import org.apache.wicket.request.resource.PackageResourceReference;
-import org.apache.wicket.request.resource.ResourceReference;
-import org.apache.wicket.util.lang.Args;
-import org.apache.wicket.util.lang.Bytes;
-
-/**
- * Uploads files from a drop event.
- *
- * @author Andrew Kondratev
- * @author svenmeier
- */
-public class AjaxFileDropBehavior extends AjaxEventBehavior
-{
-
-	public static final String DRAG_OVER_CLASS_KEY = CssUtils.key(AjaxFileDropBehavior.class, "dragover");
-
-	private static final ResourceReference JS = new PackageResourceReference(
-		AjaxFileDropBehavior.class, "datatransfer.js");
-
-	/**
-	 * Maximum size of all uploaded files in bytes in a request.
-	 */
-	private Bytes maxSize;
-
-	/**
-	 * Maximum size of file of upload in bytes (if there are more than one) in a request.
-	 */
-	private Bytes fileMaxSize;
-
-	private String parameterName = "f";
-
-	/**
-	 * Listen for 'dragover' and 'drop' events and prevent them, only 'drop' will initiate
-	 * an Ajax request.
-	 */
-	public AjaxFileDropBehavior()
-	{
-		super("dragenter dragover dragleave drop");
-	}
-
-	@Override
-	public void renderHead(Component component, IHeaderResponse response)
-	{
-		super.renderHead(component, response);
-
-		response.render(JavaScriptHeaderItem.forReference(JS));
-	}
-
-	@Override
-	protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
-	{
-		super.updateAjaxAttributes(attributes);
-
-		attributes.setMultipart(true);
-		attributes.setMethod(Method.POST);
-		// default must be prevented, otherwise browser will consume the dataTransfer
-		attributes.setPreventDefault(true);
-
-		attributes.getAjaxCallListeners().add(new AjaxCallListener() {
-			@Override
-			public CharSequence getPrecondition(Component component)
-			{
-				String css = getComponent().getString(DRAG_OVER_CLASS_KEY);
-				
-				return String.format("jQuery('#' + attrs.c).toggleClass('%s', attrs.event.type === 'dragover'); return (attrs.event.type === 'drop');", css);
-			}
-		});
-		
-		attributes.getDynamicExtraParameters()
-			.add(String.format(
-				"return Wicket.DataTransfer.getFilesAsParamArray(attrs.event.originalEvent, '%s');",
-				parameterName));
-	}
-
-	@Override
-	protected void onEvent(AjaxRequestTarget target)
-	{
-		try
-		{
-			ServletWebRequest request = (ServletWebRequest)getComponent().getRequest();
-			final MultipartServletWebRequest multipartWebRequest = request
-				.newMultipartWebRequest(getMaxSize(), getComponent().getPage().getId());
-			multipartWebRequest.setFileMaxSize(getFileMaxSize());
-			multipartWebRequest.parseFileParts();
-
-			// TODO: Can't this be detected from header?
-			getComponent().getRequestCycle().setRequest(multipartWebRequest);
-
-			ArrayList<FileUpload> fileUploads = new ArrayList<>();
-
-			// Get the item for the path
-			final List<FileItem> fileItems = multipartWebRequest.getFile(parameterName);
-
-			if (fileItems != null)
-			{
-				for (FileItem item : fileItems)
-				{
-					fileUploads.add(new FileUpload(item));
-				}
-			}
-
-			onFileUpload(target, fileUploads);
-		}
-		catch (final FileUploadException fux)
-		{
-			onError(target, fux);
-		}
-	}
-
-	public Bytes getMaxSize()
-	{
-		if (maxSize == null)
-		{
-			maxSize = getComponent().getApplication().getApplicationSettings()
-				.getDefaultMaximumUploadSize();
-		}
-		return maxSize;
-	}
-
-	/**
-	 * Set the maximum upload size.
-	 * 
-	 * @param maxSize maximum size, must not be null
-	 */
-	public void setMaxSize(Bytes maxSize)
-	{
-		Args.notNull(maxSize, "maxSize");
-		this.maxSize = maxSize;
-	}
-
-	public Bytes getFileMaxSize()
-	{
-		return fileMaxSize;
-	}
-
-	/**
-	 * Set an optional maximum size per file.
-	 * 
-	 * @param fileMaxSize maximum size for each uploaded file
-	 */
-	public void setFileMaxSize(Bytes fileMaxSize)
-	{
-		this.fileMaxSize = fileMaxSize;
-	}
-
-	/**
-	 * Hook method called after a file was uploaded.
-	 * <p>
-	 * Note: {@link #onError(AjaxRequestTarget, FileUploadException)} is called instead when
-	 * uploading failed
-	 * 
-	 * @param target
-	 *            the current request handler
-	 * @param files
-	 *            uploaded files
-	 */
-	protected void onFileUpload(AjaxRequestTarget target, List<FileUpload> files)
-	{
-	}
-
-	/**
-	 * Hook method called to handle any error during uploading of the file.
-	 * <p>
-	 * Default implementation re-throws the exception. 
-	 *
-	 * @param target
-	 *            the current request handler
-	 * @param e
-	 *            the error that occurred
-	 */
-	protected void onError(AjaxRequestTarget target, FileUploadException fux)
-	{
-		throw new WicketRuntimeException(fux);
-	}
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/29d2775c/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/datatransfer.js
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/datatransfer.js b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/datatransfer.js
deleted file mode 100644
index 05ff68a..0000000
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/datatransfer.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.
- */
-
-;(function (undefined) {
-	'use strict';
-
-	if (typeof(Wicket) === "undefined") {
-		window.Wicket = {};
-	}
-
-	if (Wicket.DataTransfer) {
-		return;
-	}
-
-	Wicket.DataTransfer = {
-		getFilesAsParamArray : function(ev, name) {
-			var files = [];
-				
-			function pushFile(file) {
-				files.push({'name' : name, 'value' : file}); 
-			};
-
-			var dataTransfer = ev.dataTransfer; 
-			var i;
-			if (dataTransfer.items) { 
-			  for (i = 0; i < dataTransfer.items.length; i++) { 
-			    if (dataTransfer.items[i].kind == 'file') { 
-			      pushFile(dataTransfer.items[i].getAsFile()); 
-			    } 
-			  } 
-			} else { 
-			  for (i = 0; i < dataTransfer.files.length; i++) { 
-			    pushFile(dataTransfer.files[i]); 
-			  } 
-			}
-			
-			return files;
-		}
-	};
-})();

http://git-wip-us.apache.org/repos/asf/wicket/blob/29d2775c/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/wicket-ajaxupload.js
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/wicket-ajaxupload.js b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/wicket-ajaxupload.js
new file mode 100644
index 0000000..05ff68a
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/wicket-ajaxupload.js
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+;(function (undefined) {
+	'use strict';
+
+	if (typeof(Wicket) === "undefined") {
+		window.Wicket = {};
+	}
+
+	if (Wicket.DataTransfer) {
+		return;
+	}
+
+	Wicket.DataTransfer = {
+		getFilesAsParamArray : function(ev, name) {
+			var files = [];
+				
+			function pushFile(file) {
+				files.push({'name' : name, 'value' : file}); 
+			};
+
+			var dataTransfer = ev.dataTransfer; 
+			var i;
+			if (dataTransfer.items) { 
+			  for (i = 0; i < dataTransfer.items.length; i++) { 
+			    if (dataTransfer.items[i].kind == 'file') { 
+			      pushFile(dataTransfer.items[i].getAsFile()); 
+			    } 
+			  } 
+			} else { 
+			  for (i = 0; i < dataTransfer.files.length; i++) { 
+			    pushFile(dataTransfer.files[i]); 
+			  } 
+			}
+			
+			return files;
+		}
+	};
+})();


[02/16] wicket git commit: Release wicket-eclipse-settings 4

Posted by sv...@apache.org.
Release wicket-eclipse-settings 4


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 34872517516ee6bf121f6cf998cc7da5e9597bba
Parents: c27a57b
Author: Martijn Dashorst <ma...@topicus.nl>
Authored: Sun Jan 14 14:32:13 2018 +0100
Committer: Martijn Dashorst <ma...@topicus.nl>
Committed: Thu Jan 18 10:55:07 2018 +0100

----------------------------------------------------------------------
 wicket-eclipse-settings/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/34872517/wicket-eclipse-settings/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-eclipse-settings/pom.xml b/wicket-eclipse-settings/pom.xml
index 129aa83..cb2ed7f 100644
--- a/wicket-eclipse-settings/pom.xml
+++ b/wicket-eclipse-settings/pom.xml
@@ -27,7 +27,7 @@
   </parent>
   <groupId>org.apache.wicket</groupId>
   <artifactId>wicket-eclipse-settings</artifactId>
-  <version>4-SNAPSHOT</version>
+  <version>4</version>
   <packaging>jar</packaging>
   <name>Wicket Eclipse Settings</name>
   <description>


[09/16] wicket git commit: WICKET-6517 pass ajax target to onError

Posted by sv...@apache.org.
WICKET-6517 pass ajax target to onError


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 3f5c2932c47a6798b3dd361c98bb5756b623eaaf
Parents: 237147f
Author: Sven Meier <sv...@apache.org>
Authored: Thu Jan 18 07:46:51 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Fri Jan 26 23:09:37 2018 +0100

----------------------------------------------------------------------
 .../examples/ajax/builtin/FileUploadPage.java   |  9 +++
 .../ajax/markup/html/AjaxFileDropBehavior.java  | 82 +++++++++++++++-----
 2 files changed, 70 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/3f5c2932/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
----------------------------------------------------------------------
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
index 7399301..f7a473c 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
@@ -18,6 +18,7 @@ package org.apache.wicket.examples.ajax.builtin;
 
 import java.util.List;
 
+import org.apache.commons.fileupload.FileUploadException;
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
@@ -134,6 +135,14 @@ public class FileUploadPage extends BasePage
 				
 				target.add(feedback);
 			}
+			
+			@Override
+			protected void onError(AjaxRequestTarget target, FileUploadException fux)
+			{
+				info(fux.getMessage());
+				
+				target.add(feedback);				
+			}
 		});
 		add(drop);
 	}

http://git-wip-us.apache.org/repos/asf/wicket/blob/3f5c2932/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
index 9073cd3..b8806d9 100644
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
@@ -22,6 +22,7 @@ import java.util.List;
 import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.fileupload.FileUploadException;
 import org.apache.wicket.Component;
+import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
@@ -46,34 +47,38 @@ import org.apache.wicket.util.lang.Bytes;
 public class AjaxFileDropBehavior extends AjaxEventBehavior
 {
 
-	private static final ResourceReference JS = new PackageResourceReference(AjaxFileDropBehavior.class, "datatransfer.js");
+	private static final ResourceReference JS = new PackageResourceReference(
+		AjaxFileDropBehavior.class, "datatransfer.js");
 
 	/**
-	 *  Maximum size of all uploaded files in bytes in a request.
+	 * Maximum size of all uploaded files in bytes in a request.
 	 */
 	private Bytes maxSize;
 
 	/**
-	 *  Maximum size of file of upload in bytes (if there are more than one) in a request.
+	 * Maximum size of file of upload in bytes (if there are more than one) in a request.
 	 */
 	private Bytes fileMaxSize;
 
 	private String parameterName = "f";
-	
+
 	public AjaxFileDropBehavior()
 	{
 		super("drop");
 	}
-	
+
 	@Override
 	public void renderHead(Component component, IHeaderResponse response)
 	{
 		super.renderHead(component, response);
-		
+
 		response.render(JavaScriptHeaderItem.forReference(JS));
-		
-		// default must be prevented for dragover event, otherwise browser will consume the dataTransfer
-		response.render(OnDomReadyHeaderItem.forScript(String.format("jQuery('#%s').on('dragover', function(e) { e.preventDefault(); });", component.getMarkupId())));
+
+		// default must be prevented for dragover event, otherwise browser will consume the
+		// dataTransfer
+		response.render(OnDomReadyHeaderItem.forScript(
+			String.format("jQuery('#%s').on('dragover', function(e) { e.preventDefault(); });",
+				component.getMarkupId())));
 	}
 
 	@Override
@@ -86,9 +91,10 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
 		// default must be prevented, otherwise browser will consume the dataTransfer
 		attributes.setPreventDefault(true);
 
-		attributes.getDynamicExtraParameters().add(
-			String.format("return Wicket.DataTransfer.getFilesAsParamArray(attrs.event.originalEvent, '%s');", parameterName)
-		);
+		attributes.getDynamicExtraParameters()
+			.add(String.format(
+				"return Wicket.DataTransfer.getFilesAsParamArray(attrs.event.originalEvent, '%s');",
+				parameterName));
 	}
 
 	@Override
@@ -97,14 +103,14 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
 		try
 		{
 			ServletWebRequest request = (ServletWebRequest)getComponent().getRequest();
-			final MultipartServletWebRequest multipartWebRequest = request.newMultipartWebRequest(
-				getMaxSize(), getComponent().getPage().getId());
+			final MultipartServletWebRequest multipartWebRequest = request
+				.newMultipartWebRequest(getMaxSize(), getComponent().getPage().getId());
 			multipartWebRequest.setFileMaxSize(getFileMaxSize());
 			multipartWebRequest.parseFileParts();
 
 			// TODO: Can't this be detected from header?
 			getComponent().getRequestCycle().setRequest(multipartWebRequest);
-			
+
 			ArrayList<FileUpload> fileUploads = new ArrayList<>();
 
 			// Get the item for the path
@@ -117,23 +123,30 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
 					fileUploads.add(new FileUpload(item));
 				}
 			}
-			
+
 			onFileUpload(target, fileUploads);
 		}
 		catch (final FileUploadException fux)
 		{
-			onError(fux);
+			onError(target, fux);
 		}
 	}
 
 	public Bytes getMaxSize()
 	{
-		if (maxSize == null) {
-			maxSize = getComponent().getApplication().getApplicationSettings().getDefaultMaximumUploadSize();
+		if (maxSize == null)
+		{
+			maxSize = getComponent().getApplication().getApplicationSettings()
+				.getDefaultMaximumUploadSize();
 		}
 		return maxSize;
 	}
 
+	/**
+	 * Set the maximum upload size.
+	 * 
+	 * @param maxSize maximum size, must not be null
+	 */
 	public void setMaxSize(Bytes maxSize)
 	{
 		Args.notNull(maxSize, "maxSize");
@@ -145,16 +158,43 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
 		return fileMaxSize;
 	}
 
+	/**
+	 * Set an optional maximum size per file.
+	 * 
+	 * @param fileMaxSize maximum size for each uploaded file
+	 */
 	public void setFileMaxSize(Bytes fileMaxSize)
 	{
 		this.fileMaxSize = fileMaxSize;
 	}
-	
+
+	/**
+	 * Hook method called after a file was uploaded.
+	 * <p>
+	 * Note: {@link #onError(AjaxRequestTarget, FileUploadException)} is called instead when
+	 * uploading failed
+	 * 
+	 * @param target
+	 *            the current request handler
+	 * @param files
+	 *            uploaded files
+	 */
 	protected void onFileUpload(AjaxRequestTarget target, List<FileUpload> files)
 	{
 	}
 
-	protected void onError(FileUploadException fux)
+	/**
+	 * Hook method called to handle any error during uploading of the file.
+	 * <p>
+	 * Default implementation re-throws the exception. 
+	 *
+	 * @param target
+	 *            the current request handler
+	 * @param e
+	 *            the error that occurred
+	 */
+	protected void onError(AjaxRequestTarget target, FileUploadException fux)
 	{
+		throw new WicketRuntimeException(fux);
 	}
 }
\ No newline at end of file


[15/16] wicket git commit: WICKET-6523 remove timer handle as soon as possible

Posted by sv...@apache.org.
WICKET-6523 remove timer handle as soon as possible


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 36bf207bbda3e6ba53a6a24fc1fa6409783449c4
Parents: 29d2775
Author: Sven Meier <sv...@apache.org>
Authored: Wed Jan 24 19:42:40 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Sat Jan 27 00:02:58 2018 +0100

----------------------------------------------------------------------
 .../wicket/ajax/AbstractAjaxTimerBehavior.java  | 16 ++++------------
 .../wicket/ajax/res/js/wicket-ajax-jquery.js    |  9 ++++++---
 wicket-core/src/test/js/timer.js                | 20 +++++++++-----------
 3 files changed, 19 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/36bf207b/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 7fd3606..25dd1b7 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
@@ -88,7 +88,7 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 
 		if (isStopped() == false)
 		{
-			addTimeout(response);
+			setTimeout(response);
 		}
 	}
 
@@ -112,23 +112,15 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 	@Override
 	protected final void respond(final AjaxRequestTarget target)
 	{
-		// onTimer might remove this behavior, so keep the component
-		// so the timeout can be cleared later on
-		Component component = getComponent();
-		
 		if (shouldTrigger())
 		{
 			onTimer(target);
 
 			if (shouldTrigger())
 			{
-				addTimeout(target.getHeaderResponse());
-
-				return;
+				setTimeout(target.getHeaderResponse());
 			}
 		}
-
-		clearTimeout(component, target.getHeaderResponse());
 	}
 
 	/**
@@ -175,12 +167,12 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 
 			if (target != null)
 			{
-				addTimeout(target.getHeaderResponse());
+				setTimeout(target.getHeaderResponse());
 			}
 		}
 	}
 
-	private void addTimeout(IHeaderResponse headerResponse)
+	private void setTimeout(IHeaderResponse headerResponse)
 	{
 		headerResponse.render(OnLoadHeaderItem.forScript(getJsTimeoutCall(updateInterval)));
 	}

http://git-wip-us.apache.org/repos/asf/wicket/blob/36bf207b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
index b2ad3a0..67c9a2c 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
@@ -2541,16 +2541,19 @@
 			/**
 			 * Schedules a timer
 			 * @param {string} timerId - the identifier for the timer
-			 * @param {function|string} js - the JavaScript to execute after the timeout
+			 * @param {function} f - the JavaScript function to execute after the timeout
 			 * @param {number} delay - the timeout
 			 */
-			'set': function(timerId, js, delay) {
+			'set': function(timerId, f, delay) {
 				if (typeof(Wicket.TimerHandles) === 'undefined') {
 					Wicket.TimerHandles = {};
 				}
 
 				Wicket.Timer.clear(timerId);
-				Wicket.TimerHandles[timerId] = setTimeout(js, delay);
+				Wicket.TimerHandles[timerId] = setTimeout(function() {
+					Wicket.Timer.clear(timerId);
+					f();
+				}, delay);
 			},
 
 			/**

http://git-wip-us.apache.org/repos/asf/wicket/blob/36bf207b/wicket-core/src/test/js/timer.js
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/js/timer.js b/wicket-core/src/test/js/timer.js
index e018f24..c95c20b 100644
--- a/wicket-core/src/test/js/timer.js
+++ b/wicket-core/src/test/js/timer.js
@@ -28,8 +28,8 @@ jQuery(document).ready(function() {
 
 		var timerId = 'timerId',
 			run = function() {
+				ok(typeof(Wicket.TimerHandles[timerId]) === 'undefined', "There is no handle to the timeout!");
 				ok("The timer is ran!");
-				ok(Wicket.TimerHandles[timerId], "There is a handle to the timeout!");
 				start();
 			};
 
@@ -38,21 +38,19 @@ jQuery(document).ready(function() {
 
 	test('clear', function () {
 		stop();
-		expect(3);
+		expect(2);
 
 		var timerId = 'timerId',
 			run = function() {
-				ok("The timer is ran!");
-
-				ok(Wicket.TimerHandles[timerId], "There is a handle to the timeout!");
-
-				Wicket.Timer.clear(timerId);
-
-				ok(typeof(Wicket.TimerHandles[timerId]) === 'undefined', "There is NO handle to the timeout!");
-
-				start();
+				ok(false, "timeout is not called");
 			};
 
 		Wicket.Timer.set('timerId', run, 1);
+		ok(Wicket.TimerHandles[timerId], "There is a handle to the timeout!");
+		
+		Wicket.Timer.clear(timerId);
+		ok(typeof(Wicket.TimerHandles[timerId]) === 'undefined', "There is no handle to the timeout!");
+
+		start();
 	});
 });


[07/16] wicket git commit: WICKET-6517 dep could be multipart too

Posted by sv...@apache.org.
WICKET-6517 dep could be multipart too


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 44fb374876210fc0545a5c02a83232ebc1500a38
Parents: f642f4a
Author: Sven Meier <sv...@apache.org>
Authored: Wed Jan 17 00:32:29 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Fri Jan 26 23:09:37 2018 +0100

----------------------------------------------------------------------
 .../wicket/ajax/res/js/wicket-ajax-jquery.js    |  49 ++----
 .../examples/ajax/builtin/FileUploadPage.html   |  10 +-
 .../examples/ajax/builtin/FileUploadPage.java   |  26 ++++
 .../markup/html/AjaxFileUploadBehavior.java     | 156 +++++++++++++++++++
 .../extensions/ajax/markup/html/datatransfer.js |  54 +++++++
 5 files changed, 261 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/44fb3748/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
index 801a47d..b2ad3a0 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
@@ -49,8 +49,7 @@
 		};
 	}
 
-	var createIFrame,
-		getAjaxBaseUrl,
+	var getAjaxBaseUrl,
 		isUndef,
 		replaceAll,
 		htmlToDomDocument,
@@ -66,19 +65,6 @@
 	};
 
 	/**
-	 * Creates an iframe that can be used to load data asynchronously or as a
-	 * target for Ajax form submit.
-	 *
-	 * @param iframeName {String} the value of the iframe's name attribute
-	 */
-	createIFrame = function (iframeName) {
-		// WICKET-6340 properly close tag for XHTML markup
-		var $iframe = jQuery('<iframe name="'+iframeName+'" id="'+iframeName+
-			'" src="about:blank" style="position: absolute; top: -9999px; left: -9999px;"></iframe>');
-		return $iframe[0];
-	};
-
-	/**
 	 * A safe getter for Wicket's Ajax base URL.
 	 * If the value is not defined or is empty string then
 	 * return '.' (current folder) as base URL.
@@ -553,7 +539,7 @@
 				extraParam = this._asParamArray(extraParam);
 				params = params.concat(extraParam);
 			}
-			return jQuery.param(params);
+			return params;
 		},
 
 		/**
@@ -583,6 +569,8 @@
 					'Wicket-Ajax': 'true',
 					'Wicket-Ajax-BaseURL': getAjaxBaseUrl()
 				},
+				
+				url = attrs.u,
 
 				// the request (extra) parameters
 				data = this._asParamArray(attrs.ep),
@@ -658,6 +646,17 @@
 				var el = Wicket.$(attrs.c);
 				data = data.concat(Wicket.Form.serializeElement(el, attrs.sr));
 			}
+			
+			// collect the dynamic extra parameters
+			if (jQuery.isArray(attrs.dep)) {
+				var dynamicData = this._calculateDynamicParameters(attrs);
+				if (attrs.m.toLowerCase() === 'post') {
+					data = data.concat(dynamicData);
+				} else {
+					var separator = url.indexOf('?') > -1 ? '&' : '?';
+					url = url + separator + jQuery.param(dynamicData);
+				}
+			}
 
 			var wwwFormUrlEncoded = undefined; // default
 			if (attrs.mp) {
@@ -676,29 +675,13 @@
 
 			// execute the request
 			var jqXHR = jQuery.ajax({
-				url: attrs.u,
+				url: url,
 				type: attrs.m,
 				context: self,
 				processData: wwwFormUrlEncoded,
 				contentType: wwwFormUrlEncoded,
 				
 				beforeSend: function (jqXHR, settings) {
-					// collect the dynamic extra parameters
-					if (jQuery.isArray(attrs.dep)) {
-						var queryString,
-							separator;
-
-						queryString = this._calculateDynamicParameters(attrs);
-						if (settings.type.toLowerCase() === 'post') {
-							separator = settings.data.length > 0 ? '&' : '';
-							settings.data = settings.data + separator + queryString;
-							jqXHR.setRequestHeader("Content-Type", settings.contentType);
-						} else {
-							separator = settings.url.indexOf('?') > -1 ? '&' : '?';
-							settings.url = settings.url + separator + queryString;
-						}
-					}
-
 					self._executeHandlers(attrs.bsh, attrs, jqXHR, settings);
 					we.publish(topic.AJAX_CALL_BEFORE_SEND, attrs, jqXHR, settings);
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/44fb3748/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
----------------------------------------------------------------------
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
index 9351d4c..4642ae3 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
@@ -1,4 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" ?>
+<html>
+<body>
 <wicket:extend xmlns:wicket="http://wicket.apache.org">
 
 Demonstrates Wicket's ability to transparently handle multipart forms via AJAX.<br/><br/>The only difference between this example and other non-AJAX upload examples is the option to trigger the form submit via an AjaxButton, everything else is handled transparently by Wicket.<br/><br/>
@@ -13,4 +15,10 @@ Demonstrates Wicket's ability to transparently handle multipart forms via AJAX.<
 	<input type="submit" value="Regular Submit"/> <input wicket:id="ajaxSubmit" type="button" value="Ajax Submit"/>
 </form>
 
-</wicket:extend>
\ No newline at end of file
+<div wicket:id="drop" style="border: 1px dotted black; width:200px; height:200px;">
+	Drop file here.
+</div>
+
+</wicket:extend>
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/44fb3748/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
----------------------------------------------------------------------
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
index e2eda2e..ca6dc70 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
@@ -16,10 +16,14 @@
  */
 package org.apache.wicket.examples.ajax.builtin;
 
+import java.util.List;
+
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.extensions.ajax.markup.html.AjaxFileUploadBehavior;
 import org.apache.wicket.extensions.ajax.markup.html.form.upload.UploadProgressBar;
+import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.form.TextField;
@@ -110,5 +114,27 @@ public class FileUploadPage extends BasePage
 			}
 
 		});
+		
+		WebMarkupContainer drop = new WebMarkupContainer("drop");
+		drop.add(new AjaxFileUploadBehavior() {
+			protected void onFileUpload(AjaxRequestTarget target, List<FileUpload> files) {
+			    
+				// display uploaded info
+				if (files == null || files.isEmpty())
+				{
+					info("No file uploaded");
+				}
+				else
+				{
+				    for (FileUpload file : files) {
+				    	info("File-Name: " + file.getClientFileName() + " File-Size: " +
+				    		Bytes.bytes(file.getSize()).toString());
+				    }
+				}
+				
+				target.add(feedback);
+			}
+		});
+		add(drop);
 	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/44fb3748/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileUploadBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileUploadBehavior.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileUploadBehavior.java
new file mode 100644
index 0000000..3801c62
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileUploadBehavior.java
@@ -0,0 +1,156 @@
+/*
+ * 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.extensions.ajax.markup.html;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.markup.html.form.upload.FileUpload;
+import org.apache.wicket.protocol.http.servlet.MultipartServletWebRequest;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.request.resource.PackageResourceReference;
+import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.lang.Bytes;
+
+/**
+ * Uploads files from a drop event.
+ * 
+ * @author svenmeier
+ */
+public class AjaxFileUploadBehavior extends AjaxEventBehavior
+{
+
+	private static final ResourceReference JS = new PackageResourceReference(AjaxFileUploadBehavior.class, "datatransfer.js");
+
+	/**
+	 *  Maximum size of all uploaded files in bytes in a request.
+	 */
+	private Bytes maxSize;
+
+	/**
+	 *  Maximum size of file of upload in bytes (if there are more than one) in a request.
+	 */
+	private Bytes fileMaxSize;
+
+	private String parameterName = "f";
+	
+	public AjaxFileUploadBehavior()
+	{
+		super("drop");
+	}
+	
+	@Override
+	public void renderHead(Component component, IHeaderResponse response)
+	{
+		super.renderHead(component, response);
+		
+		response.render(JavaScriptHeaderItem.forReference(JS));
+		
+		// default must be prevented for dragover event, otherwise browser will consume the dataTransfer
+		response.render(OnDomReadyHeaderItem.forScript(String.format("jQuery('#%s').on('dragover', function(e) { e.preventDefault(); });", component.getMarkupId())));
+	}
+
+	@Override
+	protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
+	{
+		super.updateAjaxAttributes(attributes);
+
+		attributes.setMultipart(true);
+		attributes.setMethod(Method.POST);
+		// default must be prevented, otherwise browser will consume the dataTransfer
+		attributes.setPreventDefault(true);
+
+		attributes.getDynamicExtraParameters().add(
+			String.format("return Wicket.DataTransfer.getFilesAsParamArray(attrs.event.originalEvent, '%s');", parameterName)
+		);
+	}
+
+	@Override
+	protected void onEvent(AjaxRequestTarget target)
+	{
+		try
+		{
+			ServletWebRequest request = (ServletWebRequest)getComponent().getRequest();
+			final MultipartServletWebRequest multipartWebRequest = request.newMultipartWebRequest(
+				getMaxSize(), getComponent().getPage().getId());
+			multipartWebRequest.setFileMaxSize(getFileMaxSize());
+			multipartWebRequest.parseFileParts();
+
+			// TODO: Can't this be detected from header?
+			getComponent().getRequestCycle().setRequest(multipartWebRequest);
+			
+			ArrayList<FileUpload> fileUploads = new ArrayList<>();
+
+			// Get the item for the path
+			final List<FileItem> fileItems = multipartWebRequest.getFile(parameterName);
+
+			if (fileItems != null)
+			{
+				for (FileItem item : fileItems)
+				{
+					fileUploads.add(new FileUpload(item));
+				}
+			}
+			
+			onFileUpload(target, fileUploads);
+		}
+		catch (final FileUploadException fux)
+		{
+			onError(fux);
+		}
+	}
+
+	public Bytes getMaxSize()
+	{
+		return maxSize;
+	}
+
+	public void setMaxSize(Bytes maxSize)
+	{
+		Args.notNull(maxSize, "maxSize");
+		this.maxSize = maxSize;
+	}
+
+	public Bytes getFileMaxSize()
+	{
+		return fileMaxSize;
+	}
+
+	public void setFileMaxSize(Bytes fileMaxSize)
+	{
+		this.fileMaxSize = fileMaxSize;
+	}
+	
+	protected void onFileUpload(AjaxRequestTarget target, List<FileUpload> files)
+	{
+	}
+
+	protected void onError(FileUploadException fux)
+	{
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/44fb3748/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/datatransfer.js
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/datatransfer.js b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/datatransfer.js
new file mode 100644
index 0000000..05ff68a
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/datatransfer.js
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+;(function (undefined) {
+	'use strict';
+
+	if (typeof(Wicket) === "undefined") {
+		window.Wicket = {};
+	}
+
+	if (Wicket.DataTransfer) {
+		return;
+	}
+
+	Wicket.DataTransfer = {
+		getFilesAsParamArray : function(ev, name) {
+			var files = [];
+				
+			function pushFile(file) {
+				files.push({'name' : name, 'value' : file}); 
+			};
+
+			var dataTransfer = ev.dataTransfer; 
+			var i;
+			if (dataTransfer.items) { 
+			  for (i = 0; i < dataTransfer.items.length; i++) { 
+			    if (dataTransfer.items[i].kind == 'file') { 
+			      pushFile(dataTransfer.items[i].getAsFile()); 
+			    } 
+			  } 
+			} else { 
+			  for (i = 0; i < dataTransfer.files.length; i++) { 
+			    pushFile(dataTransfer.files[i]); 
+			  } 
+			}
+			
+			return files;
+		}
+	};
+})();


[03/16] wicket git commit: Upgrade eclipse settings for Java 8

Posted by sv...@apache.org.
Upgrade eclipse settings for Java 8


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 1617e2b136e8b9c050b6c590d6ff1773a2b67d29
Parents: 3487251
Author: Martijn Dashorst <ma...@topicus.nl>
Authored: Thu Jan 18 10:54:56 2018 +0100
Committer: Martijn Dashorst <ma...@topicus.nl>
Committed: Thu Jan 18 10:55:08 2018 +0100

----------------------------------------------------------------------
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/1617e2b1/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 94d04ca..ead585c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -321,7 +321,7 @@
 			<dependency>
 				<groupId>org.apache.wicket</groupId>
 				<artifactId>wicket-eclipse-settings</artifactId>
-				<version>3</version>
+				<version>4</version>
 			</dependency>
 			<dependency>
 				<groupId>org.apache.wicket</groupId>
@@ -787,7 +787,7 @@
 				        <dependency>
 				            <groupId>org.apache.wicket</groupId>
 				            <artifactId>wicket-eclipse-settings</artifactId>
-				            <version>3</version>
+				            <version>4</version>
 				        </dependency>
 				    </dependencies>
 				</plugin>


[06/16] wicket git commit: WICKET-6517 added some CSS styling

Posted by sv...@apache.org.
WICKET-6517 added some CSS styling


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: f1dd096c772feb9f878f783c5764a37403e82e5b
Parents: 3f5c293
Author: Sven Meier <sv...@apache.org>
Authored: Thu Jan 18 22:43:21 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Fri Jan 26 23:09:37 2018 +0100

----------------------------------------------------------------------
 .../examples/ajax/builtin/FileUploadPage.html   | 17 +++++++++++-
 .../wicket/extensions/Initializer.properties    |  2 ++
 .../ajax/markup/html/AjaxFileDropBehavior.java  | 27 ++++++++++++++------
 3 files changed, 37 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/f1dd096c/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
----------------------------------------------------------------------
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
index 4642ae3..2ed083d 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
@@ -1,5 +1,20 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <html>
+<head>
+	<wicket:head>
+		<style>
+			.drop-zone {
+				border: 1px dotted #FF9925;
+				width:200px;
+				height:200px;
+			}
+			.drop-zone.drag-over {
+				background: #FF9925;
+				color: #ffffff;
+			}
+		</style>
+	</wicket:head>
+</head>
 <body>
 <wicket:extend xmlns:wicket="http://wicket.apache.org">
 
@@ -15,7 +30,7 @@ Demonstrates Wicket's ability to transparently handle multipart forms via AJAX.<
 	<input type="submit" value="Regular Submit"/> <input wicket:id="ajaxSubmit" type="button" value="Ajax Submit"/>
 </form>
 
-<div wicket:id="drop" style="border: 1px dotted black; width:200px; height:200px;">
+<div wicket:id="drop" class="drop-zone">
 	Drop file here.
 </div>
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/f1dd096c/wicket-extensions/src/main/java/org/apache/wicket/extensions/Initializer.properties
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/Initializer.properties b/wicket-extensions/src/main/java/org/apache/wicket/extensions/Initializer.properties
index 98f7925..6b43d43 100644
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/Initializer.properties
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/Initializer.properties
@@ -45,3 +45,5 @@ AbstractDateTimeField.CSS.time=datetime-time
 TimeField.hoursSeparator=\u00a0:\u00a0
 TimeField.CSS.hours=time-hours
 TimeField.CSS.minutes=time-minutes
+
+AjaxFileDropBehavior.CSS.dragover=drag-over
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/f1dd096c/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
index b8806d9..817c2f4 100644
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxFileDropBehavior.java
@@ -25,11 +25,12 @@ import org.apache.wicket.Component;
 import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
 import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
+import org.apache.wicket.core.util.string.CssUtils;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
-import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
 import org.apache.wicket.markup.html.form.upload.FileUpload;
 import org.apache.wicket.protocol.http.servlet.MultipartServletWebRequest;
 import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
@@ -47,6 +48,8 @@ import org.apache.wicket.util.lang.Bytes;
 public class AjaxFileDropBehavior extends AjaxEventBehavior
 {
 
+	public static final String DRAG_OVER_CLASS_KEY = CssUtils.key(AjaxFileDropBehavior.class, "dragover");
+
 	private static final ResourceReference JS = new PackageResourceReference(
 		AjaxFileDropBehavior.class, "datatransfer.js");
 
@@ -62,9 +65,13 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
 
 	private String parameterName = "f";
 
+	/**
+	 * Listen for 'dragover' and 'drop' events and prevent them, only 'drop' will initiate
+	 * an Ajax request.
+	 */
 	public AjaxFileDropBehavior()
 	{
-		super("drop");
+		super("dragenter dragover dragleave drop");
 	}
 
 	@Override
@@ -73,12 +80,6 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
 		super.renderHead(component, response);
 
 		response.render(JavaScriptHeaderItem.forReference(JS));
-
-		// default must be prevented for dragover event, otherwise browser will consume the
-		// dataTransfer
-		response.render(OnDomReadyHeaderItem.forScript(
-			String.format("jQuery('#%s').on('dragover', function(e) { e.preventDefault(); });",
-				component.getMarkupId())));
 	}
 
 	@Override
@@ -91,6 +92,16 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
 		// default must be prevented, otherwise browser will consume the dataTransfer
 		attributes.setPreventDefault(true);
 
+		attributes.getAjaxCallListeners().add(new AjaxCallListener() {
+			@Override
+			public CharSequence getPrecondition(Component component)
+			{
+				String css = getComponent().getString(DRAG_OVER_CLASS_KEY);
+				
+				return String.format("jQuery('#' + attrs.c).toggleClass('%s', attrs.event.type === 'dragover'); return (attrs.event.type === 'drop');", css);
+			}
+		});
+		
 		attributes.getDynamicExtraParameters()
 			.add(String.format(
 				"return Wicket.DataTransfer.getFilesAsParamArray(attrs.event.originalEvent, '%s');",


[05/16] wicket git commit: Merge branch 'master' into WICKET-6518-quickstart-logback

Posted by sv...@apache.org.
Merge branch 'master' into WICKET-6518-quickstart-logback


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 1d20044b5e9a5d282217514bffd040c13794b808
Parents: da3b69f eb9f6c9
Author: Maxim Solodovnik <so...@gmail.com>
Authored: Mon Jan 22 10:21:59 2018 +0700
Committer: Maxim Solodovnik <so...@gmail.com>
Committed: Mon Jan 22 10:21:59 2018 +0700

----------------------------------------------------------------------
 pom.xml                                         |   4 +-
 .../main/java/org/apache/wicket/Component.java  | 332 ++++++-------------
 .../java/org/apache/wicket/MarkupContainer.java |  22 --
 .../src/main/java/org/apache/wicket/Page.java   |  36 +-
 .../ComponentRenderingRequestHandler.java       |   9 +-
 .../handler/PageAndComponentProvider.java       |   2 +-
 .../core/util/string/ComponentRenderer.java     |   3 +-
 .../apache/wicket/feedback/FeedbackDelay.java   | 119 +++++++
 .../org/apache/wicket/feedback/IFeedback.java   |   5 +-
 .../apache/wicket/page/PartialPageUpdate.java   |  74 ++++-
 .../wicket/page/XmlPartialPageUpdate.java       |  50 +--
 .../wicket/feedback/FeedbackRenderTest.java     |  22 +-
 .../apache/wicket/feedback/FeedbacksPage.html   |  16 +-
 .../apache/wicket/feedback/FeedbacksPage.java   |  31 +-
 .../markup/html/internal/EnclosurePage_1.java   |  50 ++-
 .../markup/html/internal/EnclosureTest.java     |   4 +
 wicket-eclipse-settings/pom.xml                 |   2 +-
 .../componentLifecycle_1.adoc                   |  11 +-
 .../componentLifecycle_2.adoc                   |   9 +-
 .../componentLifecycle_3.adoc                   |   6 +-
 .../componentLifecycle_4.adoc                   |  23 +-
 .../componentLifecycle_5.adoc                   |   6 +-
 .../componentLifecycle_6.adoc                   |   3 +-
 .../componentLifecycle_7.adoc                   |   5 +
 .../main/asciidoc/img/component-lifecycle.png   | Bin 10587 -> 34960 bytes
 wicket-user-guide/src/main/asciidoc/single.adoc |   8 +-
 26 files changed, 474 insertions(+), 378 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/1d20044b/pom.xml
----------------------------------------------------------------------


[16/16] wicket git commit: WICKET-6523 restarting should re-set the timeout

Posted by sv...@apache.org.
WICKET-6523 restarting should re-set the timeout


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

Branch: refs/heads/WICKET-6523-ajax-timers
Commit: 15aa06f47b2230a4fbe8b6aed6bf731e68968ac8
Parents: 36bf207
Author: Sven Meier <sv...@apache.org>
Authored: Wed Jan 24 19:46:27 2018 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Sat Jan 27 00:02:58 2018 +0100

----------------------------------------------------------------------
 .../apache/wicket/ajax/AbstractAjaxTimerBehavior.java  | 13 +++++--------
 wicket-core/src/test/js/timer.js                       |  4 +++-
 2 files changed, 8 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/15aa06f4/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 25dd1b7..d193691 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
@@ -154,21 +154,18 @@ public abstract class AbstractAjaxTimerBehavior extends AbstractDefaultAjaxBehav
 	}
 
 	/**
-	 * Re-enables the timer if already stopped
+	 * Restart the timer.
 	 * 
 	 * @param target
 	 *            may be null
 	 */
 	public final void restart(final IPartialPageRequestHandler target)
 	{
-		if (stopped == true)
-		{
-			stopped = false;
+		stopped = false;
 
-			if (target != null)
-			{
-				setTimeout(target.getHeaderResponse());
-			}
+		if (target != null)
+		{
+			setTimeout(target.getHeaderResponse());
 		}
 	}
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/15aa06f4/wicket-core/src/test/js/timer.js
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/js/timer.js b/wicket-core/src/test/js/timer.js
index c95c20b..48efdaa 100644
--- a/wicket-core/src/test/js/timer.js
+++ b/wicket-core/src/test/js/timer.js
@@ -51,6 +51,8 @@ jQuery(document).ready(function() {
 		Wicket.Timer.clear(timerId);
 		ok(typeof(Wicket.TimerHandles[timerId]) === 'undefined', "There is no handle to the timeout!");
 
-		start();
+		setTimeout(function() {
+			start();			
+		}, 2);
 	});
 });