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 >
