Hi,

Why did you prefer to introduce AutoLabel instead of using
re-FormComponentLabel ?
I see the new one has some more logic about setting required/valid classes.
The diff I notice in FormComponentLabel is that it accepts
LabeledWebMarkupContainer instead of FormComponent as ctor parameter.
This allows it to be used with Check, Radio and CheckGroupSelector
additionally.

On Sat, Jul 9, 2011 at 6:15 AM,  <[email protected]> wrote:
> Author: ivaynberg
> Date: Sat Jul  9 04:15:13 2011
> New Revision: 1144589
>
> URL: http://svn.apache.org/viewvc?rev=1144589&view=rev
> Log:
> wicket:for attribute to make it easy to link form component labels to form 
> components
> Issue: WICKET-1469
>
> Added:
>    
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java
>    (with props)
>    
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelTagHandler.java
>    (with props)
>    
> wicket/branches/wicket-1.4.x/wicket/src/test/java/org/apache/wicket/markup/html/form/AutoLabelTest.java
>    (with props)
> Modified:
>    
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/MarkupParser.java
>    
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
>
> Modified: 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/MarkupParser.java
> URL: 
> http://svn.apache.org/viewvc/wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/MarkupParser.java?rev=1144589&r1=1144588&r2=1144589&view=diff
> ==============================================================================
> --- 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/MarkupParser.java
>  (original)
> +++ 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/MarkupParser.java
>  Sat Jul  9 04:15:13 2011
> @@ -24,6 +24,7 @@ import java.util.regex.Pattern;
>  import org.apache.wicket.Application;
>  import org.apache.wicket.Page;
>  import org.apache.wicket.WicketRuntimeException;
> +import org.apache.wicket.markup.html.form.AutoLabelTagHandler;
>  import org.apache.wicket.markup.parser.IMarkupFilter;
>  import org.apache.wicket.markup.parser.IXmlPullParser;
>  import org.apache.wicket.markup.parser.XmlPullParser;
> @@ -163,6 +164,7 @@ public class MarkupParser
>                appendMarkupFilter(new WicketLinkTagHandler());
>                appendMarkupFilter(new 
> WicketNamespaceHandler(markupResourceData));
>
> +
>                // Provided the wicket component requesting the markup is 
> known ...
>                final MarkupResourceStream resource = 
> markupResourceData.getResource();
>                if (resource != null)
> @@ -186,6 +188,7 @@ public class MarkupParser
>                appendMarkupFilter(new RelativePathPrefixHandler());
>                appendMarkupFilter(new EnclosureHandler());
>                appendMarkupFilter(new InlineEnclosureHandler());
> +               appendMarkupFilter(new AutoLabelTagHandler());
>        }
>
>        /**
>
> Added: 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java
> URL: 
> http://svn.apache.org/viewvc/wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java?rev=1144589&view=auto
> ==============================================================================
> --- 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java
>  (added)
> +++ 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java
>  Sat Jul  9 04:15:13 2011
> @@ -0,0 +1,372 @@
> +package org.apache.wicket.markup.html.form;
> +
> +import org.apache.wicket.Component;
> +import org.apache.wicket.Component.IVisitor;
> +import org.apache.wicket.MarkupContainer;
> +import org.apache.wicket.WicketRuntimeException;
> +import org.apache.wicket.markup.ComponentTag;
> +import org.apache.wicket.markup.MarkupElement;
> +import org.apache.wicket.markup.MarkupStream;
> +import org.apache.wicket.markup.RawMarkup;
> +import org.apache.wicket.markup.html.WebMarkupContainer;
> +import org.apache.wicket.markup.parser.XmlPullParser;
> +import org.apache.wicket.markup.parser.XmlTag;
> +import org.apache.wicket.markup.resolver.IComponentResolver;
> +import org.apache.wicket.model.Model;
> +import org.apache.wicket.util.string.AppendingStringBuffer;
> +import org.apache.wicket.util.string.Strings;
> +import org.slf4j.Logger;
> +import org.slf4j.LoggerFactory;
> +
> +/**
> + * Resolver that implements the {@code wicket:for} attribute functionality. 
> The attribute makes it
> + * easy to set up {@code <label>} tags for form components by providing the 
> following features
> + * without having to add any additional components in code:
> + * <ul>
> + * <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>
> + * <li>Appends {@code error} css class to the {@code <label>} tag if the 
> referenced form component
> + * has failed validation</li>
> + * <li>If the {@code <label>} tag contains {@code <span 
> class='text'></span>} markup and the form
> + * component has a label configured either via the label model or a property 
> files, the body of the
> + * {code <span>} will be replaced with the label</li>
> + * <li>If the {@code <label>} tag contains {@code <span 
> class='text'>body</span>} markup and the
> + * form component does not have a label configured either via the label 
> model or a properties file,
> + * the label of the form component will be set to the body of the {@code 
> <span>} tag - in this
> + * example {@code body}</li>
> + * </ul>
> + *
> + * <p>
> + * The value of the {@code wicket:for} atribute can either contain an id of 
> the form component or a
> + * path a path to it using the standard {@code :} path separator. Note that 
> {@code ..} can be used
> + * as part of the path to construct a reference to the parent container, eg 
> {@code ..:..:foo:bar}.
> + * First the value of the attribute will be treated as a path and the {@code 
> <label>} tag's closest
> + * parent container will be queried for the form component. If the form 
> component cannot be resolved
> + * the value of the {@code wicket:for} attribute will be treated as an id 
> and all containers will be
> + * searched from the closest parent to the page.
> + * </p>
> + *
> + * <p>
> + * Given markup like this:
> + *
> + * <code>
> + * [label wicket:for="name"][span class="text"]Name[/span]:[/label][input 
> wicket:id="name" type="text"/]
> + * </code>
> + *
> + * If the {@code name} component has its label set to 'First Name' the 
> resulting output will be:
> + * <code>
> + * [label for="name5"][span class="text"]First Name[/span]:[/label][input 
> name="name" type="text" id="name5"/]
> + * </code>
> + *
> + * However, if the {@code name} component does not have a label set then it 
> will be set to
> + * {@code Name} based on the markup.
> + * </p>
> + *
> + * @author igor
> + */
> +public class AutoLabelResolver implements IComponentResolver
> +{
> +       private static Logger logger = 
> LoggerFactory.getLogger(AutoLabelResolver.class);
> +
> +       public boolean resolve(MarkupContainer container, MarkupStream 
> markupStream, ComponentTag tag)
> +       {
> +               if (!AutoLabelTagHandler.class.getName().equals(tag.getId()))
> +               {
> +                       return false;
> +               }
> +
> +               final String id = tag.getAttribute("wicket:for").trim();
> +
> +               FormComponent<?> component = findRelatedComponent(container, 
> id);
> +
> +               if (component == null)
> +               {
> +                       throw new WicketRuntimeException("Could not find form 
> component with id: " + id +
> +                               " while trying to resolve wicket:for 
> attribute");
> +               }
> +               if (!(component instanceof FormComponent<?>))
> +               {
> +                       throw new WicketRuntimeException("Component pointed 
> to by wicket:for attribute: " + id +
> +                               " is not a form component");
> +               }
> +
> +               if (!component.getOutputMarkupId())
> +               {
> +                       component.setOutputMarkupId(true);
> +                       if (!component.hasBeenRendered())
> +                       {
> +                               logger.warn(
> +                                       "Form component: {} is reference via 
> a wicket:for attribute but does not have its outputMarkupId property set to 
> true",
> +                                       component.toString(false));
> +                       }
> +               }
> +               final FormComponent<?> fc = component;
> +
> +               container.autoAdd(new AutoLabel("label" + 
> container.getPage().getAutoIndex2(), fc),
> +                       markupStream);
> +
> +               return true;
> +       }
> +
> +       protected FormComponent<?> findRelatedComponent(MarkupContainer 
> container, final String id)
> +       {
> +               // try the quick and easy route first
> +
> +               Component component = container.get(id);
> +               if (component != null && (component instanceof 
> FormComponent<?>))
> +               {
> +                       return (FormComponent<?>)component;
> +               }
> +
> +               // try the long way, search the hierarchy from the closest 
> container up to the page
> +
> +               final Component[] searched = new Component[] { null };
> +               while (container != null)
> +               {
> +                       component = 
> (Component)container.visitChildren(Component.class,
> +                               new IVisitor<Component>()
> +                               {
> +                                       public Object component(Component 
> child)
> +                                       {
> +                                               if (child == searched[0])
> +                                               {
> +                                                       // this container was 
> already searched
> +                                                       return 
> CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER;
> +                                               }
> +                                               if (id.equals(child.getId()) 
> && (child instanceof FormComponent))
> +                                               {
> +                                                       return child;
> +                                               }
> +                                               return CONTINUE_TRAVERSAL;
> +                                       }
> +                               });
> +
> +                       if (component != null && (component instanceof 
> FormComponent))
> +                       {
> +                               return (FormComponent<?>)component;
> +                       }
> +
> +                       // remember the container so we dont search it again, 
> and search the parent
> +                       searched[0] = container;
> +                       container = container.getParent();
> +               }
> +
> +               return null;
> +       }
> +
> +       /**
> +        * 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
> +        *
> +        * @author igor
> +        */
> +       protected static class AutoLabel extends WebMarkupContainer
> +       {
> +               private final FormComponent<?> fc;
> +
> +               public AutoLabel(String id, FormComponent<?> fc)
> +               {
> +                       super(id);
> +                       this.fc = fc;
> +               }
> +
> +               @Override
> +               protected void onComponentTag(ComponentTag tag)
> +               {
> +                       super.onComponentTag(tag);
> +                       tag.put("for", fc.getMarkupId());
> +                       if (fc.isRequired())
> +                       {
> +                               tag.append("class", "required", " ");
> +                       }
> +                       if (!fc.isValid())
> +                       {
> +                               tag.append("class", "error", " ");
> +                       }
> +               }
> +
> +               @Override
> +               protected void onComponentTagBody(MarkupStream markupStream, 
> ComponentTag openTag)
> +               {
> +                       if (!(markupStream.get() instanceof RawMarkup))
> +                       {
> +                               // no raw markup found inside the label, do 
> not modify the contents
> +                               return;
> +                       }
> +
> +                       // read all raw markup in the body and find the range 
> of the label text inside it. the
> +                       // range is specified as the body of the <span 
> class='text'></span> tag.
> +
> +                       AppendingStringBuffer markup = 
> readBodyMarkup(markupStream);
> +                       int[] range = findLabelTextRange(markup);
> +                       final int start = range[0];
> +                       final int end = range[1];
> +
> +                       if (start < 0)
> +                       {
> +                               // if we could not find the range of the 
> label text in the markup we have nothing
> +                               // further to do
> +
> +                               super.onComponentTagBody(markupStream, 
> openTag);
> +                               return;
> +                       }
> +
> +                       // based on whether or not the form component has a 
> label set read or write it into the
> +                       // markup
> +
> +                       String label = getFormComponentLabelText(fc);
> +
> +                       if (label != null)
> +                       {
> +                               // if label is set write it into the markup
> +
> +                               markup = markup.replace(start, end, label);
> +                               replaceComponentTagBody(markupStream, 
> openTag, markup);
> +                       }
> +                       else
> +                       {
> +                               // if label is not set, read it from the 
> markup into the form component
> +
> +                               String markupLabel = markup.substring(start, 
> end);
> +                               fc.setLabel(Model.of(markupLabel));
> +                               super.onComponentTagBody(markupStream, 
> openTag);
> +                       }
> +               }
> +
> +               /**
> +                * Finds start and end index of text in the label. This range 
> is represented by the body of
> +                * the {@code <span class='text'></span>} tag
> +                *
> +                * @param markup
> +                * @return
> +                */
> +               protected int[] findLabelTextRange(AppendingStringBuffer 
> markup)
> +               {
> +                       int[] range = new int[] { -1, -1 };
> +
> +                       XmlPullParser parser = new XmlPullParser();
> +                       XmlTag opening = null; // opening label text span tag
> +                       XmlTag closing = null; // close label text span tag
> +
> +                       try
> +                       {
> +                               parser.parse(markup);
> +
> +                               XmlTag tag = null; // current tag
> +
> +                               int depth = 0; // depth of span tags
> +                               int openDepth = -1; // depth of the label 
> text open span tag
> +
> +                               while (((tag = (XmlTag)parser.nextTag()) != 
> null))
> +                               {
> +                                       if 
> (!"span".equalsIgnoreCase(tag.getName()) || tag.getNamespace() != null)
> +                                       {
> +                                               // skip non-span tags
> +                                               continue;
> +                                       }
> +
> +                                       if (opening != null && tag.isClose() 
> && depth == openDepth)
> +                                       {
> +                                               // found the closing tag we 
> need, we are done
> +                                               closing = tag;
> +                                               break;
> +                                       }
> +
> +                                       depth += tag.isOpen() ? 1 : -1;
> +
> +                                       if (opening == null && 
> isTextSpan(tag))
> +                                       {
> +                                               // found the opening tag, 
> keep looking for the closing one
> +                                               opening = tag;
> +                                               openDepth = depth;
> +                                               continue;
> +                                       }
> +                               }
> +                       }
> +                       catch (Exception e)
> +                       {
> +                               throw new WicketRuntimeException(
> +                                       "Could not parse markup while 
> processing an auto label for component: " +
> +                                               fc.toString(false), e);
> +                       }
> +
> +                       if (opening != null)
> +                       {
> +                               // calculate the range of the tag's body, 
> this is where the label text is/will be
> +                               range[0] = opening.getPos() + 
> opening.getLength();
> +                               range[1] = closing.getPos();
> +                       }
> +
> +                       return range;
> +               }
> +
> +               protected AppendingStringBuffer readBodyMarkup(MarkupStream 
> markupStream)
> +               {
> +                       int streamIndex = markupStream.getCurrentIndex();
> +
> +                       AppendingStringBuffer markup = new 
> AppendingStringBuffer();
> +                       do
> +                       {
> +                               
> markup.append(((RawMarkup)markupStream.get()).toString());
> +                               markupStream.next();
> +                       }
> +                       while ((markupStream.get() instanceof RawMarkup));
> +
> +                       markupStream.setCurrentIndex(streamIndex);
> +
> +                       return markup;
> +               }
> +
> +               protected String getFormComponentLabelText(FormComponent<?> 
> fc)
> +               {
> +                       String label = fc.getLabel() != null ? 
> fc.getLabel().getObject() : null;
> +                       if (label == null)
> +                       {
> +                               label = fc.getDefaultLabel("wicket:unknown");
> +                               if ("wicket:unknown".equals(label))
> +                               {
> +                                       label = null;
> +                               }
> +                       }
> +                       return label;
> +               }
> +
> +               protected final boolean isTextSpan(MarkupElement element)
> +               {
> +                       if (!(element instanceof XmlTag))
> +                               return false;
> +
> +                       XmlTag tag = (XmlTag)element;
> +
> +                       if (!tag.isOpen())
> +                               return false;
> +
> +                       if (!"span".equalsIgnoreCase(tag.getName()) || 
> tag.getNamespace() != null)
> +                               return false;
> +
> +                       String classNames = 
> tag.getAttributes().getString("class");
> +                       if (Strings.isEmpty(classNames))
> +                               return false;
> +
> +                       boolean textClassFound = false;
> +                       for (String className : classNames.split(" "))
> +                       {
> +                               if ("text".equals(className))
> +                               {
> +                                       textClassFound = true;
> +                                       break;
> +                               }
> +                       }
> +                       if (!textClassFound)
> +                               return false;
> +
> +
> +                       return true;
> +               }
> +
> +       }
> +
> +
> +}
>
> Propchange: 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelResolver.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
> Added: 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelTagHandler.java
> URL: 
> http://svn.apache.org/viewvc/wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelTagHandler.java?rev=1144589&view=auto
> ==============================================================================
> --- 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelTagHandler.java
>  (added)
> +++ 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelTagHandler.java
>  Sat Jul  9 04:15:13 2011
> @@ -0,0 +1,52 @@
> +package org.apache.wicket.markup.html.form;
> +
> +import java.text.ParseException;
> +
> +import org.apache.wicket.markup.ComponentTag;
> +import org.apache.wicket.markup.MarkupElement;
> +import org.apache.wicket.markup.parser.AbstractMarkupFilter;
> +
> +/**
> + * Markup filter that identifies tags with the {@code wicket:for} attribute. 
> See
> + * {@link AutoLabelResolver} for details.
> + *
> + * @author igor
> + */
> +public class AutoLabelTagHandler extends AbstractMarkupFilter
> +{
> +       public MarkupElement nextTag() throws ParseException
> +       {
> +               final ComponentTag tag = nextComponentTag();
> +               if (tag == null || tag.isClose())
> +               {
> +                       return tag;
> +               }
> +
> +               String related = tag.getAttribute("wicket:for");
> +               if (related == null)
> +               {
> +                       return tag;
> +               }
> +
> +               related = related.trim();
> +               if (related.isEmpty())
> +               {
> +                       throw new ParseException("Tag contains an empty 
> wicket:for attribute", tag.getPos());
> +               }
> +               if (!"label".equalsIgnoreCase(tag.getName()))
> +               {
> +                       throw new ParseException("Attribute wicket:for can 
> only be attached to <label> tag",
> +                               tag.getPos());
> +               }
> +               if (tag.getId() != null)
> +               {
> +                       throw new ParseException(
> +                               "Attribute wicket:for cannot be used in 
> conjunction with wicket:id", tag.getPos());
> +               }
> +
> +               tag.setId(getClass().getName());
> +               tag.setModified(true);
> +               return tag;
> +       }
> +
> +}
>
> Propchange: 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/markup/html/form/AutoLabelTagHandler.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
> Modified: 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
> URL: 
> http://svn.apache.org/viewvc/wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/protocol/http/WebApplication.java?rev=1144589&r1=1144588&r2=1144589&view=diff
> ==============================================================================
> --- 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
>  (original)
> +++ 
> wicket/branches/wicket-1.4.x/wicket/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
>  Sat Jul  9 04:15:13 2011
> @@ -34,6 +34,7 @@ import org.apache.wicket.Response;
>  import org.apache.wicket.Session;
>  import org.apache.wicket.WicketRuntimeException;
>  import org.apache.wicket.ajax.AjaxRequestTarget;
> +import org.apache.wicket.markup.html.form.AutoLabelResolver;
>  import org.apache.wicket.markup.html.pages.AccessDeniedPage;
>  import org.apache.wicket.markup.html.pages.InternalErrorPage;
>  import org.apache.wicket.markup.html.pages.PageExpiredErrorPage;
> @@ -555,6 +556,7 @@ public abstract class WebApplication ext
>
>                // Add resolver for automatically resolving HTML links
>                getPageSettings().addComponentResolver(new AutoLinkResolver());
> +               getPageSettings().addComponentResolver(new 
> AutoLabelResolver());
>
>                // Set resource finder to web app path
>                getResourceSettings().setResourceFinder(getResourceFinder());
>
> Added: 
> wicket/branches/wicket-1.4.x/wicket/src/test/java/org/apache/wicket/markup/html/form/AutoLabelTest.java
> URL: 
> http://svn.apache.org/viewvc/wicket/branches/wicket-1.4.x/wicket/src/test/java/org/apache/wicket/markup/html/form/AutoLabelTest.java?rev=1144589&view=auto
> ==============================================================================
> --- 
> wicket/branches/wicket-1.4.x/wicket/src/test/java/org/apache/wicket/markup/html/form/AutoLabelTest.java
>  (added)
> +++ 
> wicket/branches/wicket-1.4.x/wicket/src/test/java/org/apache/wicket/markup/html/form/AutoLabelTest.java
>  Sat Jul  9 04:15:13 2011
> @@ -0,0 +1,198 @@
> +/*
> + * 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.markup.html.form;
> +
> +import org.apache.wicket.MarkupContainer;
> +import org.apache.wicket.Page;
> +import org.apache.wicket.WicketTestCase;
> +import org.apache.wicket.markup.IMarkupCacheKeyProvider;
> +import org.apache.wicket.markup.IMarkupResourceStreamProvider;
> +import org.apache.wicket.markup.html.WebPage;
> +import org.apache.wicket.model.Model;
> +import org.apache.wicket.util.resource.IResourceStream;
> +import org.apache.wicket.util.resource.StringResourceStream;
> +
> +/**
> + * Tests {@code wicket:for} attribute functionality
> + *
> + * @author igor
> + */
> +public class AutoLabelTest extends WicketTestCase
> +{
> +       public void testLabelIntoMarkupInsertion()
> +       {
> +               class MyTestPage extends TestPage
> +               {
> +                       public MyTestPage(String labelMarkup)
> +                       {
> +                               super("<label wicket:for='t'>" + labelMarkup 
> + "</label>");
> +                               field.setLabel(Model.of("t"));
> +                       }
> +               }
> +
> +               // simple insertion
> +               assertRendered(new MyTestPage("<span 
> class='text'>text</span>"),
> +                       "<span class='text'>t</span>");
> +
> +
> +               // preserves markup before and after
> +               assertRendered(new MyTestPage(" <div> a </div> <span 
> class='text'>text</span> b "),
> +                       " <div> a </div> <span class='text'>t</span> b ");
> +
> +
> +               // embedded span tags
> +               assertRendered(new MyTestPage(" a <div> b <span 
> class='text'>text</span> c </div> d"),
> +                       " a <div> b <span class='text'>t</span> c </div> d");
> +
> +               // double text span tags - only the first one is touched
> +               assertRendered(new MyTestPage(
> +                       "<span class='text'>text</span><span 
> class='text'>text</span>"),
> +                       "<span class='text'>t</span><span 
> class='text'>text</span>");
> +
> +               // no span - no insertion
> +               assertRendered(new MyTestPage(" text "), " text ");
> +
> +               // empty label tag
> +               assertRendered(new MyTestPage(""), "></label>");
> +
> +               // empty span tag
> +               assertRendered(new MyTestPage("<span class='text'></span>"), 
> "<span class='text'>t</span>");
> +
> +               // open/close span tag
> +               assertRendered(new MyTestPage("<span class='text'/>"), "<span 
> class='text'>t</span>");
> +
> +               // test additional classes on the span are preserved
> +               assertRendered(new MyTestPage("<span class='foo text bar'/>"),
> +                       "<span class='foo text bar'>t</span>");
> +       }
> +
> +       public void testMarkupIntoLabelInsertion()
> +       {
> +               class MyTestPage extends TestPage
> +               {
> +                       public MyTestPage(String labelMarkup)
> +                       {
> +                               super("<label wicket:for='t'>" + labelMarkup 
> + "</label>");
> +                       }
> +               }
> +
> +               // test form component label is defaulted to the contents of 
> span class='text'
> +
> +               MyTestPage page = new MyTestPage("<span 
> class='text'>text</span>");
> +               tester.startPage(page);
> +               assertEquals("text", 
> ((MyTestPage)tester.getLastRenderedPage()).field.getLabel()
> +                       .getObject());
> +       }
> +
> +       public void testLabelTagClasses()
> +       {
> +               class MyTestPage extends TestPage
> +               {
> +                       public MyTestPage()
> +                       {
> +                               super("<label wicket:for='t'><span 
> class='text'>field</span></label>");
> +                       }
> +               }
> +
> +               // test required class
> +               MyTestPage page = new MyTestPage();
> +               assertNotRendered(page, "class='required'");
> +               page.field.setRequired(true);
> +               assertRendered(page, "class='required'");
> +
> +               // test error class
> +               page = new MyTestPage();
> +               assertNotRendered(page, "class='error'");
> +               page.field.error("too short");
> +               assertRendered(page, "class='error'");
> +
> +               // test classes are appended and not overridden
> +               page = new MyTestPage();
> +               page.field.setRequired(true);
> +               page.field.error("too short");
> +               tester.startPage(page);
> +               String markup = tester.getServletResponse().getDocument();
> +               assertTrue(markup.contains("class=\"required error\"") ||
> +                       markup.contains("class=\"error required\""));
> +
> +               // test existing classes are preserved
> +               class MyTestPage2 extends TestPage
> +               {
> +                       public MyTestPage2()
> +                       {
> +                               super("<label class='long' 
> wicket:for='t'><span class='text'>field</span></label>");
> +                       }
> +               }
> +
> +               MyTestPage2 page2 = new MyTestPage2();
> +               page2.field.setRequired(true);
> +               tester.startPage(page2);
> +               markup = tester.getServletResponse().getDocument();
> +               assertTrue(markup.contains("class=\"required long\"") ||
> +                       markup.contains("class=\"long required\""));
> +
> +       }
> +
> +       private void assertRendered(Page page, String markupFragment)
> +       {
> +               tester.startPage(page);
> +               String markup = tester.getServletResponse().getDocument();
> +               markup = markup.replace("'", "\"");
> +               assertTrue("fragment: [" + markupFragment + "] not found in 
> generated markup: [" + markup +
> +                       "]", markup.contains(markupFragment.replace("'", 
> "\"")));
> +       }
> +
> +       private void assertNotRendered(Page page, String markupFragment)
> +       {
> +               tester.startPage(page);
> +               String markup = tester.getServletResponse().getDocument();
> +               markup = markup.replace("'", "\"");
> +               assertFalse("fragment: [" + markupFragment + "] not found in 
> generated markup: [" + markup +
> +                       "]", markup.contains(markupFragment.replace("'", 
> "\"")));
> +       }
> +
> +       private static class TestPage extends WebPage
> +               implements
> +                       IMarkupResourceStreamProvider,
> +                       IMarkupCacheKeyProvider
> +       {
> +               TextField<String> field;
> +
> +               private final String labelMarkup;
> +
> +               public TestPage(String labelMarkup)
> +               {
> +                       this.labelMarkup = labelMarkup;
> +                       Form<?> form = new Form<Void>("f");
> +                       add(form);
> +                       form.add(field = new TextField<String>("t", 
> Model.of("")));
> +               }
> +
> +               public IResourceStream 
> getMarkupResourceStream(MarkupContainer container,
> +                       Class<?> containerClass)
> +               {
> +                       return new StringResourceStream("<html><body><form 
> wicket:id='f'>\n" + labelMarkup +
> +                               "\n<input type='text' 
> wicket:id='t'/>\n</form></body></html>");
> +               }
> +
> +               public String getCacheKey(MarkupContainer container, Class<?> 
> containerClass)
> +               {
> +                       // no cache
> +                       return null;
> +               }
> +       }
> +}
>
> Propchange: 
> wicket/branches/wicket-1.4.x/wicket/src/test/java/org/apache/wicket/markup/html/form/AutoLabelTest.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
>
>



-- 
Martin Grigorov
jWeekend
Training, Consulting, Development
http://jWeekend.com

Reply via email to