- Revision
- 163
- Author
- gas
- Date
- 2007-06-19 11:55:32 -0500 (Tue, 19 Jun 2007)
Log Message
new select tokens tag
Modified Paths
- trunk/distribution2/src/content/sitemap.xml
- trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/SelectTag.java
- trunk/extensions/taglib/src/main/resources/META-INF/waffle.tld
- trunk/extensions/taglib-acceptance/pom.xml
- trunk/extensions/taglib-acceptance/src/main/webapp/index.jsp
- trunk/extensions/taglib-acceptance/src/main/webapp/select.jsp
Added Paths
- trunk/distribution2/src/content/taglib/select.html
- trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/BasicSelectTag.java
- trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/SelectTokensTag.java
- trunk/extensions/taglib-acceptance/src/main/webapp/selectTokens.jsp
- trunk/extensions/taglib-acceptance/src/test/java/org/codehaus/waffle/taglib/acceptance/SelectTokensTest.java
Diff
Modified: trunk/distribution2/src/content/sitemap.xml (162 => 163)
--- trunk/distribution2/src/content/sitemap.xml 2007-06-19 15:39:36 UTC (rev 162) +++ trunk/distribution2/src/content/sitemap.xml 2007-06-19 16:55:32 UTC (rev 163) @@ -34,6 +34,7 @@ <page>taglib/text.html</page> <page>taglib/submit.html</page> <page>taglib/hidden.html</page> + <page>taglib/select.html</page> </section> <section> <name>Examples</name>
Copied: trunk/distribution2/src/content/taglib/select.html (from rev 162, trunk/distribution2/src/content/taglib/submit.html) (0 => 163)
--- trunk/distribution2/src/content/taglib/select.html (rev 0) +++ trunk/distribution2/src/content/taglib/select.html 2007-06-19 16:55:32 UTC (rev 163) @@ -0,0 +1,78 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> +<head> + <title>Select tag</title> +</head> +<body class="composite"> +<div id="bodyColumn"> + <div id="contentBox"> + <div class="section"><h2>Select tag</h2> + + <p>Suppose you have a <b>java.util.Collection</b> (i.e. List or Set) of <b>Product</b>s, which you want to display + in a combo box. If this + list is available in any context as <b>products</b>, it could easily be browsed as:</p> + + <div class="source"> + <pre><w:select name="product.id" items="${products}" value="id" var="product" > + ${product.name} +</w:select></pre> + </div> + </div> + <div class="section"><h2>Adding an empty line</h2> + + <p>In order to add an empty option, use the <i>addEmpty</i> attribute:</p> + + <div class="source"> + <pre><w:select name="product.id" items="${products}" value="id" var="product" addEmpty="true" > + ${product.name} +</w:select></pre> + </div> + + </div> + <div class="section"><h2>Setting the default selected item</h2> + + <p>You can set the selected item by specifying the <i>selected</i> attribute:</p> + + <div class="source"> + <pre><w:select name="product.id" items="${products}" value="id" var="product" selected="${2}" > + ${product.name} +</w:select></pre> + </div> + + <p>It will compare the <i>selected</i> attribute value with the <i>id</i> of each one of your products.</p> + + </div> + + <div class="section"><h2>Showing radio buttons</h2> + + <p>A collection of radio buttons is just another output of a collection of elements. One can create radio buttons by using the <i>type</i> attribute:</p> + + <div class="source"> + <pre><w:select name="product.id" items="${products}" value="id" var="product" type="radio" > + ${product.name} +</w:select></pre> + </div> + + </div> + + <div class="section"><h2>Using tokens instead of collections</h2> + + <p>Sometimes one faces the problem of iterating over a small list of <i>key</i>, <i>value</i> pairs, instead of having one entire collection to iterate. The + <b>w:selectTokens</b> tag works the same way as <b>w:select</b>, but instead of iterating over a collection, it uses a comma separated list of keys and values:</p> + + <div class="source"> + <pre><w:selectTokens name="writtenPosition" tokens="first,1,second,2,third,3,fourth,4,fifth,5,sixth,6,seventh,7" var="number" > + ${number} +</w:selectTokens></pre> + </div> + + <p>The above code will generate a combo box with items labeled 1, 2, ..., 7 and hidden values named first, second, ..., seventh.</p> + + <p>The <b>w:selectTokens</b> tag does not contain an <i>addEmpty</i> attribute, nor the <i>value</i> one, which does not make sense in this case.</p> + </div> + </div> +</div> + +</body> + +</html>
Added: trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/BasicSelectTag.java (0 => 163)
--- trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/BasicSelectTag.java (rev 0) +++ trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/BasicSelectTag.java 2007-06-19 16:55:32 UTC (rev 163) @@ -0,0 +1,151 @@ +package org.codehaus.waffle.taglib.form; + +import org.codehaus.waffle.taglib.writer.TypeWriter; +import org.codehaus.waffle.taglib.writer.ComboBoxTypeWriter; +import org.codehaus.waffle.taglib.writer.RadioButtonTypeWriter; + +import javax.servlet.jsp.JspWriter; +import javax.servlet.jsp.JspException; +import java.util.Map; +import java.io.Writer; +import java.io.IOException; + +/** + * A basic select tag. + * + * @author Guilherme Silveira + * @since upcoming + */ +abstract class BasicSelectTag extends FormElement { + + private static final String COMBOBOX_TYPE = "combobox"; + + private static final String RADIO_TYPE = "radio"; + + private String var, name; + + private Object selected; + + private ItemsIterator iterator; + + private TypeWriter typeWriter; + + private boolean addEmpty; + + private boolean first; + + private void addItem(Writer out, String key, boolean selected) throws IOException { + out.write(this.typeWriter.getOpeningItem(key, selected)); + } + + private String getIterationVarKey() { + return var == null ? "item" : var; + } + + @Override + public void release() { + super.release(); + var = "item"; + iterator = null; + selected = 0; + typeWriter = new ComboBoxTypeWriter(); + first = true; + addEmpty = false; + name = null; + } + + public void setType(String type) { + if (COMBOBOX_TYPE.equalsIgnoreCase(type)) { + typeWriter = new ComboBoxTypeWriter(); + } else if (RADIO_TYPE.equalsIgnoreCase(type)) { + typeWriter = new RadioButtonTypeWriter(); + } + } + + public void setSelected(Object selected) { + this.selected = selected; + } + + public void setVar(String var) { + this.var = var; + } + + @Override + protected IterationResult afterBody(JspWriter out) throws IOException { + return iterator.hasNext() ? IterationResult.BODY_AGAIN : IterationResult.PAGE; + } + + @Override + protected void end(Writer out) throws JspException, IOException { + out.write(this.typeWriter.getClosingTag(first)); + pageContext.removeAttribute(getIterationVarKey()); + release(); + super.end(out); + } + + @Override + protected void beforeBody(Writer out) throws JspException, IOException { + if (!first) { + out.write(this.typeWriter.getClosingItem()); + } + first = false; + Map.Entry entry = iterator.next(); + Object itemKey = entry.getKey(); + Object value = entry.getValue(); + boolean isSelected; + if (!(itemKey instanceof Number)) { + isSelected = itemKey.equals(selected); + } else { + isSelected = ((Number) itemKey).longValue() == ((Number)selected).longValue(); + } + addItem(out, itemKey.toString(), isSelected); + pageContext.setAttribute(getIterationVarKey(), value); + } + + + public void setAddEmpty(boolean addEmpty) { + this.addEmpty = addEmpty; + } + + + @Override + protected IterationResult start(Writer out) throws JspException, IOException { + + first = true; + attributes.put("name", name); + out.write(typeWriter.getOpeningTag(attributes)); + if (addEmpty) { + addItem(out, "", false); + first = false; + } + iterator = getItemsIterator(); + if (iterator == null) { + return IterationResult.PAGE; + } + return iterator.hasNext() ? IterationResult.BODY : IterationResult.PAGE; + } + + /** + * Returns an iterator of items to populate this select tag. + * @return the items. null or empty iterator if there are no items. + */ + protected abstract ItemsIterator getItemsIterator() ; + + public void setName(String name) { + this.name = name; + } + + @Override + protected String getDefaultLabel() { + return name; + } + + /** + * An item iterator. + */ + // gs: we do not use Iterator<Map.Entry> as you can not cache SelectTag values and we do not want to write the remove method + interface ItemsIterator { + boolean hasNext(); + Map.Entry next(); + } +}
Modified: trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/SelectTag.java (162 => 163)
--- trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/SelectTag.java 2007-06-19 15:39:36 UTC (rev 162) +++ trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/SelectTag.java 2007-06-19 16:55:32 UTC (rev 163) @@ -1,152 +1,69 @@ package org.codehaus.waffle.taglib.form; -import java.io.IOException; -import java.io.Writer; +import org.codehaus.waffle.taglib.Functions; + import java.util.Collection; import java.util.Iterator; +import java.util.Map; -import javax.servlet.jsp.JspException; -import javax.servlet.jsp.JspWriter; - -import org.codehaus.waffle.taglib.writer.ComboBoxTypeWriter; -import org.codehaus.waffle.taglib.writer.RadioButtonTypeWriter; -import org.codehaus.waffle.taglib.writer.TypeWriter; -import org.codehaus.waffle.taglib.Functions; - /** - * A combo selection or check box tag. + * A combo selection or check box tag based on a collection of items. * * @author Guilherme Silveira * @author Nico Steppat + * @since upcoming */ -public class SelectTag extends FormElement { +public class SelectTag extends BasicSelectTag { - private static final long serialVersionUID = -2367444646817282900L; - - private static final String COMBOBOX_TYPE = "combobox"; - - private static final String RADIO_TYPE = "radio"; - private Collection<Object> items; - private String name, value; - - private String var; - - private boolean addEmpty, first; - - private long selected; - - private Iterator<Object> iterator; - - private TypeWriter typeWriter; - - private void addItem(Writer out, String key, boolean selected) throws IOException { - out.write(this.typeWriter.getOpeningItem(key, selected)); - } - - private String getKey() { - return var == null ? "item" : var; - } - + private String value; + @Override public void release() { super.release(); items = null; - addEmpty = false; - var = "item"; - name = null; - iterator = null; - selected = 0; value = null; - first = true; - typeWriter = new ComboBoxTypeWriter(); } - public void setAddEmpty(boolean addEmpty) { - this.addEmpty = addEmpty; - } - - public void setType(String type) { - if (COMBOBOX_TYPE.equalsIgnoreCase(type)) { - typeWriter = new ComboBoxTypeWriter(); - } else if (RADIO_TYPE.equalsIgnoreCase(type)) { - typeWriter = new RadioButtonTypeWriter(); + protected ItemsIterator getItemsIterator() { + if (items == null) { + return null; } + return new ItemsIterator(){ + private Iterator iterator = items.iterator(); + public boolean hasNext() { + return iterator.hasNext(); + } + public Map.Entry next() { + if(!hasNext()) { + throw new IllegalStateException("This iterator does not contain any more items"); + } + return new Map.Entry() { + Object current = iterator.next(); + public Object getKey() { + return Functions.getProperty(current, value); + } + + public Object getValue() { + return current; + } + + public Object setValue(Object value) { + throw new UnsupportedOperationException(); + } + }; + } + + }; } public void setItems(Collection<Object> collection) { this.items = collection; } - public void setName(String name) { - this.name = name; - } - - public void setSelected(long selected) { - this.selected = selected; - } - public void setValue(String value) { this.value = value; } - public void setVar(String var) { - this.var = var; - } - - @Override - protected String getDefaultLabel() { - return name; - } - - @Override - protected IterationResult start(Writer out) throws JspException, IOException { - - first = true; - attributes.put("name", name); - out.write(typeWriter.getOpeningTag(attributes)); - if (addEmpty) { - addItem(out, "", false); - first = false; - } - if (items == null) { - return IterationResult.PAGE; - } - iterator = items.iterator(); - return iterator.hasNext() ? IterationResult.BODY : IterationResult.PAGE; - } - - @Override - protected IterationResult afterBody(JspWriter out) throws IOException { - return iterator.hasNext() ? IterationResult.BODY_AGAIN : IterationResult.PAGE; - } - - @Override - protected void end(Writer out) throws JspException, IOException { - - out.write(this.typeWriter.getClosingTag(first)); - pageContext.removeAttribute(getKey()); - release(); - super.end(out); - } - - @Override - protected void beforeBody(Writer out) throws JspException, IOException { - if (!first) { - out.write(this.typeWriter.getClosingItem()); - } - first = false; - Object current = iterator.next(); - Object key = Functions.getProperty(current, value); - boolean isSelected; - if (!(key instanceof Number)) { - isSelected = key.equals(selected); - } else { - isSelected = ((Number) key).longValue() == selected; - } - addItem(out, key.toString(), isSelected); - pageContext.setAttribute(getKey(), current); - } - }
Copied: trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/SelectTokensTag.java (from rev 159, trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/SelectTag.java) (0 => 163)
--- trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/SelectTokensTag.java (rev 0) +++ trunk/extensions/taglib/src/main/java/org/codehaus/waffle/taglib/form/SelectTokensTag.java 2007-06-19 16:55:32 UTC (rev 163) @@ -0,0 +1,67 @@ +package org.codehaus.waffle.taglib.form; + +import java.util.Map; + +/** + * A combo selection or check box tag based on a collection of items. + * + * @author Guilherme Silveira + * @author Nico Steppat + * @since upcoming + */ +public class SelectTokensTag extends BasicSelectTag { + + private String tokens; + private String[] parts; + + @Override + public void release() { + super.release(); + tokens = null; + } + + protected ItemsIterator getItemsIterator() { + if (tokens == null) { + return null; + } + return new ItemsIterator() { + + private int current = 0; + + public boolean hasNext() { + return current != parts.length; + } + + public Map.Entry next() { + if(!hasNext()) { + throw new IllegalStateException("This iterator does not contain any more items"); + } + Map.Entry entry = new Map.Entry() { + int position = current; + public Object getKey() { + return parts[position]; + } + + public Object getValue() { + return parts[position+1]; + } + + public Object setValue(Object value) { + throw new UnsupportedOperationException(); + } + }; + current += 2; + return entry; + } + + }; + } + + public void setTokens(String tokens) { + this.tokens = tokens; + this.parts = tokens.split(","); + if (this.parts.length % 2 != 0) { + throw new IllegalArgumentException("String '" + tokens + "' is invalid as there is an odd number of tokens in it."); + } + } +} \ No newline at end of file
Modified: trunk/extensions/taglib/src/main/resources/META-INF/waffle.tld (162 => 163)
--- trunk/extensions/taglib/src/main/resources/META-INF/waffle.tld 2007-06-19 15:39:36 UTC (rev 162) +++ trunk/extensions/taglib/src/main/resources/META-INF/waffle.tld 2007-06-19 16:55:32 UTC (rev 163) @@ -196,7 +196,7 @@ <required>false</required> <rtexprvalue>true</rtexprvalue> <type>java.lang.Boolean</type> - <description>se esse campo deve ser mostrado ou não</description> + <description>whether this field should be displayed or not</description> </attribute> <attribute> <name>items</name> @@ -240,9 +240,56 @@ <required>false</required> <rtexprvalue>true</rtexprvalue> <description>the value to be selected</description> + <type>java.lang.Object</type> </attribute> </tag> + <tag> + <name>selectTokens</name> + <tagclass>org.codehaus.waffle.taglib.form.SelectTokensTag</tagclass> + <bodycontent>scriptless</bodycontent> + <info>Tag for select box based on tokens.</info> + <dynamic-attributes>true</dynamic-attributes> + <attribute> + <name>rendered</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <type>java.lang.Boolean</type> + <description>whether this field should be displayed or not</description> + </attribute> + <attribute> + <name>tokens</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + <type>java.lang.String</type> + </attribute> + <attribute> + <name>type</name> + <required>false</required> + <type>java.lang.String</type> + <description>combobox or radio buttons</description> + </attribute> + <attribute> + <name>name</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + <type>java.lang.String</type> + <description>The field name</description> + </attribute> + <attribute> + <name>var</name> + <type>java.lang.String</type> + <description>The iterated variable name</description> + </attribute> + <attribute> + <name>selected</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <description>the value to be selected</description> + <type>java.lang.Object</type> + </attribute> + </tag> + <!-- text tag --> <tag>
Modified: trunk/extensions/taglib-acceptance/pom.xml (162 => 163)
--- trunk/extensions/taglib-acceptance/pom.xml 2007-06-19 15:39:36 UTC (rev 162) +++ trunk/extensions/taglib-acceptance/pom.xml 2007-06-19 16:55:32 UTC (rev 163) @@ -17,6 +17,18 @@ <version>${pom.version}</version> </dependency> <dependency> + <groupId>javax.servlet</groupId> + <artifactId>jstl</artifactId> + <version>1.1.2</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>taglibs</groupId> + <artifactId>standard</artifactId> + <version>1.1.2</version> + <scope>runtime</scope> + </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope>
Modified: trunk/extensions/taglib-acceptance/src/main/webapp/index.jsp (162 => 163)
--- trunk/extensions/taglib-acceptance/src/main/webapp/index.jsp 2007-06-19 15:39:36 UTC (rev 162) +++ trunk/extensions/taglib-acceptance/src/main/webapp/index.jsp 2007-06-19 16:55:32 UTC (rev 163) @@ -7,6 +7,7 @@ <a href="" /> <a href="" /> <a href="" /> +<a href="" /> <a href="" /> <a href="" /> <a href="" />
Modified: trunk/extensions/taglib-acceptance/src/main/webapp/select.jsp (162 => 163)
--- trunk/extensions/taglib-acceptance/src/main/webapp/select.jsp 2007-06-19 15:39:36 UTC (rev 162) +++ trunk/extensions/taglib-acceptance/src/main/webapp/select.jsp 2007-06-19 16:55:32 UTC (rev 163) @@ -26,7 +26,7 @@ </div> test selected=2 <br> -<w:select var="produto" name="produto.id.selected.2" items="${lista}" value="id" selected="2"> +<w:select var="produto" name="produto.id.selected.2" items="${lista}" value="id" selected="${2}"> ${produto.name} </w:select> @@ -34,7 +34,7 @@ <br> w:select type="combo": <br> -<w:select var="produto" name="produto.id" items="${lista}" value="id" selected="2" addEmpty="true"> +<w:select var="produto" name="produto.id" items="${lista}" value="id" selected="${2}" addEmpty="true"> ${produto.name} </w:select>
Copied: trunk/extensions/taglib-acceptance/src/main/webapp/selectTokens.jsp (from rev 159, trunk/extensions/taglib-acceptance/src/main/webapp/select.jsp) (0 => 163)
--- trunk/extensions/taglib-acceptance/src/main/webapp/selectTokens.jsp (rev 0) +++ trunk/extensions/taglib-acceptance/src/main/webapp/selectTokens.jsp 2007-06-19 16:55:32 UTC (rev 163) @@ -0,0 +1,32 @@ +<%@ taglib uri="http://waffle.codehaus.org" prefix="w" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<%@ page contentType="text/html;encoding=iso-8859-1" %> + +<html> +<head><title>SelectTokensTest</title></head> +<body > + +<fmt:setLocale value="pt_Br" /> + +<div id="renderedTest"> + <w:selectTokens id="notRendered" rendered="${false}" var="day" name="notRendered" tokens="first,1,second,2,third,3,fourth,4,fifth,5,sixth,6,seventh,7">${day}</w:selectTokens> + <w:selectTokens id="rendered" rendered="${true}" var="day" name="rendered" tokens="first,1,second,2,third,3,fourth,4,fifth,5,sixth,6,seventh,7">${day}</w:selectTokens> +</div> + +test selected=2 <br> +<w:selectTokens var="day" name="selected.2" tokens="first,1,second,2,third,3,fourth,4,fifth,5,sixth,6,seventh,7" selected="second">${day}</w:selectTokens> +<br> +<br> + +w:select type="combo": <br> +<w:selectTokens var="day" name="combo" tokens="first,1,second,2,third,3,fourth,4,fifth,5,sixth,6,seventh,7" selected="third">${day}</w:selectTokens> + +<br> +<br> + +w:selectTokens type="radio": <br> +<w:selectTokens type="radio" var="day" name="radio" tokens="first,1,second,2,third,3,fourth,4,fifth,5,sixth,6,seventh,7" >${day}</w:selectTokens> + +</body > +</html>
Copied: trunk/extensions/taglib-acceptance/src/test/java/org/codehaus/waffle/taglib/acceptance/SelectTokensTest.java (from rev 159, trunk/extensions/taglib-acceptance/src/test/java/org/codehaus/waffle/taglib/acceptance/SelectTest.java) (0 => 163)
--- trunk/extensions/taglib-acceptance/src/test/java/org/codehaus/waffle/taglib/acceptance/SelectTokensTest.java (rev 0) +++ trunk/extensions/taglib-acceptance/src/test/java/org/codehaus/waffle/taglib/acceptance/SelectTokensTest.java 2007-06-19 16:55:32 UTC (rev 163) @@ -0,0 +1,17 @@ +package org.codehaus.waffle.taglib.acceptance; + +public class SelectTokensTest extends IntegrationTest { + + public void testAllowsTheUserToSpecifyTheSelectedValue() { + open("selectTokens.jsp"); + assertEquals("second", selenium.getSelectedValue("selected.2")); + } + + public void testHonorsRenderAttribute() { + open("selectTokens.jsp"); + verifyTrue(!selenium.isElementPresent("notRendered")); + verifyTrue(selenium.isElementPresent("rendered")); + checkForVerificationErrors(); + } + +} \ No newline at end of file
To unsubscribe from this list please visit:
