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
>

Reply via email to