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 [EMAIL PROTECTED] 
IExternalPage} to be selected.
      * Associated with a [EMAIL PROTECTED] 
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 [EMAIL PROTECTED] 
org.apache.tapestry.request.IRequestDecoder}.
-     * 
+     *
      * @since 2.2
      */
 
@@ -164,7 +155,7 @@
      * extension must implement [EMAIL PROTECTED] 
org.apache.tapestry.multipart.IMultipartDecoder} (and is
      * generally a configured instance of
      * [EMAIL PROTECTED] IMultipartDecoder}).
-     * 
+     *
      * @since 3.0
      */
 
@@ -172,7 +163,7 @@
 
     /**
      * Method id used to check that [EMAIL PROTECTED] 
IPage#validate(IRequestCycle)} is invoked.
-     * 
+     *
      * @see #checkMethodInvocation(Object, String, Object)
      * @since 3.0
      */
@@ -181,7 +172,7 @@
 
     /**
      * Method id used to check that [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 
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 [EMAIL PROTECTED] 
MessageFormat#format(java.lang.String, java.lang.Object[])}.
-     * 
+     *
      * @since 1.0.8
      */
 
@@ -378,7 +369,7 @@
 
     /**
      * Convienience method for invoking [EMAIL PROTECTED] #format(String, 
Object[])}.
-     * 
+     *
      * @since 3.0
      */
 
@@ -389,38 +380,38 @@
 
     /**
      * Convienience method for invoking [EMAIL PROTECTED] #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 [EMAIL PROTECTED] #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 [EMAIL PROTECTED] #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
      * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 
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 [EMAIL PROTECTED] 
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();


Reply via email to