You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by jk...@apache.org on 2006/06/12 03:56:18 UTC
svn commit: r413562 - in /tapestry/tapestry4/trunk:
examples/TimeTracker/src/context/ examples/TimeTracker/src/context/css/
examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/
framework/src/java/org/apache/tapestry/ framework/src/java/o...
Author: jkuhnert
Date: Sun Jun 11 18:56:16 2006
New Revision: 413562
URL: http://svn.apache.org/viewvc?rev=413562&view=rev
Log:
A little validation.
Added:
tapestry/tapestry4/trunk/framework/src/js/tapestry/form/
tapestry/tapestry4/trunk/framework/src/js/tapestry/form/__package__.js (with props)
tapestry/tapestry4/trunk/framework/src/js/tapestry/form/validation.js (with props)
tapestry/tapestry4/trunk/framework/src/js/tests/test_form_validation.js (with props)
Modified:
tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html
tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/forms.css
tapestry/tapestry4/trunk/examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/FormBehavior.java
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.jwc
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/Form.java
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormComponentContributorContext.java
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormComponentContributorContextImpl.java
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupportImpl.java
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/PropertySelection.java
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/validator/BaseValidator.java
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/validator/Required.java
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/valid/ValidationConstants.java
tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/valid/ValidationDelegate.java
tapestry/tapestry4/trunk/framework/src/js/tapestry/__package__.js
tapestry/tapestry4/trunk/framework/src/js/tapestry/form.js
tapestry/tapestry4/trunk/framework/src/js/tapestry/test.js
tapestry/tapestry4/trunk/framework/src/js/tests/test_event.js
tapestry/tapestry4/trunk/framework/src/js/tests/test_form.js
tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/form/MockForm.java
Modified: tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/Home.html Sun Jun 11 18:56:16 2006
@@ -6,7 +6,7 @@
using them.
</p>
-<form jwcid="taskForm@Form" class="container">
+<form jwcid="taskForm@Form" class="container" clientValidationEnabled="true" >
<h3><span jwcid="@Insert" value="message:new.task"/></h3>
<fieldset>
<table width="90%" class="form" cellpadding="2" cellspacing="0" >
Modified: tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/forms.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/forms.css?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/forms.css (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/context/css/forms.css Sun Jun 11 18:56:16 2006
@@ -53,3 +53,12 @@
cursor: hand;
cursor: pointer;
}
+
+.fieldMissing {
+ background: #bedef4;
+}
+
+.fieldInvalid {
+ background: #ffaf7e;
+ font-weight: bold;
+}
\ No newline at end of file
Modified: tapestry/tapestry4/trunk/examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java (original)
+++ tapestry/tapestry4/trunk/examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java Sun Jun 11 18:56:16 2006
@@ -46,7 +46,8 @@
@Component(type = "Autocompleter", id = "projectChoose",
bindings = { "model=projectModel", "value=selectedProject",
- "displayName=message:choose.project", "filterOnChange=true"})
+ "displayName=message:choose.project", "filterOnChange=true",
+ "validators=validators:required"})
public abstract Autocompleter getProjectSelection();
@InjectObject("service:timetracker.dao.ProjectDao")
@@ -63,18 +64,21 @@
public abstract Date getDate();
@Component(type = "DropdownTimePicker", id = "startPicker",
- bindings = {"value=startTime", "displayName=message:task.start.time"})
+ bindings = {"value=startTime", "displayName=message:task.start.time",
+ "validators=validators:required"})
public abstract DropdownTimePicker getStartPicker();
public abstract Date getStartTime();
@Component(type = "DropdownTimePicker", id = "endPicker",
- bindings = {"value=endTime", "displayName=message:task.end.time"})
+ bindings = {"value=endTime", "displayName=message:task.end.time",
+ "validators=validators:required"})
public abstract DropdownTimePicker getEndPicker();
public abstract Date getEndTime();
@Component(type = "TextField", id = "descriptionField",
bindings = { "value=description",
- "displayName=message:task.description"})
+ "displayName=message:task.description",
+ "validators=validators:required"})
public abstract TextField getDescriptionField();
public abstract String getDescription();
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/FormBehavior.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/FormBehavior.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/FormBehavior.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/FormBehavior.java Sun Jun 11 18:56:16 2006
@@ -17,6 +17,7 @@
import org.apache.hivemind.Location;
import org.apache.tapestry.form.FormEventType;
import org.apache.tapestry.form.IFormComponent;
+import org.apache.tapestry.json.JSONObject;
/**
* Common interface extended by {@link org.apache.tapestry.IForm} and
@@ -161,4 +162,10 @@
void registerForFocus(IFormComponent field, int priority);
+ /**
+ * The javascript object profile being built by this context to validate/translate
+ * form values.
+ * @return {@link JSONObject} profile.
+ */
+ JSONObject getProfile();
}
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.jwc
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.jwc?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.jwc (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.jwc Sun Jun 11 18:56:16 2006
@@ -49,7 +49,7 @@
<parameter name="id" property="idParameter" default-value="id"/>
<reserved-parameter name="name"/>
-
+
<inject property="validatableFieldSupport" object="service:tapestry.form.ValidatableFieldSupport"/>
<inject property="directService" object="service:tapestry.services.Direct"/>
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/Form.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/Form.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/Form.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/Form.java Sun Jun 11 18:56:16 2006
@@ -30,6 +30,7 @@
import org.apache.tapestry.engine.DirectServiceParameter;
import org.apache.tapestry.engine.IEngineService;
import org.apache.tapestry.engine.ILink;
+import org.apache.tapestry.json.JSONObject;
import org.apache.tapestry.listener.ListenerInvoker;
import org.apache.tapestry.valid.IValidationDelegate;
import org.apache.tapestry.web.WebResponse;
@@ -64,7 +65,7 @@
private String _name;
private FormSupport _formSupport;
-
+
/**
* Renders informal parameters.
* @author hls
@@ -444,4 +445,11 @@
_formSupport.registerForFocus(field, priority);
}
+ /**
+ * {@inheritDoc}
+ */
+ public JSONObject getProfile()
+ {
+ return _formSupport.getProfile();
+ }
}
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormComponentContributorContext.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormComponentContributorContext.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormComponentContributorContext.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormComponentContributorContext.java Sun Jun 11 18:56:16 2006
@@ -14,6 +14,8 @@
package org.apache.tapestry.form;
+import org.apache.tapestry.json.JSONObject;
+
/**
* Object that provides support to objects that implement
* {@link org.apache.tapestry.form.FormComponentContributor}. For the moment, at least, this is all
@@ -55,4 +57,11 @@
*/
void registerForFocus(int priority);
+
+ /**
+ * The javascript object profile being built by this context to validate/translate
+ * form values. This is really just a delegate to {@link FormBehavior}.
+ * @return {@link JSONObject} profile.
+ */
+ JSONObject getProfile();
}
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormComponentContributorContextImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormComponentContributorContextImpl.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormComponentContributorContextImpl.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormComponentContributorContextImpl.java Sun Jun 11 18:56:16 2006
@@ -23,6 +23,7 @@
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.PageRenderSupport;
import org.apache.tapestry.TapestryUtils;
+import org.apache.tapestry.json.JSONObject;
/**
* Implementation of {@link org.apache.tapestry.form.FormComponentContributorContext}.
@@ -42,7 +43,7 @@
private final IForm _form;
private final String _formId;
-
+
/**
* Used only for testing.
*/
@@ -90,4 +91,8 @@
_form.registerForFocus(_field, priority);
}
+ public JSONObject getProfile()
+ {
+ return _form.getProfile();
+ }
}
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupportImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupportImpl.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupportImpl.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/FormSupportImpl.java Sun Jun 11 18:56:16 2006
@@ -40,6 +40,7 @@
import org.apache.tapestry.TapestryUtils;
import org.apache.tapestry.engine.ILink;
import org.apache.tapestry.event.BrowserEvent;
+import org.apache.tapestry.json.JSONObject;
import org.apache.tapestry.services.ServiceConstants;
import org.apache.tapestry.util.IdAllocator;
import org.apache.tapestry.valid.IValidationDelegate;
@@ -157,6 +158,8 @@
private final PageRenderSupport _pageRenderSupport;
+ private final JSONObject _profile;
+
public FormSupportImpl(IMarkupWriter writer, IRequestCycle cycle, IForm form)
{
Defense.notNull(writer, "writer");
@@ -172,6 +175,7 @@
_allocatedIdIndex = 0;
_pageRenderSupport = TapestryUtils.getOptionalPageRenderSupport(cycle);
+ _profile = new JSONObject();
}
/**
@@ -187,6 +191,7 @@
_writer = null;
_delegate = null;
_pageRenderSupport = null;
+ _profile = null;
}
/**
@@ -530,10 +535,16 @@
if (!_form.getFocus() || _cycle.getAttribute(FIELD_FOCUS_ATTRIBUTE) != null)
return;
-
- _pageRenderSupport.addInitializationScript("Tapestry.set_focus('" + fieldId + "');");
-
+
+ _pageRenderSupport.addInitializationScript(_form, "tapestry.form.focusField('" + fieldId + "');");
_cycle.setAttribute(FIELD_FOCUS_ATTRIBUTE, Boolean.TRUE);
+
+ // register the validation profile with client side form manager
+
+ if (_form.isClientValidationEnabled()) {
+ _pageRenderSupport.addInitializationScript(_form, "tapestry.form.registerProfile('" + formId + "',"
+ + _profile.toString() + ");");
+ }
}
/**
@@ -545,10 +556,10 @@
if (_pageRenderSupport == null)
return;
- _pageRenderSupport.addInitializationScript("dojo.require(\"tapestry.form\");");
- _pageRenderSupport.addInitializationScript("Tapestry.register_form('" + formId + "');");
+ _pageRenderSupport.addInitializationScript(_form, "dojo.require(\"tapestry.form\");"
+ + "tapestry.form.registerForm('" + formId + "');");
}
-
+
public String rewind()
{
_form.getDelegate().clear();
@@ -746,4 +757,11 @@
_delegate.registerForFocus(field, priority);
}
+ /**
+ * {@inheritDoc}
+ */
+ public JSONObject getProfile()
+ {
+ return _profile;
+ }
}
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/PropertySelection.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/PropertySelection.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/PropertySelection.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/PropertySelection.java Sun Jun 11 18:56:16 2006
@@ -43,7 +43,6 @@
*
* @author Howard Lewis Ship
* @author Paul Ferraro
- * @author Jesse Kuhnert
*/
public abstract class PropertySelection extends AbstractFormComponent
implements ValidatableField
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/validator/BaseValidator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/validator/BaseValidator.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/validator/BaseValidator.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/validator/BaseValidator.java Sun Jun 11 18:56:16 2006
@@ -19,6 +19,8 @@
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.form.FormComponentContributorContext;
import org.apache.tapestry.form.IFormComponent;
+import org.apache.tapestry.json.JSONArray;
+import org.apache.tapestry.json.JSONObject;
/**
* Abstract implementation of {@link org.apache.tapestry.form.validator.Validator}.
@@ -75,5 +77,43 @@
public boolean isRequired()
{
return false;
+ }
+
+ /**
+ * Utility method to store a field specific profile property which can later
+ * be used by client side validation.
+ *
+ * @param field
+ * The field to store the property for, will key off of {@link IFormComponent#getClientId()}.
+ * @param profile
+ * The profile for the form.
+ * @param key
+ * The property key to store.
+ * @param property
+ * The property to store.
+ */
+ public void setProfileProperty(IFormComponent field, JSONObject profile,
+ String key, Object property)
+ {
+ if (!profile.has(field.getClientId()))
+ profile.put(field.getClientId(), new JSONObject());
+
+ JSONObject fieldProps = profile.getJSONObject(field.getClientId());
+ fieldProps.put(key, property);
+ }
+
+ /**
+ * Utility used to append onto an existing property represented as an
+ * object array.
+ * @param profile
+ * @param key
+ * @param value
+ */
+ public void accumulateProperty(JSONObject profile, String key, Object value)
+ {
+ if (!profile.has(key))
+ profile.put(key, new JSONArray());
+
+ profile.accumulate(key, value);
}
}
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/validator/Required.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/validator/Required.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/validator/Required.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/form/validator/Required.java Sun Jun 11 18:56:16 2006
@@ -18,10 +18,10 @@
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IRequestCycle;
-import org.apache.tapestry.TapestryUtils;
import org.apache.tapestry.form.FormComponentContributorContext;
import org.apache.tapestry.form.IFormComponent;
import org.apache.tapestry.form.ValidationMessages;
+import org.apache.tapestry.json.JSONObject;
import org.apache.tapestry.multipart.UploadPart;
import org.apache.tapestry.valid.ValidationConstants;
import org.apache.tapestry.valid.ValidationConstraint;
@@ -71,19 +71,18 @@
new Object[]
{ field.getDisplayName() });
}
-
+
public void renderContribution(IMarkupWriter writer, IRequestCycle cycle,
FormComponentContributorContext context, IFormComponent field)
{
context.registerForFocus(ValidationConstants.REQUIRED_FIELD);
-
- StringBuffer buffer = new StringBuffer("function(event) { Tapestry.require_field(event, '");
- buffer.append(field.getClientId());
- buffer.append("', ");
- buffer.append(TapestryUtils.enquote(buildMessage(context, field)));
- buffer.append("); }");
-
- context.addSubmitHandler(buffer.toString());
+
+ JSONObject profile = context.getProfile();
+
+ accumulateProperty(profile, ValidationConstants.REQUIRED, field.getClientId());
+
+ setProfileProperty(field, profile,
+ ValidationConstants.REQUIRED, buildMessage(context, field));
}
/**
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/valid/ValidationConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/valid/ValidationConstants.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/valid/ValidationConstants.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/valid/ValidationConstants.java Sun Jun 11 18:56:16 2006
@@ -21,7 +21,7 @@
* @author Howard Lewis Ship
* @since 4.0
*/
-public class ValidationConstants
+public final class ValidationConstants
{
public static final int NORMAL_FIELD = 1;
@@ -29,4 +29,8 @@
public static final int REQUIRED_FIELD = 2;
public static final int ERROR_FIELD = 3;
+
+ public static final String REQUIRED = "required";
+
+ public static final String REQUIRED_MESSAGE = "required-message";
}
Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/valid/ValidationDelegate.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/valid/ValidationDelegate.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/valid/ValidationDelegate.java (original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/valid/ValidationDelegate.java Sun Jun 11 18:56:16 2006
@@ -28,7 +28,7 @@
import org.apache.tapestry.form.IFormComponent;
/**
- * A base implementation of {@link IValidationDelegate}that can be used as a
+ * A base implementation of {@link IValidationDelegate} that can be used as a
* managed bean. This class is often subclassed, typically to override
* presentation details.
*
Modified: tapestry/tapestry4/trunk/framework/src/js/tapestry/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/__package__.js?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/__package__.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/__package__.js Sun Jun 11 18:56:16 2006
@@ -2,6 +2,6 @@
common: [
"tapestry.core","tapestry.event"
],
- browser: ["tapestry.html","tapestry.form"]
+ browser: ["tapestry.html"]
});
dojo.provide("tapestry.*");
Modified: tapestry/tapestry4/trunk/framework/src/js/tapestry/form.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/form.js?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/form.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/form.js Sun Jun 11 18:56:16 2006
@@ -1,5 +1,8 @@
dojo.provide("tapestry.form");
+dojo.require("dojo.event");
+dojo.require("dojo.event.browser");
+
dojo.require("tapestry.core");
/**
@@ -9,6 +12,8 @@
*/
tapestry.form={
+ forms:{}, // registered form references
+
/**
* Generically displays a window alert for the
* given field when in error.
@@ -99,6 +104,11 @@
}
},
+ /**
+ * Registers the form with the local <code>forms</code> property so
+ * that there is a central reference of all tapestry forms.
+ * @param id The form(form id) to register.
+ */
registerForm:function(id){
var form=dojo.byId(id);
if (!form) {
@@ -106,7 +116,73 @@
return;
}
- dojo.log.warn("registerForm() not implemented yet.");
+ if (!this.forms[id]) {
+ this.forms[id]={};
+ this.forms[id].validateForm=true;
+ this.forms[id].profiles=[];
+
+ dojo.event.connect(form, "onsubmit", this, "onFormSubmit");
+ } else {
+ dojo.log.warn("registerForm(" + id + ") Form already registered.");
+ }
+ },
+
+ /**
+ * Registers a form validation/translation profile. There
+ * can potentially be more than one profile registered with
+ * a form.
+ *
+ * The profiles will be consulted at various points in the forms
+ * life, which currently only involves running the profile checks
+ * before form submission. (more points to be determined in the future)
+ *
+ * @see {@link dojo.validate.check(form, profile)}.
+ *
+ * @param id The form(form id) to register profile with.
+ * @param profile The object containing all of the validation/value
+ * constraints for the form.
+ */
+ registerProfile:function(id, profile){
+ if (!this.forms[id]) {
+ dojo.raise("registerProfile(" + id + ") No form previously registered with that id.");
+ return;
+ }
+
+ this.forms[id].profiles.push(profile);
+ },
+
+ /**
+ * If a form registered with the specified formId
+ * exists a local property will be set that causes
+ * validation to be turned on/off depending on the argument.
+ *
+ * @param formId The id of the form to turn validation on/off for.
+ * @param validate Boolean for whether or not to validate form, if
+ * not specified assumes true.
+ */
+ setFormValidating:function(formId, validate){
+ if (this.forms[id]){
+ this.forms[id].validateForm = validate ? true : false;
+ }
+ },
+
+ /**
+ * Event connected function that is invoked when a form
+ * is submitted.
+ */
+ onFormSubmit:function(evt){
+ if (!evt || !evt.target) {
+ dojo.raise("No target for form event." + evt);
+ return;
+ }
+
+ var id=evt.target.getAttribute("id");
+ if (!id) return;
+
+ if (!tapestry.form.validation.validateForm(evt.target, this.forms[id])) {
+ dojo.event.browser.stopEvent(evt);
+ dojo.log.info("Stopped form submission, invalid input.");
+ }
},
/**
@@ -165,4 +241,5 @@
}
}
+dojo.require("tapestry.form.validation");
dojo.require("tapestry.form_compat");
Added: tapestry/tapestry4/trunk/framework/src/js/tapestry/form/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/form/__package__.js?rev=413562&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/form/__package__.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/form/__package__.js Sun Jun 11 18:56:16 2006
@@ -0,0 +1,6 @@
+dojo.kwCompoundRequire({
+ browser: [
+ "tapestry.form.validation"
+ ]
+});
+dojo.provide("tapestry.form.*");
\ No newline at end of file
Propchange: tapestry/tapestry4/trunk/framework/src/js/tapestry/form/__package__.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/framework/src/js/tapestry/form/validation.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/form/validation.js?rev=413562&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/form/validation.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/form/validation.js Sun Jun 11 18:56:16 2006
@@ -0,0 +1,114 @@
+dojo.provide("tapestry.form.validation");
+
+dojo.require("dojo.validate.check");
+dojo.require("dojo.html");
+
+tapestry.form.validation={
+
+ missingClass:"fieldMissing", // default css class that will be applied to fields missing a value
+ invalidClass:"fieldInvalid", // default css class applied to fields with invalid data
+
+ /**
+ * Main entry point for running form validation. The
+ * props object passed in contains a number of fields that
+ * are managed by tapestry.form:
+ *
+ * props = {
+ * validateForm:[true|false] // whether to run validation at all
+ * profiles:[profile1, profile2] // set of dojo.validate.check() style profiles
+ * // that may have been registered with form
+ * }
+ *
+ * The individual profiles will contain any of the data described by the dojo documentation
+ * for dojo.validate.check(). In addition to that, each profile will also have a corresponding
+ * string message to display if the specified condition has been met. For example, if you have
+ * specified that a select field named "select1" was required your profile would look something
+ * like:
+ *
+ * profile = {
+ * "required":["select1"], // normal dojo.validate.check data
+ * "select1":{ // tapestry field/error type specific data
+ * "required":"You must select a value for select1."
+ * }
+ * }
+ *
+ * It is intended for you to call dojo.validate.check(form, profile) for each profile
+ * stored in the "profiles" field, as well as deciding how to display errors / warnings.
+ *
+ * @return Boolean indicating if form submission should continue. If false the form
+ * will ~not~ be submitted.
+ */
+ validateForm:function(form, props){
+ if (!form) return false;
+ if (!props) return true; // form exists but no profile? just submit I guess..
+ if (!props.validateForm) return true;
+
+ for (var i=0; i < props.profiles.length; i++) {
+ var results=dojo.validate.check(form, props.profiles[i]);
+
+ if (!this.processResults(form, results, props.profiles[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ /**
+ * Called for each registered profile on a form after
+ * dojo.validate.check() has been called. This function is
+ * expected to do UI related notifications of fields in error.
+ *
+ * @param form The form that was validated.
+ * @param results The result of calling dojo.validate.check(form,profile)
+ * @param profile The original profile used to validate form, also holds
+ * validation error messages to be used for each field.
+ *
+ * @return Boolean, if false form should not be submitted and all validation
+ * should be stopped. If true validation will continue and eventually
+ * form will be submitted.
+ */
+ processResults:function(form, results, profile){
+ if (results.isSuccessful()) return true;
+
+ var formValid=true;
+ if (results.hasMissing()) {
+ var missing=results.getMissing();
+ for (var i=0; i < missing.length; i++) {
+ this.handleMissingField(missing[i], profile);
+ }
+
+ formValid=false;
+ }
+
+ return formValid; // if got past successful everything is invalid
+ },
+
+ /**
+ * Default field decorator for missing fields.
+ *
+ * @param field The field element that was missing data.
+ * @param profile The form validation profile.
+ */
+ handleMissingField:function(field, profile){
+ dojo.html.removeClass(field, this.invalidClass);
+
+ if (!dojo.html.hasClass(field, this.missingClass)){
+ dojo.html.prependClass(field, this.missingClass);
+ }
+ },
+
+ /**
+ * Default field decorator for invalid fields.
+ *
+ * @param field The field element that had invalid data.
+ * @param profile The form validation profile.
+ */
+ handleInvalidField:function(field, profile){
+ dojo.html.removeClass(field, this.missingClass);
+
+ if (!dojo.html.hasClass(field, this.invalidClass)){
+ dojo.html.prependClass(field, this.invalidClass);
+ }
+ }
+}
\ No newline at end of file
Propchange: tapestry/tapestry4/trunk/framework/src/js/tapestry/form/validation.js
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tapestry/tapestry4/trunk/framework/src/js/tapestry/test.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/test.js?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tapestry/test.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/tapestry/test.js Sun Jun 11 18:56:16 2006
@@ -1,5 +1,8 @@
dojo.provide("tapestry.test");
+// override to make sure our fake events pass
+dojo.event.browser.isEvent=function() { return true; }
+
if (dj_undef("byId", dj_global)) {
dojo.byId = function(id, doc){
if(id && (typeof id == "string" || id instanceof String)){
Modified: tapestry/tapestry4/trunk/framework/src/js/tests/test_event.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tests/test_event.js?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tests/test_event.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/tests/test_event.js Sun Jun 11 18:56:16 2006
@@ -3,9 +3,6 @@
dojo.require("tapestry.*");
dojo.require("tapestry.test");
-// override to make sure our fake events pass
-dojo.event.browser.isEvent=function() { return true; }
-
function test_eventCapture_props(){
var fevent=document.createEvent('UIEvents');
fevent.type="testType";
Modified: tapestry/tapestry4/trunk/framework/src/js/tests/test_form.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tests/test_form.js?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tests/test_form.js (original)
+++ tapestry/tapestry4/trunk/framework/src/js/tests/test_form.js Sun Jun 11 18:56:16 2006
@@ -4,9 +4,6 @@
dojo.require("tapestry.test");
dojo.require("tapestry.form");
-// override to make sure our fake events pass
-dojo.event.browser.isEvent=function() { return true; }
-
tapestry.form.invalidField=function(field, message){
}
Added: tapestry/tapestry4/trunk/framework/src/js/tests/test_form_validation.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tests/test_form_validation.js?rev=413562&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/tests/test_form_validation.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/tests/test_form_validation.js Sun Jun 11 18:56:16 2006
@@ -0,0 +1,29 @@
+dojo.setModulePrefix("tapestry", "../tapestry");
+
+dojo.require("tapestry.*");
+dojo.require("tapestry.test");
+dojo.require("tapestry.form");
+dojo.require("dojo.lang.*");
+
+function test_register_invalidform(){
+ try {
+ tapestry.form.registerForm("bsid");
+ throw new JUMAssertFailure("Previous test should have failed.");
+ } catch (e) {
+ jum.assertTrue("testFormRegisterInvalid", e instanceof Error);
+ }
+}
+
+function test_register_form(){
+ var form = document.createElement("form");
+ form.setAttribute("id", "regform");
+ form.submit=function(){
+ form.submitCalled=true;
+ }
+ form.submitname={value:""};
+
+ tapestry.form.registerForm("regform");
+ jum.assertTrue("formregForm", dojo.lang.isObject(tapestry.form.forms["regform"]));
+ jum.assertTrue("formregProfiles", dojo.lang.isArray(tapestry.form.forms["regform"].profiles));
+ jum.assertEquals("formregProfileLength", 0, tapestry.form.forms["regform"].profiles.length);
+}
Propchange: tapestry/tapestry4/trunk/framework/src/js/tests/test_form_validation.js
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/form/MockForm.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/form/MockForm.java?rev=413562&r1=413561&r2=413562&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/form/MockForm.java (original)
+++ tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/form/MockForm.java Sun Jun 11 18:56:16 2006
@@ -33,6 +33,7 @@
import org.apache.tapestry.IRender;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.engine.IPageLoader;
+import org.apache.tapestry.json.JSONObject;
import org.apache.tapestry.listener.ListenerMap;
import org.apache.tapestry.services.impl.ComponentEventInvoker;
import org.apache.tapestry.spec.IComponentSpecification;
@@ -57,6 +58,8 @@
private boolean _focus = true;
+ private JSONObject _profile = new JSONObject();
+
public MockForm()
{
this(null, null);
@@ -368,5 +371,13 @@
*/
public void setEventInvoker(ComponentEventInvoker invoker)
{
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public JSONObject getProfile()
+ {
+ return _profile;
}
}