You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by jk...@apache.org on 2006/07/11 05:05:17 UTC

svn commit: r420685 [1/2] - in /tapestry/tapestry4/trunk: .settings/ eclipse/ tapestry-examples/TimeTracker/src/context/ tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/ tapestry-examples/Workbench/src/context/ tapestry-fram...

Author: jkuhnert
Date: Mon Jul 10 20:05:15 2006
New Revision: 420685

URL: http://svn.apache.org/viewvc?rev=420685&view=rev
Log:
Added all of that silly ajax crap to DirectLinks and fixed portlet url encoding for assets

Added:
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/InjectRenderWorker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLinkWorker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLinkWorker.script
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/test/MockComponentRenderWorker.java
    tapestry/tapestry4/trunk/tapestry-portlet/src/java/org/apache/tapestry/portlet/PortletAssetLinkFactoryImpl.java
Modified:
    tapestry/tapestry4/trunk/.settings/org.eclipse.jdt.core.prefs
    tapestry/tapestry4/trunk/.settings/org.eclipse.jdt.ui.prefs
    tapestry/tapestry4/trunk/eclipse/formatter.xml
    tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/Home.html
    tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java
    tapestry/tapestry4/trunk/tapestry-examples/Workbench/src/context/Fields.html
    tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.enhance.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.render.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.services.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.url.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/AbstractComponent.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/IDirect.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.jwc
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.script
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/DirectService.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/DirectServiceParameter.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/EngineServiceLink.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/AbstractLinkComponent.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DefaultLinkRenderer.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLink.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLink.jwc
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseContributorImpl.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/LinkFactoryImpl.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/test/Creator.java
    tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js
    tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestLibrary.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestLocalization.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestOutputEncoding.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestSimple.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestTemplateEncoding.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestWMLComponents.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/dojo/form/TestAutocompleter.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/engine/DirectServiceTest.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/engine/EngineServiceLinkTest.java
    tapestry/tapestry4/trunk/tapestry-portlet/src/descriptor/META-INF/hivemodule.xml
    tapestry/tapestry4/trunk/tapestry-portlet/src/descriptor/META-INF/tapestry.portlet.services.xml

Modified: tapestry/tapestry4/trunk/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/.settings/org.eclipse.jdt.core.prefs?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/.settings/org.eclipse.jdt.core.prefs (original)
+++ tapestry/tapestry4/trunk/.settings/org.eclipse.jdt.core.prefs Mon Jul 10 20:05:15 2006
@@ -1,4 +1,4 @@
-#Fri Jun 02 12:37:15 EDT 2006
+#Sun Jul 09 09:30:52 EDT 2006
 eclipse.preferences.version=1
 org.eclipse.jdt.core.codeComplete.argumentPrefixes=
 org.eclipse.jdt.core.codeComplete.argumentSuffixes=
@@ -305,7 +305,7 @@
 org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
 org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=true
 org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.lineSplit=100
+org.eclipse.jdt.core.formatter.lineSplit=120
 org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
 org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
 org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false

Modified: tapestry/tapestry4/trunk/.settings/org.eclipse.jdt.ui.prefs
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/.settings/org.eclipse.jdt.ui.prefs?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/.settings/org.eclipse.jdt.ui.prefs (original)
+++ tapestry/tapestry4/trunk/.settings/org.eclipse.jdt.ui.prefs Mon Jul 10 20:05:15 2006
@@ -1,4 +1,4 @@
-#Sat Jul 01 12:53:42 EDT 2006
+#Sun Jul 09 12:08:50 EDT 2006
 eclipse.preferences.version=1
 formatter_profile=_tapestry
 formatter_settings_version=10
@@ -6,7 +6,7 @@
 org.eclipse.jdt.ui.exception.name=ex
 org.eclipse.jdt.ui.gettersetter.use.is=true
 org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.importorder=java;org;com;javax;
 org.eclipse.jdt.ui.javadoc=true
 org.eclipse.jdt.ui.keywordthis=false
 org.eclipse.jdt.ui.ondemandthreshold=99

Modified: tapestry/tapestry4/trunk/eclipse/formatter.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/eclipse/formatter.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/eclipse/formatter.xml (original)
+++ tapestry/tapestry4/trunk/eclipse/formatter.xml Mon Jul 10 20:05:15 2006
@@ -240,7 +240,7 @@
 <setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
 <setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="true"/>
 <setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="100"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
 <setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
 <setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
 <setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>

Modified: tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/Home.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/Home.html?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/Home.html (original)
+++ tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/Home.html Mon Jul 10 20:05:15 2006
@@ -60,6 +60,12 @@
     </fieldset>
 </form>
 
+<p>
+Click this link to manually update the project description. 
+	<a jwcid="@DirectLink" listener="listener:linkUpdateClicked" 
+		updateComponents="ognl:{'projectDescription'}" async="true" >Update</a>
+</p>
+
 <div jwcid="projectDescription@Any" >
 	<span jwcid="@If" condition="ognl:selectedProject">
 		<h2 style="clear:left" ><span jwcid="@Insert" value="ognl:selectedProject.name" /></h2>

Modified: tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java (original)
+++ tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java Mon Jul 10 20:05:15 2006
@@ -107,6 +107,10 @@
         cycle.getResponseBuilder().updateComponent("feedbackBlock");
     }
     
+    public void linkUpdateClicked()
+    {
+    }
+    
     /**
      * Invoked by form to add a new task.
      */

Modified: tapestry/tapestry4/trunk/tapestry-examples/Workbench/src/context/Fields.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-examples/Workbench/src/context/Fields.html?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-examples/Workbench/src/context/Fields.html (original)
+++ tapestry/tapestry4/trunk/tapestry-examples/Workbench/src/context/Fields.html Mon Jul 10 20:05:15 2006
@@ -17,7 +17,8 @@
 
 <span jwcid="showError"/>
 
-<form jwcid="form@Form" success="listener:doSubmit" delegate="bean:delegate" clientValidationEnabled="ognl:clientValidationEnabled">
+<form jwcid="form@Form" success="listener:doSubmit" delegate="bean:delegate" 
+      clientValidationEnabled="ognl:clientValidationEnabled">
 
 <table class="form">
 	<tr>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.enhance.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.enhance.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.enhance.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.enhance.xml Mon Jul 10 20:05:15 2006
@@ -82,6 +82,7 @@
     <command id="inject-messages" object="service:InjectMessagesWorker" before="abstract-property"/>    
     <command id="inject-specification" object="service:InjectSpecificationWorker" before="abstract-property"/>
     <command id="inject-event-invoker" object="service:InjectEventInvokerWorker" before="abstract-property"/>
+    <command id="inject-render-worker" object="service:InjectRenderWorker" before="abstract-property"/>
     <command id="specified-property" object="service:SpecifiedPropertyWorker" before="abstract-property"/>
     <command id="parameter" object="service:ParameterPropertyWorker" before="abstract-property"/>
     <command id="dispatch-inject" object="service:DispatchToInjectWorker" before="abstract-property"/>
@@ -183,6 +184,18 @@
     <invoke-factory>
       <construct class="InjectEventInvokerWorker">
         <set-service property="componentEventInvoker" service-id="tapestry.event.ComponentEventInvoker" />
+      </construct>
+    </invoke-factory>
+    
+  </service-point>
+  
+  <service-point id="InjectRenderWorker" interface="EnhancementWorker">
+    
+    Injects the ComponentRenderWorker property into all components.
+    
+    <invoke-factory>
+      <construct class="InjectRenderWorker">
+        <set-service property="renderWorker" service-id="tapestry.render.ComponentRenderChain" />
       </construct>
     </invoke-factory>
     

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.render.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.render.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.render.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.render.xml Mon Jul 10 20:05:15 2006
@@ -55,8 +55,25 @@
   
   </service-point>
   
+  <service-point id="DirectLinkWorker" 
+                interface="org.apache.tapestry.services.ComponentRenderWorker">
+    
+    Wires the optional parameters updateComponents/async/json shared by all IDirect components
+    to client side javascript IO events if specified.
+    
+    <invoke-factory>
+      <construct class="org.apache.tapestry.link.DirectLinkWorker"
+                 initialize-method="initialize" >
+        <set property="script" value="/org/apache/tapestry/link/DirectLinkWorker.script" />
+        <set-service property="scriptSource" service-id="tapestry.script.ScriptSource"/>
+      </construct>
+    </invoke-factory>
+  
+  </service-point>
+  
   <contribution configuration-id="ComponentRenderWorkers">
     <command id="component-event-connection" object="service:ComponentEventConnectionWorker" />
+    <command id="direct-link-worker" object="service:DirectLinkWorker" />
   </contribution>
   
 </module>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.services.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.services.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.services.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.services.xml Mon Jul 10 20:05:15 2006
@@ -261,7 +261,6 @@
                 <set-service property="localeManager" service-id="tapestry.request.RequestLocaleManager"/>
                 <set-object property="markupWriterSource"  value="infrastructure:markupWriterSource"/>
                 <set-object property="webResponse" value="infrastructure:response"/>
-                <set-service property="componentRenderWorker" service-id="tapestry.render.ComponentRenderChain" />
             </construct>
         </invoke-factory>
     </service-point>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.url.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.url.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.url.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.url.xml Mon Jul 10 20:05:15 2006
@@ -30,7 +30,7 @@
         <set-object property="servletPath" value="app-property:org.apache.tapestry.servlet-path"/>
         <set-object property="contextPath" value="infrastructure:contextPath"/>
 		<set-object property="request" value="infrastructure:request"/>
-		<set-object property="requestCycle" value="infrastructure:requestCycle"/>
+        <set-object property="requestCycle" value="infrastructure:requestCycle"/>
         <set-service property="persistenceStrategySource" 
           service-id="tapestry.persist.PropertyPersistenceStrategySource"/>
       </construct>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/AbstractComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/AbstractComponent.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/AbstractComponent.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/AbstractComponent.java Mon Jul 10 20:05:15 2006
@@ -32,6 +32,7 @@
 import org.apache.tapestry.event.BrowserEvent;
 import org.apache.tapestry.event.PageEvent;
 import org.apache.tapestry.listener.ListenerMap;
+import org.apache.tapestry.services.ComponentRenderWorker;
 import org.apache.tapestry.services.impl.ComponentEventInvoker;
 import org.apache.tapestry.spec.IComponentSpecification;
 import org.apache.tapestry.spec.IContainedComponent;
@@ -306,14 +307,14 @@
         // try to generate a client id if needed/possible
         if (_clientId == null) {
             String id = getBoundId();
+            
             if (id == null) id = getId();
             
-            _clientId = 
-                cycle.getUniqueId(TapestryUtils
-                        .convertTapestryIdToNMToken(id));
+            _clientId =  cycle.getUniqueId(TapestryUtils.convertTapestryIdToNMToken(id));
         }
         
         String id = getClientId();
+        
         if (id != null)
             writer.attribute("id", id);
     }
@@ -672,6 +673,8 @@
             prepareForRender(cycle);
             
             renderComponent(writer, cycle);
+            
+            getRenderWorker().renderComponent(cycle, this);
         }
         finally
         {
@@ -931,6 +934,14 @@
     public void triggerEvent(IRequestCycle cycle, BrowserEvent event)
     {
         getEventInvoker().invokeListeners(this, cycle, event);
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    public ComponentRenderWorker getRenderWorker()
+    {
+        throw new IllegalStateException(TapestryMessages.providedByEnhancement("getRenderWorker"));
     }
     
     /**

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/IDirect.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/IDirect.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/IDirect.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/IDirect.java Mon Jul 10 20:05:15 2006
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry;
 
+import java.util.Collection;
+
 /**
  *  Interface that defines classes that may be messaged by the direct
  *  service.
@@ -28,7 +30,7 @@
      *  the appropriate action.  The {@link org.apache.tapestry.link.DirectLink} component will
      *  notify its listener.
      *
-     **/
+     */
 
     void trigger(IRequestCycle cycle);
 
@@ -41,8 +43,51 @@
      * 
      *  @since 2.3
      * 
-     **/
+     */
 
     boolean isStateful();
-
+    
+    /**
+     * If set, will be used to update/refresh portions of a response during XHR requests.
+     * 
+     * <p>
+     *  For instance, if you have a page listing projects and you wanted to update an 
+     *  {@link Any} components contents whenever one of the project links was clicked 
+     *  you would use a {@link DirectLink} with the parameters:
+     * </p>
+     * 
+     * <pre>
+     *      updateComponents="{'projectDetails'}"
+     *      async="true"
+     * </pre>
+     * 
+     * @return The list of components to update, if any.
+     */
+    Collection getUpdateComponents();
+    
+    /**
+     * Used to specify whether or not the result of this invocation should be returned asynchronously
+     * or use normal browser page reload semantics. 
+     * 
+     * <p>
+     *  Async being true means responses will be encoded as XML using XmlHttpRequests. If you would like
+     *  your request/response to be in another format - like JSON - you must also specify the additional 
+     *  parameter {@link #isJson()}.  Without setting the {@link #getUpdateComponents()} parameter
+     * this parameter is pretty useless.
+     * </p>
+     * 
+     * @see #isJson()
+     * @return True if invocation should be processed asynchronously.
+     */
+    boolean isAsync();
+    
+    /**
+     * Used to specify that the return invocation of the response created should be in the
+     * {@linkplain http://json.org} format. Without setting the {@link #getUpdateComponents()} parameter
+     * this parameter is pretty useless.
+     * 
+     * @see {@link org.apache.IJSONRender}
+     * @return True if response should be encoded using JSON semantics.
+     */
+    boolean isJson();
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.java Mon Jul 10 20:05:15 2006
@@ -13,7 +13,10 @@
 // limitations under the License.
 package org.apache.tapestry.dojo.form;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.tapestry.IDirect;
@@ -72,10 +75,7 @@
         writer.end();
         renderDelegateSuffix(writer, cycle);
         
-        DirectServiceParameter dsp = 
-            new DirectServiceParameter(this, new Object[]{}, 
-                    new String[]{getId()}, true);
-        ILink link = getDirectService().getLink(true, dsp);
+        ILink link = getDirectService().getLink(true, new DirectServiceParameter(this));
         
         Map parms = new HashMap();
         parms.put("id", getClientId());
@@ -184,7 +184,7 @@
      */
     public boolean isStateful()
     {
-        return false;
+        return true;
     }
     
     /**
@@ -249,5 +249,32 @@
     public boolean isRequired()
     {
         return getValidatableFieldSupport().isRequired(this);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public Collection getUpdateComponents()
+    {
+        List comps = new ArrayList();
+        comps.add(getId());
+        
+        return comps;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public boolean isAsync()
+    {
+        return Boolean.TRUE;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public boolean isJson()
+    {
+        return Boolean.TRUE;
     }
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.jwc
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.jwc?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.jwc (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.jwc Mon Jul 10 20:05:15 2006
@@ -32,8 +32,8 @@
   <parameter name="model" required="yes"/>
   	
   <parameter name="disabled"/>
-
-  <parameter name="filterOnChange" default-value="false" />
+  
+  <parameter name="filterOnChange" default-value="true" />
   
   <parameter name="autocomplete" default-value="true" />
   
@@ -47,7 +47,7 @@
   <parameter name="validators"/>
   
   <parameter name="id" property="idParameter" default-value="id"/>
-
+  
   <reserved-parameter name="name"/>
   
   <inject property="validatableFieldSupport" object="service:tapestry.form.ValidatableFieldSupport"/>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.script
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.script?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.script (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/form/Autocompleter.script Mon Jul 10 20:05:15 2006
@@ -9,7 +9,6 @@
     <body>
         <unique>
             dojo.require("dojo.io");
-            dojo.require("dojo.json");
             dojo.require("dojo.event");
             dojo.require("dojo.widget.Manager");
             dojo.require("dojo.widget.Select");

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/DirectService.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/DirectService.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/DirectService.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/DirectService.java Mon Jul 10 20:05:15 2006
@@ -82,10 +82,19 @@
         parameters.put(ServiceConstants.CONTAINER, componentPage == activePage ? null
                 : componentPage.getPageName());
         parameters.put(ServiceConstants.SESSION, stateful ? "T" : null);
-        if (dsp.getUpdateParts() != null && dsp.getUpdateParts().length > 0)
-            parameters.put(ServiceConstants.UPDATE_PARTS, dsp.getUpdateParts());
-        if (dsp.isJSON())
-            parameters.put("json", String.valueOf(dsp.isJSON()));
+        
+        // handle dynamic XHR/JSON parameters
+        if (dsp.isAsync() || dsp.isJson()) {
+            
+            if (dsp.getUpdateParts() != null && dsp.getUpdateParts().length > 0)
+                parameters.put(ServiceConstants.UPDATE_PARTS, dsp.getUpdateParts());
+            
+            if (dsp.isJson())
+                parameters.put("json", String.valueOf(dsp.isJson()));
+            
+            // don't need to put isAsync parameter in as that is handled via http headers
+        }
+        
         parameters.put(ServiceConstants.PARAMETER, dsp.getServiceParameters());
         
         return _linkFactory.constructLink(this, post, parameters, true);

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/DirectServiceParameter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/DirectServiceParameter.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/DirectServiceParameter.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/DirectServiceParameter.java Mon Jul 10 20:05:15 2006
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry.engine;
 
+import java.util.Collection;
+
 import org.apache.hivemind.util.Defense;
 import org.apache.tapestry.IDirect;
 
@@ -25,43 +27,38 @@
  */
 public class DirectServiceParameter
 {
-    protected IDirect _direct;
+    private IDirect _direct;
 
-    protected Object[] _serviceParameters;
+    private Object[] _serviceParameters;
 
-    protected String[] _updateParts;
+    private String[] _updateParts;
+    
+    private boolean _json;
     
-    protected boolean _json;
+    private boolean _async;
     
     public DirectServiceParameter(IDirect direct)
     {
-        this(direct, null, null, false);
-    }
-
-    public DirectServiceParameter(IDirect direct, Object[] serviceParameters)
-    {
-        this(direct, serviceParameters, null, false);
+        this(direct, null);
     }
     
-    /**
-     * Creates a new direct service parameter map. 
-     * 
-     * @param direct The object implementing the direct triggerable interface
-     * @param serviceParameters The parameters for the triggered object
-     * @param updateParts The parts expected to be updated on any returned response
-     * triggerd by this direct call.
-     */
-    public DirectServiceParameter(IDirect direct, Object[] serviceParameters,
-            String[] updateParts, boolean json)
+    public DirectServiceParameter(IDirect direct, Object[] serviceParameters)
     {
         Defense.notNull(direct, "direct");
         
         _direct = direct;
         _serviceParameters = serviceParameters;
-        _updateParts = updateParts;
-        _json = json;
+        
+        Collection comps = direct.getUpdateComponents();
+        if (comps == null)
+            _updateParts = new String[0];
+        else
+            _updateParts = (String[])comps.toArray(new String[comps.size()]);
+        
+        _json = direct.isJson();
+        _async = direct.isAsync();
     }
-
+    
     public IDirect getDirect()
     {
         return _direct;
@@ -77,8 +74,13 @@
         return _updateParts;
     }
     
-    public boolean isJSON()
+    public boolean isJson()
     {
         return _json;
+    }
+    
+    public boolean isAsync()
+    {
+        return _async;
     }
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/EngineServiceLink.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/EngineServiceLink.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/EngineServiceLink.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/engine/EngineServiceLink.java Mon Jul 10 20:05:15 2006
@@ -40,12 +40,12 @@
 {
     private static final int DEFAULT_HTTP_PORT = 80;
 
-    private final IRequestCycle _cycle;
-
     private final String _servletPath;
 
     private final URLCodec _codec;
 
+    private IRequestCycle _cycle;
+    
     private String _encoding;
 
     /** @since 4.0 */
@@ -54,10 +54,44 @@
     /** @since 4.0 */
 
     private final WebRequest _request;
-
+    
     /**
      * Creates a new EngineServiceLink.
      * 
+     * @param servletPath
+     *            The path used to invoke the Tapestry servlet.
+     * @param codec
+     *            A codec for converting strings into URL-safe formats.
+     * @param encoding
+     *            The output encoding for the request.
+     * @param parameters
+     *            The query parameters to be encoded into the url. Keys are strings, values are
+     *            null, string or array of string. The map is retained, not copied.
+     * @param stateful
+     *            if true, the service which generated the EngineServiceLink is stateful and expects
+     *            that the final URL will be passed through {@link IRequestCycle#encodeURL(String)}.
+     */
+    
+    public EngineServiceLink(String servletPath, String encoding,
+            URLCodec codec, WebRequest request, Map parameters, boolean stateful)
+    {
+        Defense.notNull(servletPath, "servletPath");
+        Defense.notNull(encoding, "encoding");
+        Defense.notNull(codec, "codec");
+        Defense.notNull(request, "request");
+        Defense.notNull(parameters, "parameters");
+        
+        _servletPath = servletPath;
+        _encoding = encoding;
+        _codec = codec;
+        _request = request;
+        _parameters = new QueryParameterMap(parameters);
+    }
+    
+    /**
+     * Creates a new EngineServiceLink. Primarily used in portlet applications with the
+     * additional {@link IRequestCycle} parameter being used to encode asset urls.
+     * 
      * @param cycle
      *            The {@link IRequestCycle}&nbsp; the EngineServiceLink is to be created for.
      * @param servletPath
@@ -83,7 +117,7 @@
         Defense.notNull(codec, "codec");
         Defense.notNull(request, "request");
         Defense.notNull(parameters, "parameters");
-
+        
         _cycle = cycle;
         _servletPath = servletPath;
         _encoding = encoding;
@@ -155,11 +189,10 @@
         }
 
         String result = buffer.toString();
-
-        //TODO: Portlets need this result encoded again via IRequestCycle.encodeURL(), need
-        // to find a way to do this that doesn't conflict with existing URL construction semantics. (the
-        // isStateful parameter would effectively be ignored in this class if we encoded the url again
-        // because that method adds sessionID information from the servlet container ) JIRA issue TAPESTRY-802
+        
+        // TODO: This is somewhat questionable right now, was added in to support TAPESTRY-802
+        if (_cycle != null)
+            result = _cycle.encodeURL(result);
         
         return result;
     }

Added: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/InjectRenderWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/InjectRenderWorker.java?rev=420685&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/InjectRenderWorker.java (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/enhance/InjectRenderWorker.java Mon Jul 10 20:05:15 2006
@@ -0,0 +1,77 @@
+// Copyright 2005 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.tapestry.enhance;
+
+import org.apache.hivemind.ErrorLog;
+import org.apache.hivemind.util.Defense;
+import org.apache.tapestry.services.ComponentRenderWorker;
+import org.apache.tapestry.spec.IComponentSpecification;
+
+/**
+ * Injects the component's render worker chain as the
+ * {@link org.apache.tapestry.IComponent#getRenderWorker() renderWorker}property.
+ * 
+ * @author jkuhnert
+ * @since 4.1
+ */
+public class InjectRenderWorker implements EnhancementWorker
+{
+
+    public static final String PROPERTY_NAME = "renderWorker";
+    
+    private ErrorLog _errorLog;
+    
+    private ComponentRenderWorker _renderWorker;
+    
+    public void performEnhancement(EnhancementOperation op, IComponentSpecification spec)
+    {
+        try
+        {
+            injectRenderWorker(op, spec);
+        }
+        catch (Exception ex)
+        {
+            _errorLog.error(EnhanceMessages.errorAddingProperty(
+                    PROPERTY_NAME, op.getBaseClass(), ex), spec
+                    .getLocation(), ex);
+        }
+    }
+    
+    public void injectRenderWorker(EnhancementOperation op, IComponentSpecification spec)
+    {
+        Defense.notNull(op, "op");
+        Defense.notNull(spec, "spec");
+        
+        op.claimReadonlyProperty(PROPERTY_NAME);
+        
+        String fieldName = op.addInjectedField("_$"
+                + PROPERTY_NAME, ComponentRenderWorker.class,
+                _renderWorker);
+        
+        EnhanceUtils.createSimpleAccessor(op, fieldName,
+                PROPERTY_NAME, ComponentRenderWorker.class,
+                spec.getLocation());
+    }
+    
+    public void setErrorLog(ErrorLog errorLog)
+    {
+        _errorLog = errorLog;
+    }
+    
+    public void setRenderWorker(ComponentRenderWorker worker)
+    {
+        _renderWorker = worker;
+    }
+}

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/AbstractLinkComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/AbstractLinkComponent.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/AbstractLinkComponent.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/AbstractLinkComponent.java Mon Jul 10 20:05:15 2006
@@ -42,9 +42,9 @@
 public abstract class AbstractLinkComponent extends AbstractComponent implements ILinkComponent
 {
     private Map _eventHandlers;
-
+    
     public abstract boolean isDisabled();
-
+    
     /**
      * Adds an event handler (typically, from a wrapped component such as a
      * {@link org.apache.tapestry.html.Rollover}).
@@ -143,7 +143,7 @@
             wrapperFunctionName = attributeName + "_" + finalName;
 
             StringBuffer buffer = new StringBuffer();
-
+            
             buffer.append("function ");
             buffer.append(wrapperFunctionName);
             buffer.append(" ()\n{\n");
@@ -175,13 +175,15 @@
 
     public void renderAdditionalAttributes(IMarkupWriter writer, IRequestCycle cycle)
     {
+        renderIdAttribute(writer, cycle);
+        
         writeEventHandlers(writer, cycle);
-
+        
         // Generate additional attributes from informal parameters.
-
+        
         renderInformalParameters(writer, cycle);
     }
-
+    
     public abstract String getAnchor();
 
     public ILink getLink(IRequestCycle cycle)

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DefaultLinkRenderer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DefaultLinkRenderer.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DefaultLinkRenderer.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DefaultLinkRenderer.java Mon Jul 10 20:05:15 2006
@@ -52,7 +52,7 @@
 
         cycle.setAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME,
                 linkComponent);
-
+        
         boolean hasBody = getHasBody();
 
         boolean disabled = linkComponent.isDisabled() || cycle.isRewinding();
@@ -77,32 +77,30 @@
             // Allow the wrapped components a chance to render.
             // Along the way, they may interact with this component
             // and cause the name variable to get set.
-
+            
             wrappedWriter = writer.getNestedWriter();
-        }
-        else 
+        } else 
             wrappedWriter = writer;
-
-        if (hasBody) linkComponent.renderBody(wrappedWriter, cycle);
-
-        if (!disabled)
-        {
+        
+        if (hasBody) 
+            linkComponent.renderBody(wrappedWriter, cycle);
+        
+        if (!disabled) {
+            
             afterBodyRender(writer, cycle, linkComponent);
             
             linkComponent.renderAdditionalAttributes(writer, cycle);
             
-            if (hasBody)
-            {
+            if (hasBody) {
                 wrappedWriter.close();
                 
                 // Close the <element> tag
                 
                 writer.end();
-            }
-            else 
+            } else 
                 writer.closeTag();
         }
-
+        
         cycle.removeAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME);
     }
 
@@ -116,12 +114,12 @@
     protected String constructURL(ILinkComponent component, IRequestCycle cycle)
     {
         ILink link = component.getLink(cycle);
-
+        
         String scheme = component.getScheme();
         Integer port = component.getPort();
         int portI = (port == null) ? 0 : port.intValue();
         String anchor = component.getAnchor();
-
+        
         return link.getURL(scheme, null, portI, anchor, true);
     }
 

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLink.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLink.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLink.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLink.java Mon Jul 10 20:05:15 2006
@@ -41,9 +41,9 @@
      * Returns true if the stateful parameter is bound to a true value. If stateful is not bound,
      * also returns the default, true.
      */
-
+    
     public abstract boolean isStateful();
-
+    
     public ILink getLink(IRequestCycle cycle)
     {
         Object[] serviceParameters = constructServiceParameters(getParameters());
@@ -52,7 +52,7 @@
         
         return getEngine().getLink(isStateful(), dsp);
     }
-
+    
     /**
      * Converts a service parameters value to an array of objects. This is used by the
      * {@link DirectLink},{@link ServiceLink}and {@link ExternalLink}components.
@@ -101,7 +101,7 @@
 
         if (listener == null)
             throw Tapestry.createRequiredParameterException(this, "listener");
-
+        
         getListenerInvoker().invokeListener(listener, this, cycle);
     }
 

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLink.jwc
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLink.jwc?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLink.jwc (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLink.jwc Mon Jul 10 20:05:15 2006
@@ -36,7 +36,7 @@
         or method).
     </description>
   </parameter>
-     
+  
   <parameter name="stateful" default-value="true"/>
   
   <parameter name="disabled"/>
@@ -63,6 +63,13 @@
     </description>
   </parameter>  
   
+  <parameter name="updateComponents" />
+  
+  <parameter name="json" default-value="false" />
+  
+  <parameter name="async" default-value="false" />
+  
   <inject property="listenerInvoker" object="infrastructure:listenerInvoker"/>
   <inject object="service:tapestry.services.Direct" property="engine"/>
+  
 </component-specification>

Added: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLinkWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLinkWorker.java?rev=420685&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLinkWorker.java (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLinkWorker.java Mon Jul 10 20:05:15 2006
@@ -0,0 +1,131 @@
+// Copyright Jul 9, 2006 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.tapestry.link;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hivemind.ClassResolver;
+import org.apache.hivemind.util.ClasspathResource;
+import org.apache.hivemind.util.Defense;
+import org.apache.tapestry.IComponent;
+import org.apache.tapestry.IDirect;
+import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.PageRenderSupport;
+import org.apache.tapestry.TapestryUtils;
+import org.apache.tapestry.components.ILinkComponent;
+import org.apache.tapestry.engine.IScriptSource;
+import org.apache.tapestry.html.Body;
+import org.apache.tapestry.services.ComponentRenderWorker;
+
+
+/**
+ * Manages connecting {@link IDirect} components that also implement
+ * the {@link ILinkComponent} interface to JavaScript asynchronous IO operations
+ * when any of the shared parameters of {@link IDirect} are specified that relate
+ * to asynchronous operations.
+ * 
+ * @author jkuhnert
+ */
+public class DirectLinkWorker implements ComponentRenderWorker
+{
+    // Parses/manages script template
+    private IScriptSource _scriptSource;
+    
+    // Used to resolve classpath relative resources
+    private ClasspathResource _script;
+    
+    // Class resolver
+    private ClassResolver _resolver;
+    
+    // The path to the javascript template we will use to connect links to IO operations
+    private String _scriptPath;
+    
+    /**
+     * Default constructor, does nothing.
+     */
+    public DirectLinkWorker()
+    {
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void renderComponent(IRequestCycle cycle, IComponent component)
+    {
+        if (cycle.isRewinding())
+            return;
+        
+        // must implement both interfaces
+        if (!ILinkComponent.class.isInstance(component)
+                || !IDirect.class.isInstance(component))
+            return;
+        
+        IDirect direct = (IDirect)component;
+        
+        // check for dynamic parameters
+        if (!direct.isAsync() && !direct.isJson())
+            return;
+        
+        PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, component);
+        
+        if (prs == null)
+            return;
+        
+        Map parms = new HashMap();
+        
+        parms.put("component", component);
+        parms.put("json", Boolean.valueOf(direct.isJson()));
+        
+        // execute script template
+        _scriptSource.getScript(_script).execute(cycle, prs, parms);
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void renderBody(IRequestCycle cycle, Body component)
+    {
+    }
+    
+    /**
+     * Needs to be invoked to initialize resources used. 
+     */
+    public void initialize()
+    {
+        Defense.notNull(_resolver, "Classpath Resolver");
+        Defense.notNull(_scriptPath, "Script path");
+        
+        _script = new ClasspathResource(_resolver, _scriptPath);
+    }
+    
+    public void setScriptSource(IScriptSource source)
+    {
+        _scriptSource = source;
+    }
+    
+    public void setScript(String path)
+    {
+        _scriptPath = path;
+    }
+    
+    /**
+     * Auto-Wire injected.
+     * @param resolver
+     */
+    public void setClassResolver(ClassResolver resolver)
+    {
+        _resolver = resolver;
+    }
+}

Added: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLinkWorker.script
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLinkWorker.script?rev=420685&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLinkWorker.script (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/link/DirectLinkWorker.script Mon Jul 10 20:05:15 2006
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!DOCTYPE script PUBLIC
+  "-//Apache Software Foundation//Tapestry Script Specification 3.0//EN"
+  "http://jakarta.apache.org/tapestry/dtd/Script_3_0.dtd">
+<script>
+<input-symbol key="component" required="yes" />
+<input-symbol key="json" required="yes" />
+    <body>
+        <unique>
+            dojo.require("dojo.event");
+            dojo.require("tapestry.*");
+        </unique>
+    </body>
+    <initialization>
+        dojo.event.connect(dojo.byId("${component.clientId}"), "onclick", function(e){
+            dojo.event.browser.stopEvent(e);
+            
+            var content={beventname:"onClick"};
+            tapestry.event.buildEventProperties(e, content);
+            if (!content["beventtarget.id"]) content["beventtarget.id"]="${component.clientId}";
+            
+            if (typeof e == "undefined" || typeof e.target == "undefined"
+                || typeof e.target["getAttribute"] == "undefined"
+                || !e.target.getAttribute("href")) {
+                dojo.raise("Error, link target not found or invalid " + e);
+                return;    
+            }
+            
+            tapestry.bind(e.target.getAttribute("href"), content, ${json});
+        });
+    </initialization>
+</script>
\ No newline at end of file

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java Mon Jul 10 20:05:15 2006
@@ -50,11 +50,13 @@
     /** Stored in {@link IRequestCycle} with associated forms. */
     public static final String FORM_NAME_LIST = 
         "org.apache.tapestry.services.impl.ComponentEventConnectionFormNames-";
+    
     // holds mapped event listener info
     private ComponentEventInvoker _invoker;
     
     // generates links for scripts
     private IEngineService _eventEngine;
+    
     // handles resolving and loading different component event 
     // connection script types
     private IScriptSource _scriptSource;
@@ -113,6 +115,7 @@
         
         PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, component);
         Resource resource = getScript(component);
+        
         _scriptSource.getScript(resource).execute(cycle, prs, parms);
     }
     
@@ -158,6 +161,7 @@
     void mapFormNames(IRequestCycle cycle, IForm form)
     {
         List names = (List)cycle.getAttribute(FORM_NAME_LIST + form.getId());
+        
         if (names == null) {
             names = new ArrayList();
             cycle.setAttribute(FORM_NAME_LIST + form.getId(), names);
@@ -169,7 +173,9 @@
     void linkDeferredForm(IRequestCycle cycle, IForm form)
     {
         List deferred = (List)_deferredFormConnections.remove(form.getId());
+        
         for (int i=0; i < deferred.size(); i++) {
+            
             Object[] val = (Object[])deferred.get(i);
             
             Map scriptParms = (Map)val[0];
@@ -185,6 +191,7 @@
             // execute script
             PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, component);
             Resource resource = getScript(component);
+            
             _scriptSource.getScript(resource).execute(cycle, prs, scriptParms);
         }
     }
@@ -196,8 +203,10 @@
         
         Iterator it = events.iterator();
         while (it.hasNext()) {
+            
             String event = (String)it.next();
             retval.add(new Object[]{event, formNames});
+            
         }
         
         return (Object[][])retval.toArray(new Object[retval.size()][2]);
@@ -206,14 +215,18 @@
     Resource getScript(IComponent component)
     {
         if (IWidget.class.isInstance(component)) {
+            
             if (_widgetResource == null) 
                 _widgetResource = new ClasspathResource(_resolver, _widgetScript);
+            
             return _widgetResource;
         }
         
         if (Body.class.isInstance(component)) {
+            
             if (_elementResource == null) 
                 _elementResource = new ClasspathResource(_resolver, _elementScript);
+            
             return _elementResource;
         }
         
@@ -246,12 +259,15 @@
     Object[][] filterFormEvents(ComponentEventProperty prop, Map scriptParms, IRequestCycle cycle)
     {
         Set events = prop.getFormEvents();
-        if (events.size() < 1) return new Object[0][0];
+        
+        if (events.size() < 1) 
+            return new Object[0][0];
         
         List retval = new ArrayList();
         
         Iterator it = events.iterator();
         while (it.hasNext()) {
+            
             String event = (String)it.next();
             Iterator lit = prop.getFormEventListeners(event).iterator();
             
@@ -263,6 +279,7 @@
                 
                 // defer connection until form is rendered
                 if (formNames == null) {
+                    
                     deferFormConnection(formId, scriptParms);
                     continue;
                 }
@@ -293,7 +310,9 @@
     void deferFormConnection(String formId, Map scriptParms)
     {
         List deferred = (List)_deferredFormConnections.get(formId);
+        
         if (deferred == null) {
+            
             deferred = new ArrayList();
             _deferredFormConnections.put(formId, deferred);
         }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java Mon Jul 10 20:05:15 2006
@@ -23,7 +23,6 @@
 import org.apache.tapestry.IRequestCycle;
 import org.apache.tapestry.engine.NullWriter;
 import org.apache.tapestry.markup.MarkupWriterSource;
-import org.apache.tapestry.services.ComponentRenderWorker;
 import org.apache.tapestry.services.RequestLocaleManager;
 import org.apache.tapestry.services.ResponseBuilder;
 import org.apache.tapestry.util.ContentType;
@@ -44,8 +43,6 @@
 
     private WebResponse _webResponse;
     
-    private ComponentRenderWorker _renderWorker;
-    
     /** Writer that creates JSON output response. */
     private IMarkupWriter _writer;
     
@@ -70,13 +67,11 @@
      *          Web response for output stream.
      */
     public DefaultResponseBuilder(RequestLocaleManager localeManager, 
-            MarkupWriterSource markupWriterSource,
-            WebResponse webResponse, ComponentRenderWorker renderWorker)
+            MarkupWriterSource markupWriterSource, WebResponse webResponse)
     {
         _localeManager = localeManager;
         _markupWriterSource = markupWriterSource;
         _webResponse = webResponse;
-        _renderWorker = renderWorker;
     }
     
     /**
@@ -135,9 +130,6 @@
             render.render(_writer, cycle);
         else
             render.render(writer, cycle);
-        
-        if (IComponent.class.isInstance(render))
-            _renderWorker.renderComponent(cycle, (IComponent)render);
     }
     
     /** 
@@ -146,7 +138,7 @@
     public void updateComponent(String id)
     {
     }
-
+    
     /** 
      * {@inheritDoc}
      */

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseContributorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseContributorImpl.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseContributorImpl.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DefaultResponseContributorImpl.java Mon Jul 10 20:05:15 2006
@@ -17,7 +17,6 @@
 
 import org.apache.tapestry.IRequestCycle;
 import org.apache.tapestry.markup.MarkupWriterSource;
-import org.apache.tapestry.services.ComponentRenderWorker;
 import org.apache.tapestry.services.RequestLocaleManager;
 import org.apache.tapestry.services.ResponseBuilder;
 import org.apache.tapestry.services.ResponseContributor;
@@ -37,16 +36,13 @@
 
     protected WebResponse _webResponse;
     
-    private ComponentRenderWorker _renderWorker;
-    
     /**
      * {@inheritDoc}
      */
     public ResponseBuilder createBuilder(IRequestCycle cycle)
     throws IOException
     {
-        return new DefaultResponseBuilder(_localeManager, _markupWriterSource,
-                _webResponse, _renderWorker);
+        return new DefaultResponseBuilder(_localeManager, _markupWriterSource, _webResponse);
     }
     
     /**
@@ -70,10 +66,5 @@
     public void setWebResponse(WebResponse webResponse)
     {
         _webResponse = webResponse;
-    }
-    
-    public void setComponentRenderWorker(ComponentRenderWorker renderWorker)
-    {
-        _renderWorker = renderWorker;
     }
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java Mon Jul 10 20:05:15 2006
@@ -237,6 +237,7 @@
     {
         IMarkupWriter writer = getWriter(ResponseBuilder.INCLUDE_SCRIPT, ResponseBuilder.SCRIPT_TYPE);
         
+        // causes asset includes to be loaded dynamically into document head
         writer.printRaw("tapestry.loadScriptFromUrl(\"");
         writer.print(url);
         writer.printRaw("\");");
@@ -254,7 +255,9 @@
         writer.printRaw("\n\nvar " + preloadName + " = new Array();\n");
         writer.printRaw("if (document.images)\n");
         writer.printRaw("{\n");
+        
         writer.printRaw(script);
+        
         writer.printRaw("}\n");
     }
     
@@ -266,11 +269,14 @@
         IMarkupWriter writer = getWriter(ResponseBuilder.INITIALIZATION_SCRIPT, ResponseBuilder.SCRIPT_TYPE);
         
         writer.begin("script");
+        
+        // return is in XML so must escape any potentially non-xml compliant content
         writer.printRaw("\n//<![CDATA[\n");
         
         writer.printRaw(script);
         
         writer.printRaw("\n//]]>\n");
+        
         writer.end();
     }
     
@@ -279,11 +285,13 @@
      */
     public void render(IMarkupWriter writer, IRender render, IRequestCycle cycle)
     {
+        // must be a valid writer already
         if (NestedMarkupWriterImpl.class.isInstance(writer)) {
             render.render(writer, cycle);
             return;
         }
         
+        // check for page exception renders and write content to writer so client can display them
         if (IPage.class.isInstance(render)) {
             String errorPage = getErrorPage(((IPage)render).getPageName());
             if (errorPage != null) {
@@ -299,6 +307,7 @@
             return;
         }
         
+        // Nothing else found, throw out response
         render.render(NullWriter.getSharedInstance(), cycle);
     }
     
@@ -306,6 +315,7 @@
     {
         for (int i=0; i < _errorPages.size(); i++) {
             String page = (String)_errorPages.get(i);
+            
             if (pageName.indexOf(page) > -1)
                 return page;
         }
@@ -325,6 +335,7 @@
     IMarkupWriter getComponentWriter(IComponent target)
     {
         String id = getComponentId(target);
+        
         return getWriter(id, ELEMENT_TYPE);
     }
     
@@ -337,12 +348,14 @@
         Defense.notNull(id, "id can't be null");
         
         IMarkupWriter w = (IMarkupWriter)_writers.get(id);
-        if (w != null) return w;
+        if (w != null) 
+            return w;
+        
+        // Make component write to a "nested" writer
+        // so that element begin/ends don't conflict
+        // with xml element response begin/ends. This is very
+        // important.
         
-        //Make component write to a "nested" writer
-        //so that element begin/ends don't conflict
-        //with xml element response begin/ends. This is very
-        //important.
         IMarkupWriter nestedWriter = _writer.getNestedWriter();
         nestedWriter.begin("response");
         nestedWriter.attribute("id", id);
@@ -408,7 +421,8 @@
      */
     boolean isScriptWriter(String key)
     {
-        if (key == null) return false;
+        if (key == null) 
+            return false;
         
         if (ResponseBuilder.BODY_SCRIPT.equals(key)
                 || ResponseBuilder.INCLUDE_SCRIPT.equals(key)
@@ -427,8 +441,8 @@
      */
     void parseParameters(IRequestCycle cycle)
     {
-        Object[] updateParts = cycle
-                .getParameters(ServiceConstants.UPDATE_PARTS);
+        Object[] updateParts = cycle.getParameters(ServiceConstants.UPDATE_PARTS);
+        
         if (updateParts == null)
             return;
         
@@ -445,7 +459,9 @@
      */
     boolean contains(IComponent target)
     {
-        if (target == null) return false;
+        if (target == null) 
+            return false;
+        
         return _parts.contains(getComponentId(target));
     }
     

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/LinkFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/LinkFactoryImpl.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/LinkFactoryImpl.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/LinkFactoryImpl.java Mon Jul 10 20:05:15 2006
@@ -44,6 +44,17 @@
  */
 public class LinkFactoryImpl implements LinkFactory
 {
+ 
+    protected URLCodec _codec = new URLCodec();
+    
+    protected String _contextPath;
+    
+    protected PropertyPersistenceStrategySource _persistenceStrategySource;
+    
+    protected IRequestCycle _requestCycle;
+    
+    protected WebRequest _request;
+    
     private DataSqueezer _dataSqueezer;
 
     private ErrorLog _errorLog;
@@ -56,20 +67,11 @@
 
     private ServiceEncoder[] _encoders;
 
-    private String _contextPath;
-
     private String _servletPath;
 
     private final Object[] _empty = new Object[0];
-
-    private URLCodec _codec = new URLCodec();
-
-    private WebRequest _request;
-
-    private IRequestCycle _requestCycle;
-
-    private PropertyPersistenceStrategySource _persistenceStrategySource;
-
+    
+    
     public void initializeService()
     {
         Orderer orderer = new Orderer(_errorLog, "encoder");
@@ -113,8 +115,8 @@
             _persistenceStrategySource.addParametersForPersistentProperties(serviceEncoding, post);
 
         String fullServletPath = _contextPath + serviceEncoding.getServletPath();
-
-        return new EngineServiceLink(_requestCycle, fullServletPath, engine.getOutputEncoding(),
+        
+        return new EngineServiceLink(fullServletPath, engine.getOutputEncoding(),
                 _codec, _request, parameters, stateful);
     }
 
@@ -142,7 +144,7 @@
      * Creates a new service encoding, and allows the encoders to modify it before returning.
      */
 
-    private ServiceEncoding createServiceEncoding(Map parameters)
+    protected ServiceEncoding createServiceEncoding(Map parameters)
     {
         ServiceEncodingImpl result = new ServiceEncodingImpl(_servletPath, parameters);
 

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/test/Creator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/test/Creator.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/test/Creator.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/test/Creator.java Mon Jul 10 20:05:15 2006
@@ -33,7 +33,9 @@
 import org.apache.tapestry.enhance.AbstractPropertyWorker;
 import org.apache.tapestry.enhance.EnhancementOperationImpl;
 import org.apache.tapestry.enhance.EnhancementWorker;
+import org.apache.tapestry.enhance.InjectRenderWorker;
 import org.apache.tapestry.services.ComponentConstructor;
+import org.apache.tapestry.services.ComponentRenderWorker;
 import org.apache.tapestry.spec.ComponentSpecification;
 import org.apache.tapestry.spec.IComponentSpecification;
 import org.apache.tapestry.util.DescribedLocation;
@@ -73,18 +75,26 @@
 
     private final Location _creatorLocation = new DescribedLocation(_creatorResource,
             "Creator Location");
-
+    
+    private final ComponentRenderWorker _renderWorker = new MockComponentRenderWorker();
+    
+    private final InjectRenderWorker _injectRender = new InjectRenderWorker();
+    
     {
+        
+        _injectRender.setRenderWorker(_renderWorker);
+        
         // Overrride AbstractComponent's implementations of
         // these two properties (making them read/write).
 
         _workers.add(new CreatePropertyWorker("messages", _creatorLocation));
         _workers.add(new CreatePropertyWorker("specification", _creatorLocation));
-
+        _workers.add(_injectRender);
+        
         // Implement any abstract properties.
         // Note that we don't bother setting the errorLog property
         // so failures may turn into NPEs.
-
+        
         _workers.add(new AbstractPropertyWorker());
     }
 

Added: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/test/MockComponentRenderWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/test/MockComponentRenderWorker.java?rev=420685&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/test/MockComponentRenderWorker.java (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/test/MockComponentRenderWorker.java Mon Jul 10 20:05:15 2006
@@ -0,0 +1,50 @@
+// Copyright Jul 10, 2006 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.tapestry.test;
+
+import org.apache.tapestry.IComponent;
+import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.html.Body;
+import org.apache.tapestry.services.ComponentRenderWorker;
+
+
+/**
+ * Placeholder class used to allow proper creation of {@link AbstractComponent} classes
+ * that normally rely on it being injected at runtime. Used primarily by {@link Creator}.
+ * 
+ * @author jkuhnert
+ */
+public class MockComponentRenderWorker implements ComponentRenderWorker
+{
+
+    /** Does nothing. */
+    public MockComponentRenderWorker()
+    {
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void renderBody(IRequestCycle cycle, Body component)
+    {
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void renderComponent(IRequestCycle cycle, IComponent component)
+    {
+    }
+
+}

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js Mon Jul 10 20:05:15 2006
@@ -11,30 +11,43 @@
 
 tapestry={
 	
-	version:"4.1",
-	scriptInFlight:false,
-	ScriptFragment:'(?:<script.*?>)((\n|.|\r)*?)(?:<\/script>)',
+	version:"4.1", // tapestry script version
+	scriptInFlight:false, // whether or not javascript is currently being eval'd
+	ScriptFragment:'(?:<script.*?>)((\n|.|\r)*?)(?:<\/script>)', // regexp for script elements
 	
 	/**
 	 * Global XHR bind function for tapestry internals. The 
-	 * error/load functions of this same package are used to handle
+	 * error/load functions defined in this package are used to handle
 	 * load/error of dojo.io.bind.
 	 * 
-	 * @param url The url to bind the request to.
-	 * @param content A properties map of optional extra content to send.
+	 * @param url 
+	 * 			The url to bind the request to.
+	 * @param content 
+	 * 			A properties map of optional extra content to send.
+	 * @param json 
+	 * 			Boolean, optional parameter specifying whether or not to create a json request.
+	 * 			If not specified the default is to use XHR.
 	 */
-	bind:function(url, content){
-		dojo.io.bind({
+	bind:function(url, content, json){
+		var parms = {
 			url:url,
 			content:content,
-            headers:{"dojo-ajax-request":true},
             useCache:true,
             preventCache:true,
             load: (function(){tapestry.load.apply(this, arguments);}),
-            error: (function(){tapestry.error.apply(this, arguments);}),
-            mimetype: "text/xml",
-            encoding: "UTF-8"
-        });
+            error: (function(){tapestry.error.apply(this, arguments);})
+		};
+		
+		// setup content type
+		if (typeof json != "undefined" && json) {
+			parms.mimetype = "text/json";
+		} else {
+			parms.headers={"dojo-ajax-request":true};
+			parms.mimetype="text/xml";
+			parms.encoding="UTF-8";
+		}
+		
+		dojo.io.bind(parms);
 	},
 	
 	/**
@@ -53,6 +66,7 @@
 			dojo.log.err("No data received in response.");
 			return;
 		}
+		
 		var resp=data.getElementsByTagName("ajax-response");
 		if (!resp || resp.length < 1 || !resp[0].childNodes) {
 			dojo.log.warn("No ajax-response elements recieved.");
@@ -88,8 +102,8 @@
 				
 			}
 			
-			if (!id) {
-			dojo.raise("No element id found in ajax-response node.");
+			if (!id){
+				dojo.raise("No element id found in ajax-response node.");
 				return;
 			}
 			

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestLibrary.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestLibrary.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestLibrary.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestLibrary.xml Mon Jul 10 20:05:15 2006
@@ -35,7 +35,7 @@
   	  	  	
   	  <assert-output name="DirectLink with parameters">
 <![CDATA[  	  
-  	  <a href="/junit/mock?component=link&amp;page=Home&amp;service=direct&amp;sp=2&amp;sp=d3.5&amp;sp=SHello">
+  	  <a href="/junit/mock?component=link&amp;page=Home&amp;service=direct&amp;sp=2&amp;sp=d3.5&amp;sp=SHello" id="link">
 ]]>
   	  </assert-output>
   	  	  	
@@ -109,7 +109,7 @@
 	
   	  <assert-output name="PageLink (for library page).">
 <![CDATA[  	  
-  	  <a href="/junit/mock?page=lib%3ADumper&amp;service=page">
+  	  <a href="/junit/mock?page=lib%3ADumper&amp;service=page" id="refresh">
 ]]>
   	  </assert-output>	
 	
@@ -158,7 +158,7 @@
 	
   	  <assert-output name="DirectLink with parameters">
 <![CDATA[  	  
-  	  <a href="/junit/mock?component=link&amp;page=Home&amp;service=direct&amp;session=T&amp;sp=2&amp;sp=d3.5&amp;sp=SHello">
+  	  <a href="/junit/mock?component=link&amp;page=Home&amp;service=direct&amp;session=T&amp;sp=2&amp;sp=d3.5&amp;sp=SHello" id="link">
 ]]>
   	  </assert-output>
   </request>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestLocalization.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestLocalization.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestLocalization.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestLocalization.xml Mon Jul 10 20:05:15 2006
@@ -118,7 +118,7 @@
 		
 		<assert-output name="DirectLink switch URL still stateless">
 <![CDATA[		
-href="/mock/app?component=link&amp;page=Home&amp;service=direct&amp;sp=2&amp;sp=d3.5&amp;sp=SHello"
+href="/mock/app?component=link&amp;page=Home&amp;service=direct&amp;sp=2&amp;sp=d3.5&amp;sp=SHello" id="link"
 ]]>
 		</assert-output>			
 	</request>			

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestOutputEncoding.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestOutputEncoding.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestOutputEncoding.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestOutputEncoding.xml Mon Jul 10 20:05:15 2006
@@ -78,7 +78,7 @@
 
 		<assert-output name="External Link">
 <![CDATA[
-<a href="/c28/latin1?page=Two&amp;service=external&amp;sp=SFran%E7ais">
+<a href="/c28/latin1?page=Two&amp;service=external&amp;sp=SFran%E7ais" id="ExternalLink">
 ]]>
 		</assert-output>
 	</request>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestSimple.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestSimple.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestSimple.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestSimple.xml Mon Jul 10 20:05:15 2006
@@ -74,7 +74,7 @@
   
   	 <assert-output name="Link to page Two">
 <![CDATA[
-	<a href="/junit/simple?page=Two&amp;service=page">to page Two</a>
+	<a href="/junit/simple?page=Two&amp;service=page" id="link">to page Two</a>
 ]]>
   	 </assert-output>
   
@@ -110,7 +110,7 @@
 	
 	<assert-output name="Page Two: DirectLink">
 <![CDATA[
-	DirectLink: <a href="/junit/simple?component=link&amp;page=Two&amp;service=direct">click it</a>
+	DirectLink: <a href="/junit/simple?component=link&amp;page=Two&amp;service=direct" id="link">click it</a>
 ]]>	
 	</assert-output>	
 

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestTemplateEncoding.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestTemplateEncoding.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestTemplateEncoding.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestTemplateEncoding.xml Mon Jul 10 20:05:15 2006
@@ -40,7 +40,7 @@
 
 		<assert-output name="External Link">
 <![CDATA[
-<a href="/c28/app?page=Two&amp;service=external&amp;sp=SFran%C3%A7ais">
+<a href="/c28/app?page=Two&amp;service=external&amp;sp=SFran%C3%A7ais" id="ExternalLink">
 ]]>
 		</assert-output>
 	</request>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestWMLComponents.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestWMLComponents.xml?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestWMLComponents.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/scripts/TestWMLComponents.xml Mon Jul 10 20:05:15 2006
@@ -76,7 +76,7 @@
 
         <assert-output name="ServiceLink component">
             <![CDATA[
-            <go href="/mock/app?service=home"/>
+            <go href="/mock/app?service=home" id="ServiceLink"/>
             ]]>
         </assert-output>
 

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/dojo/form/TestAutocompleter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/dojo/form/TestAutocompleter.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/dojo/form/TestAutocompleter.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/dojo/form/TestAutocompleter.java Mon Jul 10 20:05:15 2006
@@ -14,7 +14,10 @@
 
 package org.apache.tapestry.dojo.form;
 
-import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.checkOrder;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
 import static org.testng.AssertJUnit.assertEquals;
 
 import java.util.Map;
@@ -51,8 +54,8 @@
         StringPropertySelectionModel model = new StringPropertySelectionModel(values);
         ValidatableFieldSupport vfs = newMock(ValidatableFieldSupport.class);
         
-        Autocompleter component = newInstance(Autocompleter.class, new Object[]
-        { "model", model, "validatableFieldSupport", vfs });
+        Autocompleter component = newInstance(Autocompleter.class, 
+                new Object[] { "model", model, "validatableFieldSupport", vfs});
         
         IRequestCycle cycle = newMock(IRequestCycle.class);
         IForm form = newMock(IForm.class);
@@ -145,16 +148,17 @@
         
         IScript script = newMock(IScript.class);
         
-        Autocompleter component = newInstance(Autocompleter.class, new Object[]
-        { "name", "fred", "model", model, 
+        Autocompleter component = newInstance(Autocompleter.class, 
+                new Object[] { 
+            "name", "fred", "model", model, 
             "directService", engine,
             "script", script,
             "validatableFieldSupport", vfs, 
-            "value", values[1] });
+            "value", values[1]
+        });
         
         DirectServiceParameter dsp = 
-            new DirectServiceParameter(component, new Object[]{}, 
-                    new String[]{"fred"}, true);
+            new DirectServiceParameter(component);
         
         trainGetForm(cycle, form);
         trainWasPrerendered(form, writer, component, false);
@@ -217,8 +221,8 @@
     {
         ValidatableFieldSupport support = newMock(ValidatableFieldSupport.class);
         
-        Autocompleter field = newInstance(Autocompleter.class, new Object[]
-        { "validatableFieldSupport", support, });
+        Autocompleter field = newInstance(Autocompleter.class, 
+                new Object[] { "validatableFieldSupport", support, });
         
         expect(support.isRequired(field)).andReturn(true);
         

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/engine/DirectServiceTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/engine/DirectServiceTest.java?rev=420685&r1=420684&r2=420685&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/engine/DirectServiceTest.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/engine/DirectServiceTest.java Mon Jul 10 20:05:15 2006
@@ -14,10 +14,11 @@
 
 package org.apache.tapestry.engine;
 
-import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.*;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertSame;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -44,15 +45,24 @@
 @Test
 public class DirectServiceTest extends ServiceTestCase
 {
-    protected IDirect newDirect()
+    protected IDirect newDirect(boolean checkParameters)
     {
-        return newMock(IDirect.class);
+        IDirect c = newMock(IDirect.class);
+        
+        if (checkParameters) {
+            checkOrder(c, false);
+            expect(c.getUpdateComponents()).andReturn(Collections.EMPTY_LIST);
+            expect(c.isJson()).andReturn(false);
+            expect(c.isAsync()).andReturn(false);
+        }
+        
+        return c;
     }
 
     public void testGetLinkOnSamePage()
     {
         IPage page = newPage("ThePage");
-        IDirect c = newDirect();
+        IDirect c = newDirect(true);
         IRequestCycle cycle = newCycle();
         WebRequest request = newWebRequest(false, null);
         LinkFactory lf = newLinkFactory();
@@ -90,7 +100,7 @@
     public void testGetLinkOnSamePageForPost()
     {
         IPage page = newPage("ThePage");
-        IDirect c = newDirect();
+        IDirect c = newDirect(true);
         IRequestCycle cycle = newCycle();
         WebRequest request = newWebRequest(false, null);
         LinkFactory lf = newLinkFactory();
@@ -126,15 +136,16 @@
     }
 
     public void testGetLinkOnSamePageStateful()
-    {
+    {   
+        IDirect c = newDirect(true);
+        
         IPage page = newPage("ThePage");
-        IDirect c = newDirect();
         IRequestCycle cycle = newCycle();
         WebSession session = newWebSession();
         WebRequest request = newWebRequest(false, session);
         LinkFactory lf = newLinkFactory();
         ILink link = newLink();
-
+        
         trainGetPage(cycle, page);
         trainGetPage(c, page);
         trainGetIdPath(c, "fred.barney");
@@ -153,11 +164,11 @@
         ds.setLinkFactory(lf);
         ds.setRequest(request);
         ds.setRequestCycle(cycle);
-
+        
         trainConstructLink(lf, ds, false, parameters, true, link);
-
+        
         replay();
-
+        
         assertSame(link, ds.getLink(false, new DirectServiceParameter(c, serviceParameters)));
 
         verify();
@@ -167,7 +178,7 @@
     {
         IPage page = newPage("ActivePage");
         IPage componentPage = newPage("ComponentPage");
-        IDirect c = newDirect();
+        IDirect c = newDirect(true);
         IRequestCycle cycle = newCycle();
         WebRequest request = newWebRequest(false, null);
         LinkFactory lf = newLinkFactory();
@@ -206,7 +217,7 @@
         Object[] parameters = new Object[0];
         IRequestCycle cycle = newCycle();
         IPage page = newPage();
-        IDirect d = newDirect();
+        IDirect d = newDirect(false);
         LinkFactory lf = newLinkFactory();
         ResponseRenderer rr = newResponseRenderer();
 
@@ -249,7 +260,7 @@
         IRequestCycle cycle = newCycle();
         IPage page = newPage();
         IPage componentPage = newPage();
-        IDirect d = newDirect();
+        IDirect d = newDirect(false);
         LinkFactory lf = newLinkFactory();
         ResponseRenderer rr = newResponseRenderer();
 
@@ -331,7 +342,7 @@
         Object[] parameters = new Object[0];
         IRequestCycle cycle = newCycle();
         IPage page = newPage();
-        IDirect d = newDirect();
+        IDirect d = newDirect(false);
         
         LinkFactory lf = newLinkFactory();
         ResponseRenderer rr = newResponseRenderer();
@@ -382,7 +393,7 @@
     {
         IRequestCycle cycle = newCycle();
         IPage page = newPage();
-        IDirect d = newDirect();
+        IDirect d = newDirect(false);
         
         Location l = newLocation();