Author: hlship
Date: Mon Nov  3 10:36:07 2008
New Revision: 710122

URL: http://svn.apache.org/viewvc?rev=710122&view=rev
Log:
TAP5-25: Client-side validation is triggered onblur even when switching to a 
different form in the same page, or to a non-form element such as a link

Modified:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/BeanEditorDemo.tml
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BeanEditorDemo.java

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js?rev=710122&r1=710121&r2=710122&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
 Mon Nov  3 10:36:07 2008
@@ -45,7 +45,7 @@
      */
     FIELD_VALIDATE_EVENT : "tapestry:fieldvalidate",
 
-    /** Event, triggered on the document object, which identifies the current 
focus element. */
+    /** Event, triggered on the document object, which identifies the current 
focus input element. */
     FOCUS_CHANGE_EVENT : "tapestry:focuschange",
 
     /** When false, the default, the Tapestry.debug() function will be a 
no-op. */
@@ -97,7 +97,14 @@
             {
                 element.observe("focus", function()
                 {
-                    document.fire(Tapestry.FOCUS_CHANGE_EVENT, element);
+                    if (element != Tapestry.currentFocusField)
+                    {
+                        Tapestry.debug("Focus changed to #{id}", element);
+
+                        document.fire(Tapestry.FOCUS_CHANGE_EVENT, element);
+
+                        Tapestry.currentFocusField = element;
+                    }
                 });
 
                 t.observingFocusChange = true;
@@ -105,8 +112,8 @@
         });
 
         // When a submit element is clicked, record the name of the element
-        // on the associated form. This is necessary for some Ajax processing
-        // TAPESTRY-2324.
+        // on the associated form. This is necessary for some Ajax processing,
+        // see TAPESTRY-2324.
 
         $$("INPUT[type=submit]").each(function(element)
         {
@@ -949,16 +956,16 @@
                 return;
             }
 
-            var focused = event.memo;
-
-            if (focused == this.field)
+            if (event.memo == this.field)
             {
                 this.fadeIn();
+                return;
             }
-            else
-            {
-                this.fadeOut();
-            }
+
+            // If this field is not the focus field after a focus change, then 
it's bubble,
+            // if visible, should fade out. This covers tabbing from one form 
to another. 
+            this.fadeOut();
+
         }.bind(this));
     },
 
@@ -986,17 +993,27 @@
 
     fadeIn : function()
     {
+        Tapestry.debug("fadeIn: " + this.field.id);
+
         if (! this.hasMessage) return;
 
         this.repositionBubble();
 
-        if (this.status == "fadeIn") return;
-
-        if (this.outerDiv.visible()) return;
+        if (this.animation) return;
 
-        this.animation = new Effect.Appear(this.outerDiv, { queue: this.queue 
});
+        this.animation = new Effect.Appear(this.outerDiv, {
+            queue: this.queue,
+            afterFinish: function()
+            {
+                this.animation = null;
 
-        this.status = "fadeIn";
+                if (this.field != Tapestry.currentFocusField)
+                {
+                    Tapestry.debug("Field #{id} lost focus, fading bubble", 
this.field);
+                    this.fadeOut();
+                }
+            }.bind(this)
+        });
     },
 
     stopAnimation : function()
@@ -1004,18 +1021,19 @@
         if (this.animation) this.animation.cancel();
 
         this.animation = null;
-        this.status = null;
     },
 
     fadeOut : function ()
     {
-        // Tapestry.debug("fadeOut: " + this.field.id);
-
-        if (this.status == "fadeOut") return;
+        Tapestry.debug("fadeOut: " + this.field.id);
 
-        this.animation = new Effect.Fade(this.outerDiv, { queue : this.queue 
});
+        if (this.animation) return;
 
-        this.status = "fadeOut";
+        this.animation = new Effect.Fade(this.outerDiv, { queue : this.queue,
+            afterFinish: function()
+            {
+                this.animation = null;
+            }.bind(this) });
     },
 
     hide : function()
@@ -1122,9 +1140,18 @@
         this.label = $(id + ':label');
         this.icon = $(id + ':icon');
 
-        this.field.observe("blur", function()
+        document.observe(Tapestry.FOCUS_CHANGE_EVENT, function(event)
         {
-            this.validateInput(false);
+            // If changing focus *within the same form* then
+            // perform validation.  Note that Tapestry.currentFocusField does 
not change
+            // until after the FOCUS_CHANGE_EVENT notification.
+
+            if (Tapestry.currentFocusField == this.field &&
+                this.field.form == event.memo.form)
+            {
+                Tapestry.debug("Validating input for #{id} on focus change", 
this.field);
+                this.validateInput();
+            }
         }.bindAsEventListener(this));
     },
 

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/BeanEditorDemo.tml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/BeanEditorDemo.tml?rev=710122&r1=710121&r2=710122&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/BeanEditorDemo.tml 
(original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/BeanEditorDemo.tml Mon 
Nov  3 10:36:07 2008
@@ -1,14 +1,31 @@
 <t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
-  <h1>${pageTitle}</h1>
+    <h1>${pageTitle}</h1>
 
-  <form t:id="registrationData" submitlabel="Register">
+    <form t:id="registrationData" submitlabel="Register">
 
-    <t:parameter name="firstName">
-      <t:label for="firstName"/>
-      <input t:type="TextField" t:id="firstName" 
value="registrationData.firstName" size="40"/>
-      (First Name is Required) </t:parameter>
+        <t:parameter name="firstName">
+            <t:label for="firstName"/>
+            <input t:type="TextField" t:id="firstName" 
value="registrationData.firstName" size="40"/>
+            (First Name is Required)
+        </t:parameter>
 
-  </form>
+    </form>
 
-  <p>[<a t:type="ActionLink" t:id="clear">Clear Data</a>]</p>
+    <p>[<a t:type="ActionLink" t:id="clear">Clear Data</a>]
+    </p>
+
+    <h2>Second Form</h2>
+
+    <p>Used to test tabbing
+        <em>between</em>
+        forms.
+    </p>
+
+    <p>
+        <t:form t:id="search">
+            <t:label for="searchTerm"/>
+            <t:textfield t:id="searchTerm"/>
+            <input type="submit"/>
+        </t:form>
+    </p>
 </t:border>

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BeanEditorDemo.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BeanEditorDemo.java?rev=710122&r1=710121&r2=710122&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BeanEditorDemo.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BeanEditorDemo.java
 Mon Nov  3 10:36:07 2008
@@ -17,19 +17,24 @@
 import org.apache.tapestry5.annotations.ApplicationState;
 import org.apache.tapestry5.annotations.Component;
 import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.beaneditor.Validate;
 import org.apache.tapestry5.corelib.components.BeanEditForm;
 import org.apache.tapestry5.integration.app1.data.RegistrationData;
 
 public class BeanEditorDemo
 {
     @Component(id = "registrationData", parameters =
-            { "clientValidation=clientValidation" })
+            {"clientValidation=clientValidation"})
     private BeanEditForm form;
 
     @ApplicationState
     @Property
     private RegistrationData registrationData;
 
+    @Property
+    @Validate("required")
+    private String searchTerm;
+
     Object onSuccess()
     {
         return ViewRegistration.class;


Reply via email to