You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by dr...@apache.org on 2009/11/22 15:10:09 UTC

svn commit: r883081 - in /tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src: main/java/org/apache/tapestry5/ main/java/org/apache/tapestry5/corelib/components/ main/resources/org/apache/tapestry5/ test/app1/ test/java/org/apache/tapestry5/integ...

Author: drobiazko
Date: Sun Nov 22 14:10:08 2009
New Revision: 883081

URL: http://svn.apache.org/viewvc?rev=883081&view=rev
Log:
TAP5-138: Add Zone parameter to Select component

Added:
    tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/app1/SelectZoneDemo.tml
    tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java   (with props)
    tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java   (with props)
Modified:
    tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java
    tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java
    tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.xdoc
    tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
    tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
    tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java

Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java?rev=883081&r1=883080&r2=883081&view=diff
==============================================================================
--- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java (original)
+++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java Sun Nov 22 14:10:08 2009
@@ -149,4 +149,13 @@
      * @SINCE 5.1.0.4
      */
     public static final String PROVIDE_COMPLETIONS = "providecompletions";
+    
+    /**
+     * Event triggered by {@link org.apache.tapestry5.corelib.components.Select} component to inform its
+     * container that Select's value has changed.
+     *
+     * @since 5.2.0.0
+     */
+    public static final String VALUE_CHANGED = "valuechanged";
+    
 }

Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java?rev=883081&r1=883080&r2=883081&view=diff
==============================================================================
--- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java (original)
+++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java Sun Nov 22 14:10:08 2009
@@ -18,14 +18,22 @@
 import org.apache.tapestry5.annotations.*;
 import org.apache.tapestry5.corelib.base.AbstractField;
 import org.apache.tapestry5.corelib.data.BlankOption;
+import org.apache.tapestry5.corelib.internal.ComponentActionSink;
+import org.apache.tapestry5.corelib.internal.HiddenFieldPositioner;
 import org.apache.tapestry5.corelib.mixins.RenderDisabled;
 import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.internal.services.PageRenderQueue;
+import org.apache.tapestry5.internal.util.Holder;
 import org.apache.tapestry5.internal.util.SelectModelRenderer;
 import org.apache.tapestry5.ioc.Messages;
 import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.ioc.internal.util.IdAllocator;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.json.JSONArray;
+import org.apache.tapestry5.json.JSONObject;
 import org.apache.tapestry5.services.*;
 import org.apache.tapestry5.util.EnumSelectModel;
+import org.slf4j.Logger;
 
 import java.util.Locale;
 
@@ -39,9 +47,12 @@
  * can be overriden by binding the encoder parameter, or extended by contributing a {@link ValueEncoderFactory} into the
  * service's configuration.
  */
-@Events(EventConstants.VALIDATE)
+@Events({EventConstants.VALIDATE, EventConstants.VALUE_CHANGED + " when 'zone' parameter is bound"})
 public class Select extends AbstractField
 {
+    public static final String FORM_COMPONENTID_PARAMETER = "t:formcomponentid";
+    public static final String CHANGE_EVENT = "change";
+
     private class Renderer extends SelectModelRenderer
     {
 
@@ -116,9 +127,47 @@
      */
     @Parameter(required = true, principal = true, autoconnect = true)
     private Object value;
+    
+    /**
+     * Binding the zone parameter will cause any change of Select's value to be handled as an Ajax request that updates the
+     * indicated zone. The component will trigger the event {@link EventConstants#VALUE_CHANGED} to inform its
+     * container that Select's value has changed.
+     * 
+     * @since 5.2.0.0
+     */
+    @Parameter(defaultPrefix = BindingConstants.LITERAL)
+    private String zone;
+
+    @Inject
+    private FieldValidationSupport fieldValidationSupport;    
+    
+    @Environmental
+    private FormSupport formSupport;
+
+    @Inject
+    private Environment environment;
+
+    @Inject
+    private RenderSupport renderSupport;
+
+    @Inject
+    private ComponentResources componentResources;
+
+    @Inject
+    private HiddenFieldLocationRules rules;
 
     @Inject
-    private FieldValidationSupport fieldValidationSupport;
+    private Logger logger;
+
+    @Inject
+    private ClientDataEncoder clientDataEncoder;
+
+    @Inject
+    private ComponentSource componentSource;
+
+    @Inject
+    private PageRenderQueue pageRenderQueue;
+
 
     @SuppressWarnings("unused")
     @Mixin
@@ -139,9 +188,7 @@
 
         tracker.recordInput(this, submittedValue);
 
-        Object selectedValue = InternalUtils.isBlank(submittedValue)
-                               ? null :
-                               encoder.toValue(submittedValue);
+        Object selectedValue = toValue(submittedValue);
 
         try
         {
@@ -169,7 +216,86 @@
         resources.renderInformalParameters(writer);
 
         // Disabled is via a mixin
+        
+        if (this.zone != null) 
+        {
+            final Link link = this.resources.createEventLink(CHANGE_EVENT);
+
+            link.addParameter(FORM_COMPONENTID_PARAMETER, this.formSupport.getFormComponentId());
+
+            final JSONArray spec = new JSONArray();
+            spec.put("change");
+            spec.put(getClientId());
+            spec.put(this.zone);
+            spec.put(link.toAbsoluteURI());
+
+            this.renderSupport.addInit("updateZoneOnEvent", spec);
+        }
+
     }
+    
+    Object onChange() 
+    {
+        final String formId = this.request.getParameter(FORM_COMPONENTID_PARAMETER);
+
+        final String changedValue = this.request.getParameter("t:selectvalue");
+
+        final Object newValue = toValue(changedValue);
+
+        final Holder<Object> holder = Holder.create();
+
+        final ComponentEventCallback callback = new ComponentEventCallback() 
+        {
+            public boolean handleResult(final Object result) 
+            {
+
+                holder.put(result);
+
+                Select.this.value = newValue;
+
+                return true;
+            }
+        };
+
+        this.componentResources.triggerEvent(EventConstants.VALUE_CHANGED, new Object[] { newValue }, callback);
+
+        final PartialMarkupRendererFilter filter = new PartialMarkupRendererFilter() 
+        {
+            public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer) 
+            {
+
+                HiddenFieldPositioner hiddenFieldPositioner = new HiddenFieldPositioner(writer, Select.this.rules);
+
+                final ComponentActionSink actionSink = new ComponentActionSink(Select.this.logger, Select.this.clientDataEncoder);
+
+                final Form form = (Form) Select.this.componentSource.getComponent(formId);
+
+                FormSupport formSupport = form.createRenderTimeFormSupport(form.getClientId(), actionSink, new IdAllocator());
+
+                Select.this.environment.push(FormSupport.class, formSupport);
+                Select.this.environment.push(ValidationTracker.class, new ValidationTrackerImpl());
+
+                renderer.renderMarkup(writer, reply);
+
+                Select.this.environment.pop(ValidationTracker.class);
+                Select.this.environment.pop(FormSupport.class);
+
+                hiddenFieldPositioner.getElement().attributes("type", "hidden", "name", Form.FORM_DATA, 
+                        "value", actionSink.getClientData());
+
+            }
+        };
+
+        this.pageRenderQueue.addPartialMarkupRendererFilter(filter);
+
+        return holder.get();
+    }
+
+    protected Object toValue(final String submittedValue) 
+    {
+        return InternalUtils.isBlank(submittedValue) ? null : this.encoder.toValue(submittedValue);
+    }
+
 
     @SuppressWarnings("unchecked")
     ValueEncoder defaultEncoder()

Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.xdoc
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.xdoc?rev=883081&r1=883080&r2=883081&view=diff
==============================================================================
--- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.xdoc (original)
+++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.xdoc Sun Nov 22 14:10:08 2009
@@ -171,5 +171,119 @@
 
         </section>
 
+        <section name="Chaining of Select components">
+        	There is often a requirement for chaining Select components. When a value of a Select component is changed 
+        	another Select should become visible. Let's consider the following example: you create an online shop for a car seller.
+        	A make is modeled as enumeration CarMaker.  
+        	
+        	<subsection name="CarMaker.java">
+                <source><![CDATA[                                                                   
+public enum CarMaker
+{
+    MERCEDES, AUDI, BMW;
+}]]></source>  
+			</subsection>
+			
+			<subsection name="SelectZoneDemo.tml">
+				The Select component 'carMaker' of the page SelectZoneDemo shows all available car makers. 
+				When a user selects a car maker, another Select component for selecting available models of the make should appear.
+				This can be accomplished by the parameter <em>zone</em> of the Select component 'carMaker'. When <em>zone</em> parameter is bound 
+				every change of the Select's value causes an ajax request. In this case the Select component publishes the event <em>valuechanged</em> which can 
+				be used to provide the <em>model</em> for the second Select component.
+       	                <source><![CDATA[                                                                   
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
+   <t:form>
+      <p>
+         <t:errors />
+      </p>
+      <p>
+         <t:select t:id="carMaker" validate="required" blankOption="always"
+                   model="makeModel" zone="modelZone" encoder="makeEncoder" />
+      </p>
+      
+      <t:zone t:id="modelZone">
+         <t:if test="carMaker">
+            <t:delegate to="modelBlock" />
+         </t:if>
+      </t:zone>
+      
+      <t:block id="modelBlock">
+         <p>
+            <t:select t:id="carModel" model="availableModels" validate="required"/>
+         </p>
+      </t:block>
+      
+      <p>
+         <t:submit value="literal:Submit" />
+      </p>
+   </t:form>
+
+</html>]]></source>
+        </subsection>
+        
+	    <subsection name="SelectZoneDemo.java">
+        		The event handler method for the event <em>valuechanged</em> is used to provide the available car models of the currently selected car maker.
+        		The new Select's value is passed as context. 
+        	                <source><![CDATA[                                                                   
+public class SelectZoneDemo
+{
+   
+   @Inject
+   private Messages messages;
+   
+   @Property
+   @Persist
+   private CarMaker carMaker;
+   
+   @Property
+   @Persist
+   private String carModel;
+   
+   @Inject
+   @Property
+   private Block modelBlock;
+   
+   @Property
+   @Persist
+   private List<String> availableModels;
+    
+    public Object onValueChanged(final CarMaker maker) 
+    {
+       availableModels = findAvailableModels(maker);
+       
+       return this.modelBlock;
+    }
+    
+    public List<String> findAvailableModels(final CarMaker maker) 
+    {
+      switch (maker) 
+      {
+         case AUDI:
+            return Arrays.asList("A4", "A6", "A8");
+         case BMW:
+            return Arrays.asList("3 Series", "5 Series", "7 Series");
+         case MERCEDES:
+            return Arrays.asList("C-Class", "E-Class", "S-Class");
+         default:
+            return Arrays.asList();
+       }
+    }
+    
+    public SelectModel getMakeModel()
+    {
+       return new EnumSelectModel(CarMaker.class, this.messages);
+    }
+    
+    public ValueEncoder<CarMaker> getMakeEncoder() 
+    {
+       return new EnumValueEncoder<CarMaker>(CarMaker.class);
+    }
+
+}]]></source>
+
+			</subsection>
+        
+        </section>
+
     </body>
 </document>
\ No newline at end of file

Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js?rev=883081&r1=883080&r2=883081&view=diff
==============================================================================
--- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js (original)
+++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js Sun Nov 22 14:10:08 2009
@@ -763,6 +763,11 @@
      */
     linkZone : function(element, zoneId, url)
     {
+    	Tapestry.Initializer.updateZoneOnEvent("click", element, zoneId, url);
+    },
+    
+    updateZoneOnEvent : function(eventName, element, zoneId, url)
+    {
         element = $(element);
 
         // Update the element with the id of zone div. This may be changed dynamically on the client
@@ -799,17 +804,24 @@
             return;
         }
 
-        // Otherwise, assume it's just an ordinary link.
+        // Otherwise, assume it's just an ordinary link or input field.
 
-        element.observe("click", function(event)
+        element.observe(eventName, function(event)
         {
             Event.stop(event);
 
             var zoneObject = Tapestry.findZoneManager(element);
 
             if (!zoneObject) return;
+            
+            var newUrl = url;
+
+            if(element.tagName == "SELECT" && element.value)
+            {
+            	newUrl+='&t:selectvalue='+element.value;
+            }
 
-            zoneObject.updateFromURL(url);
+            zoneObject.updateFromURL(newUrl);
         });
     },
 

Added: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/app1/SelectZoneDemo.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/app1/SelectZoneDemo.tml?rev=883081&view=auto
==============================================================================
--- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/app1/SelectZoneDemo.tml (added)
+++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/app1/SelectZoneDemo.tml Sun Nov 22 14:10:08 2009
@@ -0,0 +1,30 @@
+<t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
+	<p>Car Maker: ${carMaker}</p>
+	<p>Car Model: ${carModel}</p>
+	<t:form>
+		<p>
+			<t:errors />
+		</p>
+		<p>
+			<t:select t:id="carMaker" validate="required" blankOption="always"
+				model="makeModel" zone="modelZone" encoder="makeEncoder" />
+		</p>
+
+		<t:zone t:id="modelZone">
+			<t:if test="carMaker">
+				<t:delegate to="modelBlock" />
+			</t:if>
+		</t:zone>
+
+		<t:block id="modelBlock">
+			<p id="carModelContainer">
+				<t:select t:id="carModel" model="availableModels" validate="required" blankOption="always" />
+			</p>
+		</t:block>
+		
+		<p>
+			<t:submit value="literal:Submit" />
+		</p>
+	</t:form>
+
+</t:border>
\ No newline at end of file

Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java?rev=883081&r1=883080&r2=883081&view=diff
==============================================================================
--- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java Sun Nov 22 14:10:08 2009
@@ -2291,6 +2291,16 @@
 
         waitForCondition(condition, PAGE_LOAD_TIMEOUT);
     }
+    
+    private void waitForElementToDisappear(String elementId)
+    {
+
+        String condition = String.format("selenium.browserbot.getCurrentWindow().$(\"%s\").hide()",
+                                         elementId);
+
+        waitForCondition(condition, PAGE_LOAD_TIMEOUT);
+    }
+
 
     private void waitForCSSSelectedElementToAppear(String cssRule)
     {
@@ -2963,4 +2973,48 @@
         
         assertText("eventfired", "true");
     }
+    
+    /**
+     * TAP5-138
+     */
+    @Test
+    public void select_zone()
+    {
+        start("Select Zone Demo");
+        
+        type("carMaker", "BMW");
+        
+        waitForElementToAppear("carModelContainer");
+        
+        click(SUBMIT);
+        
+        String condition = String.format("selenium.browserbot.getCurrentWindow().$$(\"%s\")", "t-error-popup");
+
+        waitForCondition(condition, PAGE_LOAD_TIMEOUT);
+        
+        assertText(String.format("//div[@class='%s']/span", "t-error-popup"), "You must provide a value for Car Model.");
+        
+        type("carModel", "7 Series");
+        
+        clickAndWait(SUBMIT);
+        
+        assertTextPresent("Car Maker: BMW");
+        
+        assertTextPresent("Car Model: 7 Series");
+        
+        waitForElementToDisappear("carModelContainer");
+        
+        type("carMaker", "MERCEDES");
+        
+        waitForElementToAppear("carModelContainer");
+      
+        type("carModel", "E-Class");
+        
+        clickAndWait(SUBMIT);
+        
+        assertTextPresent("Car Maker: MERCEDES");
+        
+        assertTextPresent("Car Model: E-Class");
+    }
+
 }
\ No newline at end of file

Added: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java?rev=883081&view=auto
==============================================================================
--- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java (added)
+++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java Sun Nov 22 14:10:08 2009
@@ -0,0 +1,19 @@
+// Copyright 2009 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.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.integration.app1.data;
+
+public enum CarMaker
+{
+    MERCEDES, AUDI, BMW;
+}

Propchange: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java?rev=883081&r1=883080&r2=883081&view=diff
==============================================================================
--- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java (original)
+++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java Sun Nov 22 14:10:08 2009
@@ -352,7 +352,10 @@
             new Item("SubmitWithContext", "Submit With Context",
                      "Providing a context for Submit component"),
             
-            new Item("ImageSubmitDemo", "Submit with an Image Demo", "Make sure that submit with the image parameter set triggers the 'selected' event.")
+            new Item("ImageSubmitDemo", "Submit with an Image Demo", "Make sure that submit with the image parameter set triggers the 'selected' event."),
+            
+            new Item("SelectZoneDemo", "Select Zone Demo", "Use a Select component to update a zone.")
+
 
     );
 

Added: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java?rev=883081&view=auto
==============================================================================
--- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java (added)
+++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java Sun Nov 22 14:10:08 2009
@@ -0,0 +1,84 @@
+// Copyright 2009 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.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.integration.app1.pages;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.tapestry5.Block;
+import org.apache.tapestry5.SelectModel;
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.integration.app1.data.CarMaker;
+import org.apache.tapestry5.ioc.Messages;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.util.EnumSelectModel;
+import org.apache.tapestry5.util.EnumValueEncoder;
+
+public class SelectZoneDemo
+{
+
+    @Inject
+    private Messages messages;
+
+    @Property
+    @Persist
+    private CarMaker carMaker;
+
+    @Property
+    @Persist
+    private String carModel;
+
+    @Inject
+    @Property
+    private Block modelBlock;
+
+    @Property
+    @Persist
+    private List<String> availableModels;
+
+    public Object onValueChanged(final CarMaker maker)
+    {
+        availableModels = findAvailableModels(maker);
+
+        return this.modelBlock;
+    }
+
+    public List<String> findAvailableModels(final CarMaker maker)
+    {
+        switch (maker)
+        {
+            case AUDI:
+                return Arrays.asList("A4", "A6", "A8");
+            case BMW:
+                return Arrays.asList("3 Series", "5 Series", "7 Series");
+            case MERCEDES:
+                return Arrays.asList("C-Class", "E-Class", "S-Class");
+            default:
+                return Arrays.asList();
+        }
+    }
+
+    public SelectModel getMakeModel()
+    {
+        return new EnumSelectModel(CarMaker.class, this.messages);
+    }
+
+    public ValueEncoder<CarMaker> getMakeEncoder()
+    {
+        return new EnumValueEncoder<CarMaker>(CarMaker.class);
+    }
+
+}

Propchange: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Re: svn commit: r883081 - in /tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src: main/java/org/apache/tapestry5/ main/java/org/apache/tapestry5/corelib/components/ main/resources/org/apache/tapestry5/ test/app1/ test/java/org/apache/tapestry5/integ...

Posted by Ulrich Stärk <ul...@spielviel.de>.
shouldn't it be @since 5.1.0.6?

Uli

Am 22.11.2009 15:10 schrieb drobiazko@apache.org:
> Author: drobiazko
> Date: Sun Nov 22 14:10:08 2009
> New Revision: 883081
> 
> URL: http://svn.apache.org/viewvc?rev=883081&view=rev
> Log:
> TAP5-138: Add Zone parameter to Select component
> 
> Added:
>     tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/app1/SelectZoneDemo.tml
>     tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java   (with props)
>     tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java   (with props)
> Modified:
>     tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java
>     tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java
>     tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.xdoc
>     tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
>     tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
>     tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
> 
> Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java
> URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java?rev=883081&r1=883080&r2=883081&view=diff
> ==============================================================================
> --- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java (original)
> +++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/EventConstants.java Sun Nov 22 14:10:08 2009
> @@ -149,4 +149,13 @@
>       * @SINCE 5.1.0.4
>       */
>      public static final String PROVIDE_COMPLETIONS = "providecompletions";
> +    
> +    /**
> +     * Event triggered by {@link org.apache.tapestry5.corelib.components.Select} component to inform its
> +     * container that Select's value has changed.
> +     *
> +     * @since 5.2.0.0
> +     */
> +    public static final String VALUE_CHANGED = "valuechanged";
> +    
>  }
> 
> Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java
> URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java?rev=883081&r1=883080&r2=883081&view=diff
> ==============================================================================
> --- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java (original)
> +++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java Sun Nov 22 14:10:08 2009
> @@ -18,14 +18,22 @@
>  import org.apache.tapestry5.annotations.*;
>  import org.apache.tapestry5.corelib.base.AbstractField;
>  import org.apache.tapestry5.corelib.data.BlankOption;
> +import org.apache.tapestry5.corelib.internal.ComponentActionSink;
> +import org.apache.tapestry5.corelib.internal.HiddenFieldPositioner;
>  import org.apache.tapestry5.corelib.mixins.RenderDisabled;
>  import org.apache.tapestry5.internal.TapestryInternalUtils;
> +import org.apache.tapestry5.internal.services.PageRenderQueue;
> +import org.apache.tapestry5.internal.util.Holder;
>  import org.apache.tapestry5.internal.util.SelectModelRenderer;
>  import org.apache.tapestry5.ioc.Messages;
>  import org.apache.tapestry5.ioc.annotations.Inject;
> +import org.apache.tapestry5.ioc.internal.util.IdAllocator;
>  import org.apache.tapestry5.ioc.internal.util.InternalUtils;
> +import org.apache.tapestry5.json.JSONArray;
> +import org.apache.tapestry5.json.JSONObject;
>  import org.apache.tapestry5.services.*;
>  import org.apache.tapestry5.util.EnumSelectModel;
> +import org.slf4j.Logger;
>  
>  import java.util.Locale;
>  
> @@ -39,9 +47,12 @@
>   * can be overriden by binding the encoder parameter, or extended by contributing a {@link ValueEncoderFactory} into the
>   * service's configuration.
>   */
> -@Events(EventConstants.VALIDATE)
> +@Events({EventConstants.VALIDATE, EventConstants.VALUE_CHANGED + " when 'zone' parameter is bound"})
>  public class Select extends AbstractField
>  {
> +    public static final String FORM_COMPONENTID_PARAMETER = "t:formcomponentid";
> +    public static final String CHANGE_EVENT = "change";
> +
>      private class Renderer extends SelectModelRenderer
>      {
>  
> @@ -116,9 +127,47 @@
>       */
>      @Parameter(required = true, principal = true, autoconnect = true)
>      private Object value;
> +    
> +    /**
> +     * Binding the zone parameter will cause any change of Select's value to be handled as an Ajax request that updates the
> +     * indicated zone. The component will trigger the event {@link EventConstants#VALUE_CHANGED} to inform its
> +     * container that Select's value has changed.
> +     * 
> +     * @since 5.2.0.0
> +     */
> +    @Parameter(defaultPrefix = BindingConstants.LITERAL)
> +    private String zone;
> +
> +    @Inject
> +    private FieldValidationSupport fieldValidationSupport;    
> +    
> +    @Environmental
> +    private FormSupport formSupport;
> +
> +    @Inject
> +    private Environment environment;
> +
> +    @Inject
> +    private RenderSupport renderSupport;
> +
> +    @Inject
> +    private ComponentResources componentResources;
> +
> +    @Inject
> +    private HiddenFieldLocationRules rules;
>  
>      @Inject
> -    private FieldValidationSupport fieldValidationSupport;
> +    private Logger logger;
> +
> +    @Inject
> +    private ClientDataEncoder clientDataEncoder;
> +
> +    @Inject
> +    private ComponentSource componentSource;
> +
> +    @Inject
> +    private PageRenderQueue pageRenderQueue;
> +
>  
>      @SuppressWarnings("unused")
>      @Mixin
> @@ -139,9 +188,7 @@
>  
>          tracker.recordInput(this, submittedValue);
>  
> -        Object selectedValue = InternalUtils.isBlank(submittedValue)
> -                               ? null :
> -                               encoder.toValue(submittedValue);
> +        Object selectedValue = toValue(submittedValue);
>  
>          try
>          {
> @@ -169,7 +216,86 @@
>          resources.renderInformalParameters(writer);
>  
>          // Disabled is via a mixin
> +        
> +        if (this.zone != null) 
> +        {
> +            final Link link = this.resources.createEventLink(CHANGE_EVENT);
> +
> +            link.addParameter(FORM_COMPONENTID_PARAMETER, this.formSupport.getFormComponentId());
> +
> +            final JSONArray spec = new JSONArray();
> +            spec.put("change");
> +            spec.put(getClientId());
> +            spec.put(this.zone);
> +            spec.put(link.toAbsoluteURI());
> +
> +            this.renderSupport.addInit("updateZoneOnEvent", spec);
> +        }
> +
>      }
> +    
> +    Object onChange() 
> +    {
> +        final String formId = this.request.getParameter(FORM_COMPONENTID_PARAMETER);
> +
> +        final String changedValue = this.request.getParameter("t:selectvalue");
> +
> +        final Object newValue = toValue(changedValue);
> +
> +        final Holder<Object> holder = Holder.create();
> +
> +        final ComponentEventCallback callback = new ComponentEventCallback() 
> +        {
> +            public boolean handleResult(final Object result) 
> +            {
> +
> +                holder.put(result);
> +
> +                Select.this.value = newValue;
> +
> +                return true;
> +            }
> +        };
> +
> +        this.componentResources.triggerEvent(EventConstants.VALUE_CHANGED, new Object[] { newValue }, callback);
> +
> +        final PartialMarkupRendererFilter filter = new PartialMarkupRendererFilter() 
> +        {
> +            public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer) 
> +            {
> +
> +                HiddenFieldPositioner hiddenFieldPositioner = new HiddenFieldPositioner(writer, Select.this.rules);
> +
> +                final ComponentActionSink actionSink = new ComponentActionSink(Select.this.logger, Select.this.clientDataEncoder);
> +
> +                final Form form = (Form) Select.this.componentSource.getComponent(formId);
> +
> +                FormSupport formSupport = form.createRenderTimeFormSupport(form.getClientId(), actionSink, new IdAllocator());
> +
> +                Select.this.environment.push(FormSupport.class, formSupport);
> +                Select.this.environment.push(ValidationTracker.class, new ValidationTrackerImpl());
> +
> +                renderer.renderMarkup(writer, reply);
> +
> +                Select.this.environment.pop(ValidationTracker.class);
> +                Select.this.environment.pop(FormSupport.class);
> +
> +                hiddenFieldPositioner.getElement().attributes("type", "hidden", "name", Form.FORM_DATA, 
> +                        "value", actionSink.getClientData());
> +
> +            }
> +        };
> +
> +        this.pageRenderQueue.addPartialMarkupRendererFilter(filter);
> +
> +        return holder.get();
> +    }
> +
> +    protected Object toValue(final String submittedValue) 
> +    {
> +        return InternalUtils.isBlank(submittedValue) ? null : this.encoder.toValue(submittedValue);
> +    }
> +
>  
>      @SuppressWarnings("unchecked")
>      ValueEncoder defaultEncoder()
> 
> Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.xdoc
> URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.xdoc?rev=883081&r1=883080&r2=883081&view=diff
> ==============================================================================
> --- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.xdoc (original)
> +++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.xdoc Sun Nov 22 14:10:08 2009
> @@ -171,5 +171,119 @@
>  
>          </section>
>  
> +        <section name="Chaining of Select components">
> +        	There is often a requirement for chaining Select components. When a value of a Select component is changed 
> +        	another Select should become visible. Let's consider the following example: you create an online shop for a car seller.
> +        	A make is modeled as enumeration CarMaker.  
> +        	
> +        	<subsection name="CarMaker.java">
> +                <source><![CDATA[                                                                   
> +public enum CarMaker
> +{
> +    MERCEDES, AUDI, BMW;
> +}]]></source>  
> +			</subsection>
> +			
> +			<subsection name="SelectZoneDemo.tml">
> +				The Select component 'carMaker' of the page SelectZoneDemo shows all available car makers. 
> +				When a user selects a car maker, another Select component for selecting available models of the make should appear.
> +				This can be accomplished by the parameter <em>zone</em> of the Select component 'carMaker'. When <em>zone</em> parameter is bound 
> +				every change of the Select's value causes an ajax request. In this case the Select component publishes the event <em>valuechanged</em> which can 
> +				be used to provide the <em>model</em> for the second Select component.
> +       	                <source><![CDATA[                                                                   
> +<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
> +   <t:form>
> +      <p>
> +         <t:errors />
> +      </p>
> +      <p>
> +         <t:select t:id="carMaker" validate="required" blankOption="always"
> +                   model="makeModel" zone="modelZone" encoder="makeEncoder" />
> +      </p>
> +      
> +      <t:zone t:id="modelZone">
> +         <t:if test="carMaker">
> +            <t:delegate to="modelBlock" />
> +         </t:if>
> +      </t:zone>
> +      
> +      <t:block id="modelBlock">
> +         <p>
> +            <t:select t:id="carModel" model="availableModels" validate="required"/>
> +         </p>
> +      </t:block>
> +      
> +      <p>
> +         <t:submit value="literal:Submit" />
> +      </p>
> +   </t:form>
> +
> +</html>]]></source>
> +        </subsection>
> +        
> +	    <subsection name="SelectZoneDemo.java">
> +        		The event handler method for the event <em>valuechanged</em> is used to provide the available car models of the currently selected car maker.
> +        		The new Select's value is passed as context. 
> +        	                <source><![CDATA[                                                                   
> +public class SelectZoneDemo
> +{
> +   
> +   @Inject
> +   private Messages messages;
> +   
> +   @Property
> +   @Persist
> +   private CarMaker carMaker;
> +   
> +   @Property
> +   @Persist
> +   private String carModel;
> +   
> +   @Inject
> +   @Property
> +   private Block modelBlock;
> +   
> +   @Property
> +   @Persist
> +   private List<String> availableModels;
> +    
> +    public Object onValueChanged(final CarMaker maker) 
> +    {
> +       availableModels = findAvailableModels(maker);
> +       
> +       return this.modelBlock;
> +    }
> +    
> +    public List<String> findAvailableModels(final CarMaker maker) 
> +    {
> +      switch (maker) 
> +      {
> +         case AUDI:
> +            return Arrays.asList("A4", "A6", "A8");
> +         case BMW:
> +            return Arrays.asList("3 Series", "5 Series", "7 Series");
> +         case MERCEDES:
> +            return Arrays.asList("C-Class", "E-Class", "S-Class");
> +         default:
> +            return Arrays.asList();
> +       }
> +    }
> +    
> +    public SelectModel getMakeModel()
> +    {
> +       return new EnumSelectModel(CarMaker.class, this.messages);
> +    }
> +    
> +    public ValueEncoder<CarMaker> getMakeEncoder() 
> +    {
> +       return new EnumValueEncoder<CarMaker>(CarMaker.class);
> +    }
> +
> +}]]></source>
> +
> +			</subsection>
> +        
> +        </section>
> +
>      </body>
>  </document>
> \ No newline at end of file
> 
> Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
> URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js?rev=883081&r1=883080&r2=883081&view=diff
> ==============================================================================
> --- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js (original)
> +++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js Sun Nov 22 14:10:08 2009
> @@ -763,6 +763,11 @@
>       */
>      linkZone : function(element, zoneId, url)
>      {
> +    	Tapestry.Initializer.updateZoneOnEvent("click", element, zoneId, url);
> +    },
> +    
> +    updateZoneOnEvent : function(eventName, element, zoneId, url)
> +    {
>          element = $(element);
>  
>          // Update the element with the id of zone div. This may be changed dynamically on the client
> @@ -799,17 +804,24 @@
>              return;
>          }
>  
> -        // Otherwise, assume it's just an ordinary link.
> +        // Otherwise, assume it's just an ordinary link or input field.
>  
> -        element.observe("click", function(event)
> +        element.observe(eventName, function(event)
>          {
>              Event.stop(event);
>  
>              var zoneObject = Tapestry.findZoneManager(element);
>  
>              if (!zoneObject) return;
> +            
> +            var newUrl = url;
> +
> +            if(element.tagName == "SELECT" && element.value)
> +            {
> +            	newUrl+='&t:selectvalue='+element.value;
> +            }
>  
> -            zoneObject.updateFromURL(url);
> +            zoneObject.updateFromURL(newUrl);
>          });
>      },
>  
> 
> Added: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/app1/SelectZoneDemo.tml
> URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/app1/SelectZoneDemo.tml?rev=883081&view=auto
> ==============================================================================
> --- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/app1/SelectZoneDemo.tml (added)
> +++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/app1/SelectZoneDemo.tml Sun Nov 22 14:10:08 2009
> @@ -0,0 +1,30 @@
> +<t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
> +	<p>Car Maker: ${carMaker}</p>
> +	<p>Car Model: ${carModel}</p>
> +	<t:form>
> +		<p>
> +			<t:errors />
> +		</p>
> +		<p>
> +			<t:select t:id="carMaker" validate="required" blankOption="always"
> +				model="makeModel" zone="modelZone" encoder="makeEncoder" />
> +		</p>
> +
> +		<t:zone t:id="modelZone">
> +			<t:if test="carMaker">
> +				<t:delegate to="modelBlock" />
> +			</t:if>
> +		</t:zone>
> +
> +		<t:block id="modelBlock">
> +			<p id="carModelContainer">
> +				<t:select t:id="carModel" model="availableModels" validate="required" blankOption="always" />
> +			</p>
> +		</t:block>
> +		
> +		<p>
> +			<t:submit value="literal:Submit" />
> +		</p>
> +	</t:form>
> +
> +</t:border>
> \ No newline at end of file
> 
> Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
> URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java?rev=883081&r1=883080&r2=883081&view=diff
> ==============================================================================
> --- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java (original)
> +++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java Sun Nov 22 14:10:08 2009
> @@ -2291,6 +2291,16 @@
>  
>          waitForCondition(condition, PAGE_LOAD_TIMEOUT);
>      }
> +    
> +    private void waitForElementToDisappear(String elementId)
> +    {
> +
> +        String condition = String.format("selenium.browserbot.getCurrentWindow().$(\"%s\").hide()",
> +                                         elementId);
> +
> +        waitForCondition(condition, PAGE_LOAD_TIMEOUT);
> +    }
> +
>  
>      private void waitForCSSSelectedElementToAppear(String cssRule)
>      {
> @@ -2963,4 +2973,48 @@
>          
>          assertText("eventfired", "true");
>      }
> +    
> +    /**
> +     * TAP5-138
> +     */
> +    @Test
> +    public void select_zone()
> +    {
> +        start("Select Zone Demo");
> +        
> +        type("carMaker", "BMW");
> +        
> +        waitForElementToAppear("carModelContainer");
> +        
> +        click(SUBMIT);
> +        
> +        String condition = String.format("selenium.browserbot.getCurrentWindow().$$(\"%s\")", "t-error-popup");
> +
> +        waitForCondition(condition, PAGE_LOAD_TIMEOUT);
> +        
> +        assertText(String.format("//div[@class='%s']/span", "t-error-popup"), "You must provide a value for Car Model.");
> +        
> +        type("carModel", "7 Series");
> +        
> +        clickAndWait(SUBMIT);
> +        
> +        assertTextPresent("Car Maker: BMW");
> +        
> +        assertTextPresent("Car Model: 7 Series");
> +        
> +        waitForElementToDisappear("carModelContainer");
> +        
> +        type("carMaker", "MERCEDES");
> +        
> +        waitForElementToAppear("carModelContainer");
> +      
> +        type("carModel", "E-Class");
> +        
> +        clickAndWait(SUBMIT);
> +        
> +        assertTextPresent("Car Maker: MERCEDES");
> +        
> +        assertTextPresent("Car Model: E-Class");
> +    }
> +
>  }
> \ No newline at end of file
> 
> Added: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java
> URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java?rev=883081&view=auto
> ==============================================================================
> --- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java (added)
> +++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java Sun Nov 22 14:10:08 2009
> @@ -0,0 +1,19 @@
> +// Copyright 2009 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.
> +// You may obtain a copy of the License at
> +//
> +//     http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> +// See the License for the specific language governing permissions and
> +// limitations under the License.
> +package org.apache.tapestry5.integration.app1.data;
> +
> +public enum CarMaker
> +{
> +    MERCEDES, AUDI, BMW;
> +}
> 
> Propchange: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/CarMaker.java
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
> 
> Modified: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
> URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java?rev=883081&r1=883080&r2=883081&view=diff
> ==============================================================================
> --- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java (original)
> +++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java Sun Nov 22 14:10:08 2009
> @@ -352,7 +352,10 @@
>              new Item("SubmitWithContext", "Submit With Context",
>                       "Providing a context for Submit component"),
>              
> -            new Item("ImageSubmitDemo", "Submit with an Image Demo", "Make sure that submit with the image parameter set triggers the 'selected' event.")
> +            new Item("ImageSubmitDemo", "Submit with an Image Demo", "Make sure that submit with the image parameter set triggers the 'selected' event."),
> +            
> +            new Item("SelectZoneDemo", "Select Zone Demo", "Use a Select component to update a zone.")
> +
>  
>      );
>  
> 
> Added: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java
> URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java?rev=883081&view=auto
> ==============================================================================
> --- tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java (added)
> +++ tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java Sun Nov 22 14:10:08 2009
> @@ -0,0 +1,84 @@
> +// Copyright 2009 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.
> +// You may obtain a copy of the License at
> +//
> +//     http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> +// See the License for the specific language governing permissions and
> +// limitations under the License.
> +package org.apache.tapestry5.integration.app1.pages;
> +
> +import java.util.Arrays;
> +import java.util.List;
> +
> +import org.apache.tapestry5.Block;
> +import org.apache.tapestry5.SelectModel;
> +import org.apache.tapestry5.ValueEncoder;
> +import org.apache.tapestry5.annotations.Persist;
> +import org.apache.tapestry5.annotations.Property;
> +import org.apache.tapestry5.integration.app1.data.CarMaker;
> +import org.apache.tapestry5.ioc.Messages;
> +import org.apache.tapestry5.ioc.annotations.Inject;
> +import org.apache.tapestry5.util.EnumSelectModel;
> +import org.apache.tapestry5.util.EnumValueEncoder;
> +
> +public class SelectZoneDemo
> +{
> +
> +    @Inject
> +    private Messages messages;
> +
> +    @Property
> +    @Persist
> +    private CarMaker carMaker;
> +
> +    @Property
> +    @Persist
> +    private String carModel;
> +
> +    @Inject
> +    @Property
> +    private Block modelBlock;
> +
> +    @Property
> +    @Persist
> +    private List<String> availableModels;
> +
> +    public Object onValueChanged(final CarMaker maker)
> +    {
> +        availableModels = findAvailableModels(maker);
> +
> +        return this.modelBlock;
> +    }
> +
> +    public List<String> findAvailableModels(final CarMaker maker)
> +    {
> +        switch (maker)
> +        {
> +            case AUDI:
> +                return Arrays.asList("A4", "A6", "A8");
> +            case BMW:
> +                return Arrays.asList("3 Series", "5 Series", "7 Series");
> +            case MERCEDES:
> +                return Arrays.asList("C-Class", "E-Class", "S-Class");
> +            default:
> +                return Arrays.asList();
> +        }
> +    }
> +
> +    public SelectModel getMakeModel()
> +    {
> +        return new EnumSelectModel(CarMaker.class, this.messages);
> +    }
> +
> +    public ValueEncoder<CarMaker> getMakeEncoder()
> +    {
> +        return new EnumValueEncoder<CarMaker>(CarMaker.class);
> +    }
> +
> +}
> 
> Propchange: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: tapestry/tapestry5/branches/5.1.0.x-dev/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SelectZoneDemo.java
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org