You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/11/30 01:44:21 UTC

svn commit: r599662 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry/corelib/components/ main/resources/org/apache/tapestry/ test/java/org/apache/tapestry/integration/

Author: hlship
Date: Thu Nov 29 16:44:19 2007
New Revision: 599662

URL: http://svn.apache.org/viewvc?rev=599662&view=rev
Log:
TAPESTRY-1942: Client side validation should be triggered when the user moves out of a field

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/vbevel.png   (with props)
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Errors.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Errors.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Errors.java?rev=599662&r1=599661&r2=599662&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Errors.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Errors.java Thu Nov 29 16:44:19 2007
@@ -20,15 +20,14 @@
 import org.apache.tapestry.annotations.Environmental;
 import org.apache.tapestry.annotations.Parameter;
 import org.apache.tapestry.corelib.internal.InternalMessages;
-import org.apache.tapestry.dom.Element;
 import org.apache.tapestry.services.FormSupport;
 
 import java.util.List;
 
 /**
- * Standard validation error presenter. Must be enclosed by a {@link Form} component. If errors are
+ * Standard validation error presenter. Must be enclosed by a {@link org.apache.tapestry.corelib.components.Form} component. If errors are
  * present, renders a div element around a banner message and around an unnumbered list of error
- * messages.
+ * messages.         Renders nothing if the {@link org.apache.tapestry.ValidationTracker} shows no errors.
  */
 public class Errors
 {
@@ -59,9 +58,9 @@
 
         if (_tracker == null) throw new RuntimeException(InternalMessages.encloseErrorsInForm());
 
-        Element div = writer.element("div", "class", _class, "id", _formSupport.getClientId() + ":errors");
+        if (!_tracker.getHasErrors()) return;
 
-        if (!_tracker.getHasErrors()) div.addClassName(TapestryConstants.INVISIBLE_CLASS);
+        writer.element("div", "class", _class);
 
         // Inner div for the banner text
         writer.element("div");

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css?rev=599662&r1=599661&r2=599662&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css Thu Nov 29 16:44:19 2007
@@ -336,4 +336,25 @@
 DIV.t-autocomplete-menu LI.selected {
     color: black;
     font-weight: bold;
+}
+
+DIV.t-error-bevel {
+    float: left;
+    margin: 0px;
+    padding: 0px;
+
+    cursor: pointer;
+    display: block;
+}
+
+DIV.t-error-bevel SPAN {
+    background: transparent url( 'vbevel.png' ) no-repeat scroll top left;
+    color: white;
+    display: block;
+    float: left;
+    font: normal 12px arial, sans-serif;
+    margin-left: 15px;
+    padding: 6px 30px 0px 15px;
+    height: 39px;
+    text-decoration: none;
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js?rev=599662&r1=599661&r2=599662&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js Thu Nov 29 16:44:19 2007
@@ -23,20 +23,6 @@
     registerForm : function(form, clientValidations)
     {
         form = $(form);
-
-        form.errorDiv = $(form.id + ':errors');
-
-        if (form.errorDiv)
-        {
-            form.errorList = form.errorDiv.getElementsBySelector("ul").first();
-
-            if (! form.errorList)
-            {
-                // create it now
-                form.errorList = document.createElement("ul");
-                form.errorDiv.appendChild(form.errorList);
-            }
-        }
     
     // This can probably be cleaned up with bind() ...
 
@@ -46,11 +32,6 @@
 
             form.firstError = true;
 
-            if (form.errorList)
-            {
-                form.errorList.innerHTML = "";
-            }
-
 	  // Locate elements that have an event manager (and therefore, validations)
             // and let those validations execute, which may result in calls to recordError().
 
@@ -65,21 +46,6 @@
                 }
             });
 
-	  // On a failure result, display the error div.
-
-            if (form.errorDiv)
-            {
-                if (event.result)
-                {
-                    if (form.errorDiv.visible())
-                        new Effect.BlindUp(form.errorDiv);
-                }
-                else if (! form.errorDiv.visible())
-                {
-                    new Effect.BlindDown(form.errorDiv);
-                }
-            }
-
             return event.result;
         };
 
@@ -97,9 +63,6 @@
 
             field.decorateForValidationError(event, message);
 
-            if (form.errorList)
-                new Insertion.Bottom(form.errorList, "<li>" + message + "</li>");
-
         };
 
         // And handle the validations
@@ -315,6 +278,15 @@
         var id = field.id;
         this.label = $(id + ':label');
         this.icon = $(id + ':icon');
+
+        this.field.observe("blur", function()
+        {
+            var event = new Tapestry.FormEvent(this.field.form);
+
+            event.field = this.field;
+
+            this.validateInput(event);
+        }.bindAsEventListener(this));
     },
 
     // Adds a validator.  acceptBlank is true if the validator should be invoked regardless of
@@ -340,6 +312,9 @@
 
         if (this.icon)
             this.icon.hide();
+
+        if (this.popup)
+            this.popup.hide();
     },
 
     // Adds decorations to the field (including label and icon if present).
@@ -348,7 +323,6 @@
 
     addDecorations : function(event, message)
     {
-
         this.field.addClassName("t-error");
 
         if (this.label)
@@ -360,6 +334,44 @@
                 new Effect.Appear(this.icon);
         }
 
+        if (this.popup == undefined)
+        {
+            this.popupSpan = new Element("span");
+
+            this.popup = $(new Element("div", { 'class' : 't-error-bevel' })).update(this.popupSpan).hide();
+
+            this.popup.absolutize();
+
+            this.popup.field = this.field;
+
+            // It has to go somewhere.
+
+            this.field.insert({ after: this.popup });
+
+            this.popup.absolutize();
+
+            this.popup.observe("click", function()
+            {
+                new Effect.Fade(this.popup);
+            }.bindAsEventListener(this));
+        }
+
+        this.popupSpan.update(message);
+
+        if (! this.popup.visible())
+        {
+            var fieldPos = this.field.positionedOffset();
+
+            // These magic numbers are based on the height of the bevel image.
+            this.popup.setStyle({ top: fieldPos[1] - 34 + "px", left: fieldPos[0] + "px", width: "auto", height: "39px" });
+
+            this.popup.fadingIn = true;
+
+            new Effect.Appear(this.popup, { afterFinish: function()
+            {
+                this.popup.fadingIn = false;
+            }.bindAsEventListener(this) });
+        }
     },
 
 
@@ -471,4 +483,26 @@
         element.hide();
         element.removeClassName("t-invisible");
     });
+
+   // Adds a focus observer that fades all error popups except for the
+    // field in question.
+
+    $$("INPUT", "SELECT", "TEXTAREA").each(function(element)
+    {
+        element.observe("focus", function()
+        {
+            $$("DIV.t-error-bevel").each(function(popup)
+            {
+                // This handles a case where the user tabs out of a field and it is currently fading in with an
+                // error message.  Leave it up unchanged.
+
+                if (popup.fadingIn) return;
+
+                var opacity = popup.field == element ? 1 : .15;
+
+                new Effect.Opacity(popup, { to: opacity });
+            });
+        });
+    });
 });
+

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/vbevel.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/vbevel.png?rev=599662&view=auto
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/vbevel.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=599662&r1=599661&r2=599662&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Thu Nov 29 16:44:19 2007
@@ -758,15 +758,16 @@
 
         click(SUBMIT);
 
-        assertTextSeries("//li[%d]", 1, "You must provide a value for First Name.", "Everyone has to have a last name!",
-                         "Year of Birth requires a value of at least 1900.");
+        // Looks like more weaknesses in Selenium, can only manage the first match not the others.
+        assertTextSeries("//div[@class='t-error-bevel'][%d]/span", 1, "You must provide a value for First Name."
+                         //, "Everyone has to have a last name!",
+                         //       "Year of Birth requires a value of at least 1900."
+        );
 
         type("firstName", "Howard");
         type("lastName", "Lewis Ship");
         type("birthYear", "1000");
         click(SUBMIT);
-
-        assertText("//li", "Year of Birth requires a value of at least 1900.");
 
         type("birthYear", "1966");
         click("citizen");