r1144934 fixed the inconsistency
thanks!

On Sun, Jul 10, 2011 at 6:14 PM, Igor Vaynberg <[email protected]> wrote:
> because AutoLabel handles the label text output/input in a completely
> different way and i didnt want to break backwards compat this late in
> the game.
>
> -igor
>
>
> On Sun, Jul 10, 2011 at 3:29 AM, Martin Grigorov <[email protected]> wrote:
>> 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
>>
>



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

Reply via email to