On Sat, Nov 9, 2013 at 8:49 AM, <[email protected]> wrote:
> Updated Branches:
> refs/heads/wicket-6.x 4e9a83fdc -> a73209bea
>
>
> WICKET-5411 auto label auto update during ajax
>
>
> Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
> Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/a73209be
> Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/a73209be
> Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/a73209be
>
> Branch: refs/heads/wicket-6.x
> Commit: a73209beab8814a06f2e085384ad87bdf1fda212
> Parents: 4e9a83f
> Author: Igor Vaynberg <[email protected]>
> Authored: Fri Nov 8 22:48:22 2013 -0800
> Committer: Igor Vaynberg <[email protected]>
> Committed: Fri Nov 8 22:48:22 2013 -0800
>
> ----------------------------------------------------------------------
> .../form/AjaxFormComponentUpdatingBehavior.java | 2 +-
> .../wicket/core/util/string/CssUtils.java | 14 ++
> .../markup/html/form/AutoLabelResolver.java | 130 ++++++++++++++++++-
> .../apache/wicket/markup/html/form/Form.java | 24 +++-
> .../wicket/markup/html/form/FormComponent.java | 34 ++++-
> .../wicket/protocol/http/WebApplication.java | 36 +++--
> 6 files changed, 212 insertions(+), 28 deletions(-)
> ----------------------------------------------------------------------
>
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/a73209be/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormComponentUpdatingBehavior.java
> ----------------------------------------------------------------------
> diff --git
> a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormComponentUpdatingBehavior.java
> b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormComponentUpdatingBehavior.java
> index 7eab478..bd8267c 100644
> ---
> a/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormComponentUpdatingBehavior.java
> +++
> b/wicket-core/src/main/java/org/apache/wicket/ajax/form/AjaxFormComponentUpdatingBehavior.java
> @@ -160,8 +160,8 @@ public abstract class
> AjaxFormComponentUpdatingBehavior extends AjaxEventBehavio
> catch (RuntimeException e)
> {
> onError(target, e);
> -
> }
> + formComponent.updateAutoLabels(target);
> }
>
> /**
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/a73209be/wicket-core/src/main/java/org/apache/wicket/core/util/string/CssUtils.java
> ----------------------------------------------------------------------
> diff --git
> a/wicket-core/src/main/java/org/apache/wicket/core/util/string/CssUtils.java
> b/wicket-core/src/main/java/org/apache/wicket/core/util/string/CssUtils.java
> index a4944a3..7de8669 100644
> ---
> a/wicket-core/src/main/java/org/apache/wicket/core/util/string/CssUtils.java
> +++
> b/wicket-core/src/main/java/org/apache/wicket/core/util/string/CssUtils.java
> @@ -103,4 +103,18 @@ public final class CssUtils
> }
> response.write(" />");
> }
> +
> + /**
> + * Get a standardized key for a CSS class.
> + *
> + * @param scope
> + * scope of CSS class
> + * @param facet
> + * facet of CSS class
> + * @return CSS key
> + */
> + public static String key(Class<?> scope, String facet)
> + {
> + return scope.getSimpleName() + ".CSS." + facet;
> + }
> }
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/a73209be/wicket-core/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java
> ----------------------------------------------------------------------
> diff --git
> a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java
> b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java
> index 562e6ed..7892fa7 100644
> ---
> a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java
> +++
> b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java
> @@ -16,9 +16,14 @@
> */
> package org.apache.wicket.markup.html.form;
>
> +import java.io.Serializable;
> +
> import org.apache.wicket.Component;
> import org.apache.wicket.MarkupContainer;
> +import org.apache.wicket.MetaDataKey;
> import org.apache.wicket.WicketRuntimeException;
> +import org.apache.wicket.ajax.AjaxRequestTarget;
> +import org.apache.wicket.core.util.string.CssUtils;
> import org.apache.wicket.markup.ComponentTag;
> import org.apache.wicket.markup.MarkupStream;
> import org.apache.wicket.markup.html.TransparentWebMarkupContainer;
> @@ -36,11 +41,14 @@ import org.slf4j.LoggerFactory;
> * <li>Outputs the {@code for} attribute with the value equivalent to the
> markup id of the
> * referenced form component</li>
> * <li>Appends {@code required} css class to the {@code <label>} tag if
> the referenced form
> - * component is required</li>
> + * component is required. Name of the css class can be overwritten by
> having a i18n property defined
> + * for key AutoLabelResolver.CSS.required</li>
> * <li>Appends {@code error} css class to the {@code <label>} tag if the
> referenced form component
> - * has failed validation</li>
> + * has failed validation. Name of the css class can be overwritten by
> having a i18n property defined
> + * for key AutoLabelResolver.CSS.error</li>
> * <li>Appends {@code disabled} css class to the {@code <label>} tag if
> the referenced form
> - * component has is not enabled in hierarchy</li>
> + * component has is not enabled in hierarchy. Name of the css class can
> be overwritten by having a i18n property defined
> + * for key AutoLabelResolver.CSS.disabled</li>
> * </ul>
> *
> * <p>
> @@ -64,6 +72,14 @@ public class AutoLabelResolver implements
> IComponentResolver
>
> static final String WICKET_FOR = ":for";
>
> + public static final String CSS_REQUIRED_KEY =
> CssUtils.key(AutoLabelResolver.class, "requried");
> + public static final String CSS_DISABLED_KEY =
> CssUtils.key(AutoLabelResolver.class, "requried");
> + public static final String CSS_ERROR_KEY =
> CssUtils.key(AutoLabelResolver.class, "requried");
> + private static final String CSS_DISABLED_DEFAULT = "disabled";
> + private static final String CSS_REQUIRED_DEFAULT = "required";
> + private static final String CSS_ERROR_DEFAULT = "error";
> +
> +
> @Override
> public Component resolve(final MarkupContainer container, final
> MarkupStream markupStream,
> final ComponentTag tag)
> @@ -99,6 +115,11 @@ public class AutoLabelResolver implements
> IComponentResolver
> }
> }
>
> + if (component instanceof FormComponent)
> + {
> + component.setMetaData(MARKER_KEY, new
> AutoLabelMarker((FormComponent<?>)component));
> + }
> +
> return new AutoLabel("label" +
> container.getPage().getAutoIndex(), component);
> }
>
> @@ -161,6 +182,100 @@ public class AutoLabelResolver implements
> IComponentResolver
> return null;
> }
>
> + public static final String getLabelIdFor(Component component)
> + {
> + return component.getMarkupId() + "-w-lbl";
> + }
> +
> + public static final MetaDataKey<AutoLabelMarker> MARKER_KEY = new
> MetaDataKey<AutoLabelMarker>()
> + {
> + };
> +
> + /**
> + * Marker used to track whether or not a form component has an
> associated auto label by its mere
> + * presense as well as some attributes of the component across
> requests.
> + *
> + * @author igor
> + *
> + */
> + public static final class AutoLabelMarker implements Serializable
> + {
> + public static final short VALID = 0x01;
> + public static final short REQUIRED = 0x02;
> + public static final short ENABLED = 0x04;
> +
> + private short flags;
> +
> + public AutoLabelMarker(FormComponent<?> component)
> + {
> + setFlag(VALID, component.isValid());
> + setFlag(REQUIRED, component.isRequired());
> + setFlag(ENABLED, component.isEnabledInHierarchy());
> + }
> +
> + public void updateFrom(FormComponent<?> component,
> AjaxRequestTarget target)
> + {
> + boolean valid = component.isValid(), required =
> component.isRequired(), enabled = component.isEnabledInHierarchy();
> +
> + if (isValid() != valid)
> + {
> +
> target.appendJavaScript(String.format("$('#%s').toggleClass('%s', %s);",
>
Until now we haven't used jQuery APIs directly in the Java code.
This makes it harder to use different impl of wicket-event/ajax js.
> + getLabelIdFor(component),
> component.getString(CSS_ERROR_KEY, null, CSS_ERROR_DEFAULT),
> + !valid));
> + }
> +
> + if (isRequired() != required)
> + {
> +
> target.appendJavaScript(String.format("$('#%s').toggleClass('%s', %s);",
> + getLabelIdFor(component),
> component.getString(CSS_REQUIRED_KEY, null, CSS_REQUIRED_DEFAULT),
> + required));
> + }
> +
> + if (isEnabled() != enabled)
> + {
> +
> target.appendJavaScript(String.format("$('#%s').toggleClass('%s', %s);",
> + getLabelIdFor(component),
> component.getString(CSS_DISABLED_KEY, null, CSS_DISABLED_DEFAULT),
> + !enabled));
> + }
> +
> + setFlag(VALID, valid);
> + setFlag(REQUIRED, required);
> + setFlag(ENABLED, enabled);
> + }
> +
> + public boolean isValid()
> + {
> + return getFlag(VALID);
> + }
> +
> + public boolean isEnabled()
> + {
> + return getFlag(ENABLED);
> + }
> +
> + public boolean isRequired()
> + {
> + return getFlag(REQUIRED);
> + }
> +
> + private boolean getFlag(final int flag)
> + {
> + return (flags & flag) != 0;
> + }
> +
> + private void setFlag(final short flag, final boolean set)
> + {
> + if (set)
> + {
> + flags |= flag;
> + }
> + else
> + {
> + flags &= ~flag;
> + }
> + }
> + }
> +
> /**
> * Component that is attached to the {@code <label>} tag and takes
> care of writing out the label
> * text as well as setting classes on the {@code <label>} tag
> @@ -184,23 +299,24 @@ public class AutoLabelResolver implements
> IComponentResolver
> {
> super.onComponentTag(tag);
> tag.put("for", component.getMarkupId());
> + tag.put("id", getLabelIdFor(component));
>
> if (component instanceof FormComponent)
> {
> FormComponent<?> fc =
> (FormComponent<?>)component;
> if (fc.isRequired())
> {
> - tag.append("class", "required", "
> ");
> + tag.append("class",
> component.getString(CSS_REQUIRED_KEY, null, CSS_REQUIRED_DEFAULT), " ");
> }
> if (!fc.isValid())
> {
> - tag.append("class", "error", " ");
> + tag.append("class",
> component.getString(CSS_ERROR_KEY, null, CSS_ERROR_DEFAULT), " ");
> }
> }
>
> if (!component.isEnabledInHierarchy())
> {
> - tag.append("class", "disabled", " ");
> + tag.append("class",
> component.getString(CSS_DISABLED_KEY, null, CSS_DISABLED_DEFAULT), " ");
> }
> }
>
> @@ -213,4 +329,6 @@ public class AutoLabelResolver implements
> IComponentResolver
> return component;
> }
> }
> +
> +
> }
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/a73209be/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
> ----------------------------------------------------------------------
> diff --git
> a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
> b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
> index a7f07f3..a9ea6a6 100644
> ---
> a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
> +++
> b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
> @@ -30,6 +30,7 @@ import org.apache.wicket.Component;
> import org.apache.wicket.IGenericComponent;
> import org.apache.wicket.Page;
> import org.apache.wicket.WicketRuntimeException;
> +import org.apache.wicket.ajax.AjaxRequestTarget;
> import org.apache.wicket.behavior.Behavior;
> import org.apache.wicket.markup.ComponentTag;
> import org.apache.wicket.markup.MarkupStream;
> @@ -144,10 +145,8 @@ import org.slf4j.LoggerFactory;
> * @param <T>
> * The model object type
> */
> -public class Form<T> extends WebMarkupContainer
> - implements
> - IFormSubmitListener,
> - IGenericComponent<T>
> +public class Form<T> extends WebMarkupContainer implements
> IFormSubmitListener,
> + IGenericComponent<T>
> {
> private static final String HIDDEN_DIV_START = "<div
> style=\"width:0px;height:0px;position:absolute;left:-100px;top:-100px;overflow:hidden\">";
>
> @@ -778,6 +777,20 @@ public class Form<T> extends WebMarkupContainer
> {
> callOnError(submitter);
> }
> +
> +
> + if (((WebRequest)getRequest()).isAjax())
> + {
> + final AjaxRequestTarget target =
> getRequestCycle().find(AjaxRequestTarget.class);
> + visitChildren(FormComponent.class, new
> IVisitor<FormComponent<?>, Void>()
> + {
> + @Override
> + public void component(FormComponent<?>
> component, IVisit<Void> visit)
> + {
> + component.updateAutoLabels(target);
> + }
> + });
> + }
> }
>
> /**
> @@ -2089,7 +2102,8 @@ public class Form<T> extends WebMarkupContainer
> *
> * @author igor
> */
> - public static enum MethodMismatchResponse {
> + public static enum MethodMismatchResponse
> + {
> /**
> * Continue processing.
> */
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/a73209be/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java
> ----------------------------------------------------------------------
> diff --git
> a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java
> b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java
> index 450b6bd..e4b89ed 100644
> ---
> a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java
> +++
> b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/FormComponent.java
> @@ -36,12 +36,15 @@ import org.apache.wicket.IConverterLocator;
> import org.apache.wicket.IGenericComponent;
> import org.apache.wicket.Localizer;
> import org.apache.wicket.WicketRuntimeException;
> +import org.apache.wicket.ajax.AjaxRequestTarget;
> import org.apache.wicket.behavior.Behavior;
> import org.apache.wicket.core.util.lang.WicketObjects;
> import org.apache.wicket.markup.ComponentTag;
> +import
> org.apache.wicket.markup.html.form.AutoLabelResolver.AutoLabelMarker;
> import org.apache.wicket.model.IModel;
> import org.apache.wicket.model.IPropertyReflectionAwareModel;
> import org.apache.wicket.model.Model;
> +import org.apache.wicket.protocol.http.WebApplication;
> import org.apache.wicket.util.convert.ConversionException;
> import org.apache.wicket.util.convert.IConverter;
> import org.apache.wicket.util.lang.Args;
> @@ -98,11 +101,8 @@ import org.slf4j.LoggerFactory;
> * The model object type
> *
> */
> -public abstract class FormComponent<T> extends LabeledWebMarkupContainer
> - implements
> - IFormVisitorParticipant,
> - IFormModelUpdateListener,
> - IGenericComponent<T>
> +public abstract class FormComponent<T> extends LabeledWebMarkupContainer
> implements
> + IFormVisitorParticipant, IFormModelUpdateListener,
> IGenericComponent<T>
> {
> private static final Logger logger =
> LoggerFactory.getLogger(FormComponent.class);
>
> @@ -1579,6 +1579,30 @@ public abstract class FormComponent<T> extends
> LabeledWebMarkupContainer
> }
>
> /**
> + * Updates auto label css classes such as error/required during
> ajax updates when the labels may
> + * not be directly repainted in the response.
> + *
> + * @param target
> + */
> + public final void updateAutoLabels(AjaxRequestTarget target)
> + {
> + if
> (!((WebApplication)getApplication()).getUpdateAutoLabelsOnAjaxRequests())
> + {
> + return;
> + }
> +
> + AutoLabelMarker marker =
> getMetaData(AutoLabelResolver.MARKER_KEY);
> +
> + if (marker == null)
> + {
> + // this component does not have an auto label
> + return;
> + }
> +
> + marker.updateFrom(this, target);
> + }
> +
> + /**
> * Update the model of a {@link FormComponent} containing a {@link
> Collection}.
> *
> * If the model object does not yet exists, a new {@link
> ArrayList} is filled with the converted
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/a73209be/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
> ----------------------------------------------------------------------
> diff --git
> a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
> b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
> index ba69791..22bbfda 100644
> ---
> a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
> +++
> b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
> @@ -394,10 +394,10 @@ public abstract class WebApplication extends
> Application
> /**
> * Registers a replacement resource for the given javascript
> resource. This replacement can be
> * another {@link JavaScriptResourceReference} for a packaged
> resource, but it can also be an
> - * {@link org.apache.wicket.request.resource.UrlResourceReference}
> to replace the resource by a resource hosted on a CDN.
> - * Registering a replacement will cause the resource to replaced
> by the given resource
> - * throughout the application: if {@code base} is added, {@code
> replacement} will be added
> - * instead.
> + * {@link org.apache.wicket.request.resource.UrlResourceReference}
> to replace the resource by a
> + * resource hosted on a CDN. Registering a replacement will cause
> the resource to replaced by
> + * the given resource throughout the application: if {@code base}
> is added, {@code replacement}
> + * will be added instead.
> *
> * @param base
> * The resource to replace
> @@ -415,10 +415,10 @@ public abstract class WebApplication extends
> Application
> /**
> * Registers a replacement resource for the given CSS resource.
> This replacement can be another
> * {@link CssResourceReference} for a packaged resource, but it
> can also be an
> - * {@link org.apache.wicket.request.resource.UrlResourceReference}
> to replace the resource by a resource hosted on a CDN.
> - * Registering a replacement will cause the resource to replaced
> by the given resource
> - * throughout the application: if {@code base} is added, {@code
> replacement} will be added
> - * instead.
> + * {@link org.apache.wicket.request.resource.UrlResourceReference}
> to replace the resource by a
> + * resource hosted on a CDN. Registering a replacement will cause
> the resource to replaced by
> + * the given resource throughout the application: if {@code base}
> is added, {@code replacement}
> + * will be added instead.
> *
> * @param base
> * The resource to replace
> @@ -951,9 +951,8 @@ public abstract class WebApplication extends
> Application
> return ajaxRequestTargetListeners;
> }
>
> - private static class DefaultAjaxRequestTargetProvider
> - implements
> - IContextProvider<AjaxRequestTarget, Page>
> + private static class DefaultAjaxRequestTargetProvider implements
> + IContextProvider<AjaxRequestTarget, Page>
> {
> @Override
> public AjaxRequestTarget get(Page page)
> @@ -981,4 +980,19 @@ public abstract class WebApplication extends
> Application
> }
> return filterFactoryManager;
> }
> +
> + /**
> + * If true, auto label css classes such as {@code error} and
> {@code required} will be updated
> + * after form component processing during an ajax request. This
> allows auto labels to correctly
> + * reflect the state of the form component even if they are not
> part of the ajax markup update.
> + *
> + * TODO in wicket-7 this should move into a settings object.
> cannot move in 6.x because it
> + * requires a change to a setting interface.
> + *
> + * @return {@code true} iff enabled
> + */
> + public boolean getUpdateAutoLabelsOnAjaxRequests()
> + {
> + return true;
> + }
> }
>
>