You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by jk...@apache.org on 2007/07/29 22:49:41 UTC
svn commit: r560813 - in /tapestry/tapestry4/trunk/tapestry-framework/src:
java/org/apache/tapestry/ java/org/apache/tapestry/enhance/
java/org/apache/tapestry/pageload/ java/org/apache/tapestry/util/io/
js/tapestry/ js/tapestry/form/ test/org/apache/t...
Author: jkuhnert
Date: Sun Jul 29 13:49:40 2007
New Revision: 560813
URL: http://svn.apache.org/viewvc?view=rev&rev=560813
Log:
-) Compacted form related js files in to a single file.
-) Minor performance enhancements for parameter property binding enhancements.
-) Minor code cleanup/styling.
Removed:
tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/form/
tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/form_compat.js
Modified:
tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/Tapestry.java
tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/ParameterPropertyWorker.java
tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/ComponentClassProviderContext.java
tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/NamespaceClassSearchComponentClassProvider.java
tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/util/io/SerializableAdaptor.java
tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/form.js
tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestParameterPropertyWorker.java
Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/Tapestry.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/Tapestry.java?view=diff&rev=560813&r1=560812&r2=560813
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/Tapestry.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/Tapestry.java Sun Jul 29 13:49:40 2007
@@ -14,20 +14,6 @@
package org.apache.tapestry;
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Properties;
-import java.util.ResourceBundle;
-import java.util.Set;
-
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.Location;
import org.apache.tapestry.event.ChangeObserver;
@@ -36,10 +22,15 @@
import org.apache.tapestry.spec.IComponentSpecification;
import org.apache.tapestry.util.StringSplitter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.*;
+
/**
* A placeholder for a number of (static) methods that don't belong elsewhere, as well as a global
* location for static constants.
- *
+ *
* @since 1.0.1
* @author Howard Lewis Ship
*/
@@ -62,12 +53,12 @@
/**
* Almost identical to the direct service, except specifically for handling
* browser level events.
- *
+ *
* @since 4.1
*/
-
+
public static final String DIRECT_EVENT_SERVICE = "directevent";
-
+
/**
* The name ("external") of a service that a allows {@link IExternalPage} to be selected.
* Associated with a {@link org.apache.tapestry.link.ExternalLink} component.
@@ -121,13 +112,13 @@
*/
public static final String RESET_SERVICE = "reset";
-
+
/**
* Property name used to get the extension used for templates. This may be set in the page or
* component specification, or in the page (or component's) immediate container (library or
* application specification). Unlike most properties, value isn't inherited all the way up the
* chain. The default template extension is "html".
- *
+ *
* @since 3.0
*/
@@ -144,7 +135,7 @@
/**
* Suffix appended to a parameter name to form the name of a property that stores the binding
* for the parameter.
- *
+ *
* @since 3.0
*/
@@ -153,7 +144,7 @@
/**
* Key used to obtain an extension from the application specification. The extension, if it
* exists, implements {@link org.apache.tapestry.request.IRequestDecoder}.
- *
+ *
* @since 2.2
*/
@@ -164,7 +155,7 @@
* extension must implement {@link org.apache.tapestry.multipart.IMultipartDecoder} (and is
* generally a configured instance of
* {@link IMultipartDecoder}).
- *
+ *
* @since 3.0
*/
@@ -172,7 +163,7 @@
/**
* Method id used to check that {@link IPage#validate(IRequestCycle)} is invoked.
- *
+ *
* @see #checkMethodInvocation(Object, String, Object)
* @since 3.0
*/
@@ -181,7 +172,7 @@
/**
* Method id used to check that {@link IPage#detach()} is invoked.
- *
+ *
* @see #checkMethodInvocation(Object, String, Object)
* @since 3.0
*/
@@ -192,7 +183,7 @@
* Regular expression defining a simple property name. Used by several different parsers. Simple
* property names match Java variable names; a leading letter (or underscore), followed by
* letters, numbers and underscores.
- *
+ *
* @since 3.0
*/
@@ -211,10 +202,10 @@
public static final String VERSION = readVersion();
private static final String UNKNOWN_VERSION = "Unknown";
-
+
/**
* Contains strings loaded from TapestryStrings.properties.
- *
+ *
* @since 1.0.8
*/
@@ -242,7 +233,7 @@
private static final ThreadLocal _invokedMethodIds = new ThreadLocal();
-
+
/**
* Prevent instantiation.
*/
@@ -337,7 +328,7 @@
/**
* Closes the stream (if not null), ignoring any {@link IOException}thrown.
- *
+ *
* @since 1.0.2
*/
@@ -359,7 +350,7 @@
/**
* Gets a string from the TapestryStrings resource bundle. The string in the bundle is treated
* as a pattern for {@link MessageFormat#format(java.lang.String, java.lang.Object[])}.
- *
+ *
* @since 1.0.8
*/
@@ -378,7 +369,7 @@
/**
* Convienience method for invoking {@link #format(String, Object[])}.
- *
+ *
* @since 3.0
*/
@@ -389,38 +380,38 @@
/**
* Convienience method for invoking {@link #format(String, Object[])}.
- *
+ *
* @since 3.0
*/
public static String format(String key, Object arg)
{
return format(key, new Object[]
- { arg });
+ { arg });
}
/**
* Convienience method for invoking {@link #format(String, Object[])}.
- *
+ *
* @since 3.0
*/
public static String format(String key, Object arg1, Object arg2)
{
return format(key, new Object[]
- { arg1, arg2 });
+ { arg1, arg2 });
}
/**
* Convienience method for invoking {@link #format(String, Object[])}.
- *
+ *
* @since 3.0
*/
public static String format(String key, Object arg1, Object arg2, Object arg3)
{
return format(key, new Object[]
- { arg1, arg2, arg3 });
+ { arg1, arg2, arg3 });
}
/**
@@ -453,7 +444,7 @@
/**
* Returns the size of a collection, or zero if the collection is null.
- *
+ *
* @since 2.2
*/
@@ -467,7 +458,7 @@
/**
* Returns the length of the array, or 0 if the array is null.
- *
+ *
* @since 2.2
*/
@@ -481,7 +472,7 @@
/**
* Returns true if the Map is null or empty.
- *
+ *
* @since 3.0
*/
@@ -492,7 +483,7 @@
/**
* Returns true if the Collection is null or empty.
- *
+ *
* @since 3.0
*/
@@ -508,7 +499,7 @@
* representation as an array will encode more efficiently (via
* {@link org.apache.tapestry.util.io.DataSqueezerImpl} than serializing the Map and its
* contents.
- *
+ *
* @return the array of keys and values, or null if the input Map is null or empty
* @since 2.2
*/
@@ -537,7 +528,7 @@
/**
* Converts an even-sized array of objects back into a {@link Map}.
- *
+ *
* @see #convertMapToArray(Map)
* @return a Map, or null if the array is null or empty
* @since 2.2
@@ -564,10 +555,10 @@
return result;
}
-
+
/**
* Creates an exception indicating the binding value is null.
- *
+ *
* @since 3.0
*/
@@ -579,35 +570,34 @@
/** @since 3.0 * */
public static ApplicationRuntimeException createNoSuchComponentException(IComponent component,
- String id, Location location)
+ String id, Location location)
{
- return new ApplicationRuntimeException(format("no-such-component", component
- .getExtendedId(), id), component, location, null);
+ return new ApplicationRuntimeException(format("no-such-component", component.getExtendedId(), id),
+ component, location, null);
}
/** @since 3.0 * */
public static BindingException createRequiredParameterException(IComponent component,
- String parameterName)
+ String parameterName)
{
- return new BindingException(format("required-parameter", parameterName, component
- .getExtendedId()), component, null, component.getBinding(parameterName), null);
+ return new BindingException(format("required-parameter", parameterName, component.getExtendedId()),
+ component, null, component.getBinding(parameterName), null);
}
/** @since 3.0 * */
public static ApplicationRuntimeException createRenderOnlyPropertyException(
- IComponent component, String propertyName)
+ IComponent component, String propertyName)
{
- return new ApplicationRuntimeException(format(
- "render-only-property",
- propertyName,
- component.getExtendedId()), component, null, null);
+ return new ApplicationRuntimeException(format("render-only-property",
+ propertyName,
+ component.getExtendedId()), component, null, null);
}
/**
* Clears the list of method invocations.
- *
+ *
* @see #checkMethodInvocation(Object, String, Object)
* @since 3.0
*/
@@ -620,7 +610,7 @@
/**
* Adds a method invocation to the list of invocations. This is done in a super-class
* implementations.
- *
+ *
* @see #checkMethodInvocation(Object, String, Object)
* @since 3.0
*/
@@ -648,7 +638,7 @@
* the super-class implementation was invoked.
* <p>
* The list of method invocations is stored in a {@link ThreadLocal} variable.
- *
+ *
* @since 3.0
*/
@@ -659,15 +649,14 @@
if (methodIds != null && methodIds.contains(methodId))
return;
- throw new ApplicationRuntimeException(Tapestry.format(
- "Tapestry.missing-method-invocation",
- object.getClass().getName(),
- methodName));
+ throw new ApplicationRuntimeException(Tapestry.format("Tapestry.missing-method-invocation",
+ object.getClass().getName(),
+ methodName));
}
/**
* Method used by pages and components to send notifications about property changes.
- *
+ *
* @param component
* the component containing the property
* @param propertyName
Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/ParameterPropertyWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/ParameterPropertyWorker.java?view=diff&rev=560813&r1=560812&r2=560813
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/ParameterPropertyWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/ParameterPropertyWorker.java Sun Jul 29 13:49:40 2007
@@ -155,12 +155,15 @@
body.begin();
String bindingFieldName = fieldName + "$Binding";
+ String bindingCheckedName = bindingFieldName + "Checked";
op.addField(bindingFieldName, IBinding.class);
+ op.addField(bindingCheckedName, Boolean.TYPE);
- body.addln("if ({0} == null)", bindingFieldName);
+ body.addln("if (!{0})", bindingCheckedName);
body.begin();
body.addln("{0} = getBinding(\"{1}\");", bindingFieldName, parameterName);
+ body.addln("{0} = true;", bindingCheckedName);
body.end();
body.addln("return {0};", bindingFieldName);
Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/ComponentClassProviderContext.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/ComponentClassProviderContext.java?view=diff&rev=560813&r1=560812&r2=560813
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/ComponentClassProviderContext.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/ComponentClassProviderContext.java Sun Jul 29 13:49:40 2007
@@ -32,8 +32,7 @@
private IComponentSpecification _specification;
- public ComponentClassProviderContext(String pageName,
- IComponentSpecification pageSpecification, INamespace namespace)
+ public ComponentClassProviderContext(String pageName, IComponentSpecification pageSpecification, INamespace namespace)
{
Defense.notNull(pageName, "pageName");
Defense.notNull(pageSpecification, "pageSpecification");
Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/NamespaceClassSearchComponentClassProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/NamespaceClassSearchComponentClassProvider.java?view=diff&rev=560813&r1=560812&r2=560813
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/NamespaceClassSearchComponentClassProvider.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/NamespaceClassSearchComponentClassProvider.java Sun Jul 29 13:49:40 2007
@@ -25,8 +25,7 @@
* @author Howard M. Lewis Ship
* @since 4.0
*/
-public class NamespaceClassSearchComponentClassProvider implements
- ComponentClassProvider
+public class NamespaceClassSearchComponentClassProvider implements ComponentClassProvider
{
/**
@@ -38,8 +37,7 @@
private ClassFinder _classFinder;
- public String provideComponentClassName(
- ComponentClassProviderContext context)
+ public String provideComponentClassName(ComponentClassProviderContext context)
{
INamespace namespace = context.getNamespace();
String packages = namespace.getPropertyValue(_packagesName);
Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/util/io/SerializableAdaptor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/util/io/SerializableAdaptor.java?view=diff&rev=560813&r1=560812&r2=560813
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/util/io/SerializableAdaptor.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/util/io/SerializableAdaptor.java Sun Jul 29 13:49:40 2007
@@ -14,22 +14,15 @@
package org.apache.tapestry.util.io;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
import org.apache.commons.codec.binary.Base64;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.ClassResolver;
import org.apache.tapestry.services.DataSqueezer;
+import java.io.*;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
/**
* The most complicated of the adaptors, this one takes an arbitrary serializable object, serializes
* it to binary (possibly compressing the stream along the way), and encodes it in a Base64
@@ -84,8 +77,7 @@
byte[] encoded = Base64.encodeBase64(byteArray);
- String prefix = Character.toString(useCompressed ? GZIP_BYTESTREAM_PREFIX
- : BYTESTREAM_PREFIX);
+ String prefix = Character.toString(useCompressed ? GZIP_BYTESTREAM_PREFIX : BYTESTREAM_PREFIX);
return prefix + new String(encoded);
}
Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/form.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/form.js?view=diff&rev=560813&r1=560812&r2=560813
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/form.js (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/form.js Sun Jul 29 13:49:40 2007
@@ -440,5 +440,372 @@
}
}
-dojo.require("tapestry.form.validation");
-dojo.require("tapestry.form_compat");
+dojo.provide("tapestry.form.validation");
+dojo.require("dojo.validate.check");
+dojo.require("dojo.html.style");
+
+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
+
+ dialogName:"tapestry:AlertDialog",
+
+ /**
+ * 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 (typeof form == "undefined") {return false;}
+ if (typeof props == "undefined") {return true;} // form exists but no profile? just submit I guess..
+ if (!props.validateForm) {return true;}
+
+ try {
+ this.clearValidationDecorations(form, props);
+
+ 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])) {
+ this.summarizeErrors(form, results, props.profiles[i]);
+ return false;
+ }
+ }
+ } catch (e) {
+ // since so many dynamic function calls may happen in here it's best that we
+ // catch all of them and log them or else peoples forms might still get submitted
+ // and they'd never be able to figure out what was wrong
+ dojo.log.exception("Error validating", e, true);
+ 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;
+ }
+
+ if (results.hasInvalid()) {
+ var invalid=results.getInvalid();
+ for (var i=0; i < invalid.length; i++) {
+ this.handleInvalidField(invalid[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){
+ field=dojo.byId(field);
+ if (dj_undef("type", field)) {return;}
+ 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){
+ field=dojo.byId(field);
+ if (dj_undef("type", field)) {return;}
+ dojo.html.removeClass(field, this.missingClass);
+
+ if (!dojo.html.hasClass(field, this.invalidClass)){
+ dojo.html.prependClass(field, this.invalidClass);
+ }
+ },
+
+ /**
+ * Clears out previous css classes set on fields
+ * in error.
+ */
+ clearValidationDecorations:function(form, props){
+
+ for (var i=0; i < props.profiles.length; i++) {
+
+ for (var fieldName in props.profiles[i]) {
+ if (dj_undef("type", form.elements[fieldName]) || typeof form.elements[fieldName].type == "undefined"
+ || form.elements[fieldName].type == "submit"
+ || form.elements[fieldName].type == "hidden") { continue; }
+
+ dojo.html.removeClass(form.elements[fieldName], this.missingClass);
+ dojo.html.removeClass(form.elements[fieldName], this.invalidClass);
+ }
+ }
+ },
+
+ /**
+ * Optionally allows an alert dialog/dhtml dialog/etc to
+ * be displayed to user to alert them to the invalid state
+ * of their form if validation errors have occurred.
+ *
+ * @param form The form being validated.
+ * @param results Returned value of dojo.validate.check(form, profile)
+ * @param profile Validation profile definition
+ */
+ summarizeErrors:function(form, results, profile){
+ var merrs=[];
+ var ierrs=[];
+ tapestry.form.currentFocus=null;
+
+ if (results.hasMissing()){
+ var fields=results.getMissing();
+ for (var i=0; i<fields.length; i++){
+ if(i==0 && !tapestry.form.currentFocus){
+ tapestry.form.currentFocus=fields[i];
+ }
+ if (profile[fields[i]] && profile[fields[i]]["required"]){
+ if (dojo.lang.isArray(profile[fields[i]]["required"])) {
+ for (var z=0; z < profile[fields[i]]["required"].length; z++)
+ merrs.push(profile[fields[i]]["required"][z]);
+ } else
+ merrs.push(profile[fields[i]]["required"]);
+ }
+ }
+ }
+ if (results.hasInvalid()){
+ var fields=results.getInvalid();
+ for (var i=0; i<fields.length; i++){
+ if(i==0 && !tapestry.form.currentFocus){
+ tapestry.form.currentFocus=fields[i];
+ }
+ if (profile[fields[i]] && profile[fields[i]]["constraints"]){
+ if (dojo.lang.isArray(profile[fields[i]]["constraints"])) {
+ for (var z=0; z < profile[fields[i]]["constraints"].length; z++)
+ ierrs.push(profile[fields[i]]["constraints"][z]);
+ } else
+ ierrs.push(profile[fields[i]]["constraints"]);
+ }
+ }
+ }
+
+ var msg="";
+ if (merrs.length > 0) {
+ msg+='<ul class="missingList">';
+ for (var i=0; i<merrs.length;i++) {
+ msg+="<li>"+merrs[i]+"</li>";
+ }
+ msg+="</ul>";
+ }
+ if (ierrs.length > 0) {
+ msg+='<ul class="invalidList">';
+ for (var i=0; i<ierrs.length;i++) {
+ msg+="<li>"+ierrs[i]+"</li>";
+ }
+ msg+="</ul>";
+ }
+
+ dojo.require("dojo.widget.*");
+ dojo.require("tapestry.widget.AlertDialog");
+
+ var ad=dojo.widget.byId("validationDialog");
+ if (ad) {
+ ad.setMessage(msg);
+ ad.show();
+ return;
+ }
+
+ var node=document.createElement("span");
+ document.body.appendChild(node);
+ var dialog=dojo.widget.createWidget(this.dialogName,
+ {
+ widgetId:"validationDialog",
+ message:msg
+ }, node);
+ dialog.show();
+ },
+
+ /**
+ * Validates that the input value matches the given
+ * regexp pattern.
+ *
+ * @param value The string value to be evaluated.
+ * @param pattern The regexp pattern used to match against value.
+ */
+ isValidPattern:function(value, pattern){
+ if (typeof value != "string" || typeof pattern != "string") { return false; }
+
+ var re = new RegExp(pattern);
+ return re.test(value);
+ },
+
+ isPalleteSelected:function(elem){
+ return elem.length > 0;
+ },
+
+ /**
+ * Validates that the input value is equal with the value of the given input control.
+ */
+ isEqual:function(value, other){
+ var otherValue = dojo.byId(other).value;
+ return value == otherValue;
+ },
+
+ /**
+ * Validates that the input value is not equal with the value of the given input control.
+ */
+ isNotEqual:function(value, other){
+ return !tapestry.form.validation.isEqual(value, other);
+ },
+
+ /**
+ * Checks that the value given is greater than or equal to the value of
+ * minString. Uses dojo.i18n.number.parse() to parse out the values using
+ * the locale settings configured for the current page.
+ */
+ greaterThanOrEqual:function(value, minString, flags){
+ flags.validate=false;
+ var min = dojo.i18n.number.parse(minString, null, flags);
+ var num = dojo.i18n.number.parse(value, null, flags);
+ if (Number.NaN == num) { return false; }
+
+ return num >= min;
+ },
+
+ /**
+ * Checks that the value given is less than or equal to the value of
+ * maxString. Uses dojo.i18n.number.parse() to parse out the values using
+ * the locale settings configured for the current page.
+ */
+ lessThanOrEqual:function(value, maxString, flags){
+ flags.validate=false;
+ var max = dojo.i18n.number.parse(maxString, null, flags);
+ var num = dojo.i18n.number.parse(value, null, flags);
+ if (Number.NaN == num) { return false; }
+
+ return num <= max;
+ }
+}
+
+dojo.provide("tapestry.form.datetime");
+dojo.require("dojo.date.format");
+dojo.require("dojo.validate.datetime");
+
+tapestry.form.datetime={
+
+ /**
+ * Checks if the specified value is a valid date, according to
+ * the flags passed in.
+ *
+ * @param value The string value of the date being validated.
+ * @param flags An object.
+ * flags.format A string format pattern that will be used to validate
+ * the incoming value via @link dojo.validate.isValidDate(value, format).
+ * flags.max A string date value representing the maximum date that can be selected.
+ * flags.min A string date value representing the minimum date that can be selected.
+ * @return Boolean. True if valid, false otherwise.
+ */
+ isValidDate:function(value, flags){
+ if(!value){return false;}
+
+ if (!flags){
+ dojo.raise("isValidDate: value and flags must be specified");
+ return;
+ }
+
+ // parse date value
+ var dateValue=null;
+ try {
+ dateValue = dojo.date.parse(value, flags);
+ } catch (e) {
+ dojo.log.exception("Error parsing input date.", e, true);
+ return false;
+ }
+
+ if(dateValue == null) { return false; }
+
+ // convert to format that is validatable
+ value=dojo.date.format(dateValue, flags);
+
+ // TODO: This is totally useless right now, doesn't even accept formats with string equivs
+ // See a better method http://www.mattkruse.com/javascript/date/source.html
+ // basic format validation
+ // if (!dojo.validate.isValidDate(value, flags.format))
+ // return false;
+
+ // max date
+ if (!dj_undef("max", flags)){
+ if (typeof flags.max == "string"){
+ flags.max=dojo.date.parse(flags.max, flags);
+ }
+ if (dojo.date.compare(dateValue, flags.max, dojo.date.compareTypes.DATE) > 0)
+ return false;
+ }
+
+ // min date
+ if (!dj_undef("min", flags)){
+ if (typeof flags.min == "string"){
+ flags.min=dojo.date.parse(flags.min, flags);
+ }
+ if (dojo.date.compare(dateValue, flags.min, dojo.date.compareTypes.DATE) < 0)
+ return false;
+ }
+
+ return true;
+ }
+
+}
Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestParameterPropertyWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestParameterPropertyWorker.java?view=diff&rev=560813&r1=560812&r2=560813
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestParameterPropertyWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/enhance/TestParameterPropertyWorker.java Sun Jul 29 13:49:40 2007
@@ -131,29 +131,29 @@
public void test_Standard()
{
- IComponentSpecification spec = buildComponentSpecification("fred", buildParameterSpec(
- "fred",
- null,
- null));
+ IComponentSpecification spec =
+ buildComponentSpecification("fred", buildParameterSpec("fred", null, null));
EnhancementOperation op = newMock(EnhancementOperation.class);
expect(op.getPropertyType("fred")).andReturn(String.class);
-
op.claimProperty("fred");
String bindingFieldName = "_$fred$Binding";
+ String bindingChecked = bindingFieldName + "Checked";
op.addField("_$fred", String.class);
op.addField("_$fred$Default", String.class);
op.addField("_$fred$Cached", boolean.class);
- op.addField("_$fred$Binding", IBinding.class);
+ op.addField(bindingFieldName, IBinding.class);
+ op.addField(bindingChecked, Boolean.TYPE);
BodyBuilder builder = new BodyBuilder();
builder.begin();
- builder.addln("if ({0} == null)", bindingFieldName);
+ builder.addln("if (!{0})", bindingChecked);
builder.begin();
builder.addln("{0} = getBinding(\"{1}\");", bindingFieldName, "fred");
+ builder.addln("{0} = true;", bindingChecked);
builder.end();
builder.addln("return {0};", bindingFieldName);
builder.end();
@@ -195,8 +195,7 @@
builder.end();
builder.addln("if (get_$fred$Binding() == null)");
- builder
- .addln(" throw new org.apache.hivemind.ApplicationRuntimeException(\"Parameter 'fred' is not bound and can not be updated.\");");
+ builder.addln(" throw new org.apache.hivemind.ApplicationRuntimeException(\"Parameter 'fred' is not bound and can not be updated.\");");
builder.addln("get_$fred$Binding().setObject(($w) $1);");
@@ -249,17 +248,20 @@
op.claimProperty("fred");
String bindingFieldName = "_$fred$Binding";
+ String bindingChecked = bindingFieldName + "Checked";
op.addField("_$fred", String.class);
op.addField("_$fred$Default", String.class);
op.addField("_$fred$Cached", boolean.class);
- op.addField("_$fred$Binding", IBinding.class);
+ op.addField(bindingFieldName, IBinding.class);
+ op.addField(bindingChecked, Boolean.TYPE);
BodyBuilder builder = new BodyBuilder();
builder.begin();
- builder.addln("if ({0} == null)", bindingFieldName);
+ builder.addln("if (!{0})", bindingChecked);
builder.begin();
builder.addln("{0} = getBinding(\"{1}\");", bindingFieldName, "myparam");
+ builder.addln("{0} = true;", bindingChecked);
builder.end();
builder.addln("return {0};", bindingFieldName);
builder.end();