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 2008/01/13 23:54:39 UTC

svn commit: r611668 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry/internal/ main/resources/org/apache/tapestry/ site/apt/guide/ test/java/org/apache/tapestry/integration/

Author: hlship
Date: Sun Jan 13 14:54:37 2008
New Revision: 611668

URL: http://svn.apache.org/viewvc?rev=611668&view=rev
Log:
TAPESTRY-2008: Validation popup bubbles are somewhat distracting, should be simplified

Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultValidationDecorator.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/site/apt/guide/ajax.apt
    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/internal/DefaultValidationDecorator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultValidationDecorator.java?rev=611668&r1=611667&r2=611668&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultValidationDecorator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultValidationDecorator.java Sun Jan 13 14:54:37 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -34,12 +34,12 @@
 
     /**
      * @param environment        used to locate objects and services during the render
-     * @param validationMessages obtained from {@link org.apache.tapestry.services.ValidationMessagesSource}, used to obtain the label for the
-     *                           icon
+     * @param validationMessages obtained from {@link org.apache.tapestry.services.ValidationMessagesSource}, used to
+     *                           obtain the label for the icon
      * @param iconAsset          asset for an icon that will be displayed after each field (marked with the
      * @param markupWriter
      */
-    public DefaultValidationDecorator(final Environment environment, Messages validationMessages, Asset iconAsset,
+    public DefaultValidationDecorator(Environment environment, Messages validationMessages, Asset iconAsset,
                                       MarkupWriter markupWriter)
     {
         _environment = environment;

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=611668&r1=611667&r2=611668&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 Sun Jan 13 14:54:37 2008
@@ -338,7 +338,7 @@
     font-weight: bold;
 }
 
-DIV.t-error-bevel SPAN {
+DIV.t-error-popup SPAN {
     background: transparent url( 'error-bevel-left.png' ) no-repeat;
     display: block;
     line-height: 28px;
@@ -346,7 +346,7 @@
     padding: 0px 5px 10px 22px;
 }
 
-DIV.t-error-bevel {
+DIV.t-error-popup {
     background: transparent url( 'error-bevel-right.png' ) no-repeat scroll top right;
     cursor: pointer;
     color: #FFF;

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=611668&r1=611667&r2=611668&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 Sun Jan 13 14:54:37 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -20,6 +20,12 @@
 
     Zone : Class.create(),
 
+    ErrorPopup : Class.create(),
+
+    // An array of ErrorPopup that have been created for fields within the page
+
+    errorPopups : [],
+
     // Adds a callback function that will be invoked when the DOM is loaded (which
     // occurs *before* window.onload, which has to wait for images and such to load
     // first.  This simply observes the dom:loaded event on the document object (support for
@@ -274,6 +280,124 @@
     }
 };
 
+Tapestry.ErrorPopup.prototype = {
+    initialize : function(field)
+    {
+        this.field = $(field);
+
+        this.innerSpan = new Element("span");
+        this.outerDiv = $(new Element("div", { 'class' : 't-error-popup' })).update(this.innerSpan).hide();
+
+        this.field.insert({ after : this.outerDiv });
+
+        this.outerDiv.absolutize();
+
+        this.outerDiv.observe("click", function(event)
+        {
+            this.stopAnimation();
+
+            this.outerDiv.hide();
+
+            event.stop();
+        });
+
+        Tapestry.errorPopups.push(this);
+
+        this.state = "hidden";
+
+        this.queue = { position: 'end', scope: this.field.id };
+
+        Event.observe(window, "resize", this.repositionBubble.bind(this));
+    },
+
+    showMessage : function(message)
+    {
+        this.stopAnimation();
+
+        this.innerSpan.update(message);
+
+        this.hasMessage = true;
+
+        this.fadeIn();
+
+    },
+
+    repositionBubble : function()
+    {
+        var fieldPos = this.field.positionedOffset();
+
+        this.outerDiv.setStyle({ top: fieldPos[1] - 34 + "px", left: fieldPos[0] - 5 + "px", width: "auto", height: "39px" });
+    },
+
+    fadeIn : function()
+    {
+        this.repositionBubble();
+
+        if (this.state == "hidden")
+        {
+            this.state = "visible";
+
+            this.animation = new Effect.Appear(this.outerDiv, { afterFinish : this.afterFadeIn.bind(this), queue: this.queue });
+        }
+    },
+
+    stopAnimation : function()
+    {
+        if (this.animation) this.animation.cancel();
+
+        this.animation = null;
+    },
+
+    fadeOut : function ()
+    {
+        this.stopAnimation();
+
+        if (this.state == "visible")
+        {
+            this.state = "hidden";
+
+            this.animation = new Effect.Fade(this.outerDiv, { queue : this.queue });
+        }
+    },
+
+    hide : function()
+    {
+        this.hasMessage = false;
+
+        this.stopAnimation();
+
+        this.outerDiv.hide();
+
+        this.state = "hidden";
+    },
+
+    afterFadeIn : function()
+    {
+        this.animation = null;
+
+        if (this.field != Tapestry.focusedElement) this.fadeOut();
+    },
+
+    handleFocusChange : function(element)
+    {
+        if (element == this.field)
+        {
+            if (this.hasMessage) this.fadeIn();
+            return;
+        }
+
+        if (this.animation == null)
+        {
+            this.fadeOut();
+            return;
+        }
+
+        // Must be fading in, let it finish, then fade it back out.
+
+        this.animation = new Effect.Fade(this.outerDiv, { queue : this.queue });
+    }
+};
+
 Tapestry.FieldEventManager.prototype = {
 
     initialize : function(field)
@@ -322,8 +446,8 @@
         if (this.icon)
             this.icon.hide();
 
-        if (this.popup)
-            this.popup.hide();
+        if (this.errorPopup)
+            this.errorPopup.hide();
     },
 
     // Adds decorations to the field (including label and icon if present).
@@ -343,46 +467,10 @@
                 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(event)
-            {
-                this.popup.hide();
-
-                event.stop();
-            }.bindAsEventListener(this));
-        }
+        if (this.errorPopup == undefined)
+            this.errorPopup = new Tapestry.ErrorPopup(this.field);
 
-        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] - 5 + "px", width: "auto", height: "39px" });
-
-            this.popup.fadingIn = true;
-
-            new Effect.Appear(this.popup, { afterFinish: function()
-            {
-                this.popup.fadingIn = false;
-            }.bindAsEventListener(this) });
-        }
+        this.errorPopup.showMessage(message);
     },
 
 
@@ -495,23 +583,18 @@
         element.removeClassName("t-invisible");
     });
 
-   // Adds a focus observer that fades all error popups except for the
+    // 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;
+            Tapestry.focusedElement = element;
 
-                var opacity = popup.field == element ? 1 : .15;
-
-                new Effect.Opacity(popup, { to: opacity });
+            $(Tapestry.errorPopups).each(function(popup)
+            {
+                popup.handleFocusChange(element);
             });
         });
     });

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt?rev=611668&r1=611667&r2=611668&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt Sun Jan 13 14:54:37 2008
@@ -141,7 +141,7 @@
   The previous example could be re-written as:
 
 +---+
-@InjectJavaScriptLibrary("${tapestry.scriptaculous}/dragdrop.js")
+@IncludeJavaScriptLibrary("${tapestry.scriptaculous}/dragdrop.js")
 public class MyComponent
 {
  . . .

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=611668&r1=611667&r2=611668&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 Sun Jan 13 14:54:37 2008
@@ -27,8 +27,8 @@
 import java.net.URL;
 
 /**
- * Note: If these tests fail with BindException when starting Jetty, it could be Skype. At least on
- * my system, Skype is listening on localhost:80.
+ * Note: If these tests fail with BindException when starting Jetty, it could be Skype. At least on my system, Skype is
+ * listening on localhost:80.
  */
 @Test(timeOut = 50000, sequential = true, groups = {"integration"})
 public class IntegrationTests extends AbstractIntegrationTestSuite
@@ -159,9 +159,8 @@
     }
 
     /**
-     * {@link InjectContainerWorker} is largely tested by the forms tests ({@link RenderDisabled}
-     * is built on it). test is for the failure case, where a mixin class is used with the wrong
-     * type of component.
+     * {@link InjectContainerWorker} is largely tested by the forms tests ({@link RenderDisabled} is built on it). test
+     * is for the failure case, where a mixin class is used with the wrong type of component.
      */
     @Test
     public void inject_container_failure() throws Exception
@@ -381,8 +380,8 @@
     }
 
     /**
-     * Tests for forms and form submissions and basic form control components. also tests a few
-     * other things, such as computed default bindings and invisible instrumentation.
+     * Tests for forms and form submissions and basic form control components. also tests a few other things, such as
+     * computed default bindings and invisible instrumentation.
      */
     @Test
     public void simple_form()
@@ -518,8 +517,8 @@
     }
 
     /**
-     * Tests the bean editor. Along the way, tests a bunch about validation, loops, blocks, and
-     * application state objects.
+     * Tests the bean editor. Along the way, tests a bunch about validation, loops, blocks, and application state
+     * objects.
      */
     @Test
     public void bean_editor()
@@ -800,7 +799,7 @@
         click(SUBMIT);
 
         // 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."
+        assertTextSeries("//div[@class='t-error-popup'][%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."
         );
@@ -1125,8 +1124,8 @@
     }
 
     /**
-     * This can test some output and parsing capability of the DateField component, but not the
-     * interesting client-side behavior.
+     * This can test some output and parsing capability of the DateField component, but not the interesting client-side
+     * behavior.
      */
     @Test
     public void basic_datefield()