Revision: 320
Author: tfenne
Date: 2006-06-18 07:07:13 -0700 (Sun, 18 Jun 2006)
ViewCVS: http://svn.sourceforge.net/stripes/?rev=320&view=rev
Log Message:
-----------
Fix for STS-154: add a focus attribute to the form tag.
Modified Paths:
--------------
trunk/examples/web/bugzooky/AddEditBug.jsp
trunk/examples/web/bugzooky/BulkAddEditBugs.jsp
trunk/examples/web/bugzooky/Login.jsp
trunk/examples/web/bugzooky/Register.jsp
trunk/examples/web/bugzooky/Register2.jsp
trunk/stripes/resources/stripes.tld
trunk/stripes/src/net/sourceforge/stripes/tag/FormTag.java
trunk/stripes/src/net/sourceforge/stripes/tag/InputTagSupport.java
Modified: trunk/examples/web/bugzooky/AddEditBug.jsp
===================================================================
--- trunk/examples/web/bugzooky/AddEditBug.jsp 2006-06-12 11:03:05 UTC (rev
319)
+++ trunk/examples/web/bugzooky/AddEditBug.jsp 2006-06-18 14:07:13 UTC (rev
320)
@@ -12,7 +12,7 @@
<stripes:errors/>
- <stripes:form action="/examples/bugzooky/SingleBug.action">
+ <stripes:form action="/examples/bugzooky/SingleBug.action"
focus="bug.shortDescription">
<table class="leftRightForm">
<tr>
<th>Bug ID:</th>
Modified: trunk/examples/web/bugzooky/BulkAddEditBugs.jsp
===================================================================
--- trunk/examples/web/bugzooky/BulkAddEditBugs.jsp 2006-06-12 11:03:05 UTC
(rev 319)
+++ trunk/examples/web/bugzooky/BulkAddEditBugs.jsp 2006-06-18 14:07:13 UTC
(rev 320)
@@ -9,7 +9,7 @@
<jsp:useBean id="personManager" scope="page"
class="net.sourceforge.stripes.examples.bugzooky.biz.PersonManager"/>
- <stripes:form action="/examples/bugzooky/MultiBug.action">
+ <stripes:form action="/examples/bugzooky/MultiBug.action" focus="">
<stripes:errors/>
<table class="display">
Modified: trunk/examples/web/bugzooky/Login.jsp
===================================================================
--- trunk/examples/web/bugzooky/Login.jsp 2006-06-12 11:03:05 UTC (rev
319)
+++ trunk/examples/web/bugzooky/Login.jsp 2006-06-18 14:07:13 UTC (rev
320)
@@ -10,7 +10,7 @@
<!-- Somewhat contrived example of using the errors tag
'action' attribute. -->
<stripes:errors action="/examples/bugzooky/Login.action"/>
- <stripes:form action="/examples/bugzooky/Login.action">
+ <stripes:form action="/examples/bugzooky/Login.action"
focus="">
<table>
<tr>
<td style="font-weight: bold;"><stripes:label
for="username"/>:</td>
Modified: trunk/examples/web/bugzooky/Register.jsp
===================================================================
--- trunk/examples/web/bugzooky/Register.jsp 2006-06-12 11:03:05 UTC (rev
319)
+++ trunk/examples/web/bugzooky/Register.jsp 2006-06-18 14:07:13 UTC (rev
320)
@@ -7,7 +7,7 @@
<stripes:errors globalErrorsOnly="true"/>
- <stripes:form action="/examples/bugzooky/Register.action"
method="POST">
+ <stripes:form action="/examples/bugzooky/Register.action"
focus="first">
<p>Please provide the following information:</p>
<table class="leftRightForm">
Modified: trunk/examples/web/bugzooky/Register2.jsp
===================================================================
--- trunk/examples/web/bugzooky/Register2.jsp 2006-06-12 11:03:05 UTC (rev
319)
+++ trunk/examples/web/bugzooky/Register2.jsp 2006-06-18 14:07:13 UTC (rev
320)
@@ -5,7 +5,7 @@
<stripes:layout-render name="/bugzooky/layout/standard.jsp" title="Register">
<stripes:layout-component name="contents">
- <stripes:form action="/examples/bugzooky/Register.action"
method="POST">
+ <stripes:form action="/examples/bugzooky/Register.action"
focus="user.password">
<stripes:errors/>
<p>Welcome ${actionBean.user.firstName}, please pick a
password:</p>
Modified: trunk/stripes/resources/stripes.tld
===================================================================
--- trunk/stripes/resources/stripes.tld 2006-06-12 11:03:05 UTC (rev 319)
+++ trunk/stripes/resources/stripes.tld 2006-06-18 14:07:13 UTC (rev 320)
@@ -412,6 +412,17 @@
<type>java.lang.Object</type>
</attribute>
<attribute>
+ <description>
+ The name of the form field that should receive focus when the
page is loaded. Two
+ special values are recognized, 'first' and the empty string;
these values cause
+ the form to set focus on the first element in the form. If
any value is set,
+ and the form has validation errors, the behaviour is altered
and the first field
+ with validation errors is focused instead.
+ </description>
+
<name>focus</name><required>false</required><rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ <attribute>
<description>A comma separated list of content types that it is
acceptable to submit through this form. (HTML Pass-through)</description>
<name>accept</name><required>false</required><rtexprvalue>true</rtexprvalue>
</attribute>
Modified: trunk/stripes/src/net/sourceforge/stripes/tag/FormTag.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/tag/FormTag.java 2006-06-12
11:03:05 UTC (rev 319)
+++ trunk/stripes/src/net/sourceforge/stripes/tag/FormTag.java 2006-06-18
14:07:13 UTC (rev 320)
@@ -22,6 +22,8 @@
import net.sourceforge.stripes.util.CryptoUtil;
import net.sourceforge.stripes.util.HtmlUtil;
import net.sourceforge.stripes.util.Log;
+import net.sourceforge.stripes.validation.ValidationErrors;
+import net.sourceforge.stripes.validation.ValidationError;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -33,6 +35,7 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.List;
/**
* <p>Form tag for use with the Stripes framework. Supports all of the HTML
attributes applicable
@@ -45,6 +48,10 @@
/** Log used to log error and debugging information for this class. */
private static Log log = Log.getInstance(FormTag.class);
+ /** Stores the field name (or magic values ''/'first') to set focus on. */
+ private String focus;
+ private boolean focusSet = false;
+
/** Stores the value of the action attribute before the context gets
appended. */
private String actionWithoutContext;
@@ -110,6 +117,12 @@
/** Corresponding getter for 'beanclass', will always return null. */
public Object getBeanclass() { return null; }
+ /** Sets the name of the field that should receive focus when the form is
rendered. */
+ public void setFocus(String focus) { this.focus = focus; }
+ /** Gets the name of the field that should receive focus when the form is
rendered. */
+ public String getFocus() { return focus; }
+
+
////////////////////////////////////////////////////////////
// Additional attributes specific to the form tag
////////////////////////////////////////////////////////////
@@ -201,8 +214,15 @@
writeCloseTag(getPageContext().getOut(), "form");
+ // Write out a warning if focus didn't find a field
+ if (this.focus != null && !this.focusSet) {
+ log.error("Form with action [", getAction(), "] has 'focus'
set to '", this.focus,
+ "', but did not find a field with matching name to
set focus on.");
+ }
+
// Clean up any state the container won't reset during tag pooling
this.fieldsPresent.clear();
+ this.focusSet = false;
}
catch (IOException ioe) {
throw new StripesJspException("IOException in
FormTag.doEndTag().", ioe);
@@ -323,9 +343,45 @@
*/
public void registerField(InputTagSupport tag) {
this.fieldsPresent.put(tag.getName(), tag.getClass());
+ setFocusOnFieldIfRequired(tag);
}
/**
+ * Checks to see if the field should receive focus either because it is
the named
+ * field for receiving focus, because it is the first field in the form
(and first
+ * field focus was specified), or because it is the first field in error.
+ *
+ * @param tag the input tag being registered with the form
+ */
+ protected void setFocusOnFieldIfRequired(InputTagSupport tag) {
+ // Decide whether or not this field should be focused
+ if (this.focus != null && !this.focusSet) {
+ ActionBean bean = getActionBean();
+ ValidationErrors errors = bean == null ? null :
bean.getContext().getValidationErrors();
+
+ // If there are validaiton errors, select the first field in error
+ if (errors != null && errors.size() > 0) {
+ List<ValidationError> fieldErrors = errors.get(tag.getName());
+ if (fieldErrors != null && fieldErrors.size() > 0) {
+ tag.setFocus(true);
+ this.focusSet = true;
+ }
+ }
+ // Else set the named field, or the first field if that's desired
+ else if (this.focus.equals(tag.getName())) {
+ tag.setFocus(true);
+ this.focusSet = true;
+ }
+ else if ("".equals(this.focus) ||
"first".equalsIgnoreCase(this.focus)) {
+ if ( !(tag instanceof InputHiddenTag) ) {
+ tag.setFocus(true);
+ this.focusSet = true;
+ }
+ }
+ }
+ }
+
+ /**
* Gets the set of all field names for which fields have been refered
withing the form up
* until the point of calling this method. If this is called during
doEndTag it will contain
* all field names, if it is called during the body of the tag it will
only contain the
Modified: trunk/stripes/src/net/sourceforge/stripes/tag/InputTagSupport.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/tag/InputTagSupport.java
2006-06-12 11:03:05 UTC (rev 319)
+++ trunk/stripes/src/net/sourceforge/stripes/tag/InputTagSupport.java
2006-06-18 14:07:13 UTC (rev 320)
@@ -25,10 +25,13 @@
import net.sourceforge.stripes.validation.BooleanTypeConverter;
import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspWriter;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
+import java.util.Random;
import java.lang.reflect.Method;
+import java.io.IOException;
/**
* Parent class for all input tags in stripes. Provides support methods for
retrieving all the
@@ -40,6 +43,7 @@
public abstract class InputTagSupport extends HtmlTagSupport {
private String formatType;
private String formatPattern;
+ private boolean focus;
/** A list of the errors related to this input tag instance */
protected List<ValidationError> fieldErrors;
@@ -221,7 +225,9 @@
* is null, then the empty string will be returned.
*/
protected String format(Object input) {
- if (input == null) return "";
+ if (input == null) {
+ return "";
+ }
FormatterFactory factory =
StripesFilter.getConfiguration().getFormatterFactory();
Formatter formatter = factory.getFormatter(input.getClass(),
@@ -323,8 +329,13 @@
this.errorRenderer.doAfterEndTag();
}
+ if (this.focus) {
+ makeFocused();
+ }
+
this.errorRenderer = null;
this.fieldErrors = null;
+ this.focus = false;
return result;
}
@@ -333,6 +344,34 @@
}
}
+ /**
+ * Informs the tag that it should render JavaScript to ensure that it is
focused
+ * when the page is loaded. If the tag does not have an 'id' attribute a
random
+ * one will be created and set so that the tag can be located easily.
+ *
+ * @param focus true if focus is desired, false otherwise
+ */
+ public void setFocus(boolean focus) {
+ this.focus = focus;
+
+ if ( getId() == null ) {
+ setId(String.valueOf( new Random().nextInt() ));
+ }
+ }
+
+ /** Writes out a JavaScript string to set focus on the field as it is
rendered. */
+ protected void makeFocused() throws JspException {
+ try {
+ JspWriter out = getPageContext().getOut();
+ out.write("<script type=\"text/javascript\"/>var
z=document.getElementById('");
+ out.write(getId());
+ out.write("'); z.focus(); z.select();</script>");
+ }
+ catch (IOException ioe) {
+ throw new StripesJspException("Could not write javascript focus
code to jsp writer.", ioe);
+ }
+ }
+
/** Abstract method implemented in child classes instead of doEndTag(). */
public abstract int doEndInputTag() throws JspException;
@@ -385,7 +424,6 @@
/** Gets the HTML attribute of the same name. */
public String getReadonly() { return get("readonly"); }
-
public void setName(String name) { set("name", name); }
public String getName() { return get("name"); }
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development