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;
> +       }
>  }
>
>

Reply via email to