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

svn commit: r596506 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry/corelib/components/ main/java/org/apache/tapestry/corelib/mixins/ main/resources/org/apache/tapestry/ site/ site/apt/ site/apt/guide/ test/app1/ test/ja...

Author: hlship
Date: Mon Nov 19 17:12:28 2007
New Revision: 596506

URL: http://svn.apache.org/viewvc?rev=596506&view=rev
Log:
TAPESTRY-1650: Tracking issue for Ajax support

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/ajax-loader.gif   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/AutocompleteDemo.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/AutocompleteDemo.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/DateField.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/TextArea.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/TextField.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt
    tapestry/tapestry5/trunk/tapestry-core/src/site/site.xml
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/AppModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/MusicLibrary.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/DateField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/DateField.java?rev=596506&r1=596505&r2=596506&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/DateField.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/DateField.java Mon Nov 19 17:12:28 2007
@@ -188,8 +188,6 @@
 
         configure(setup);
 
-        // TODO: protected method to let subclasses provide more setup.
-
         _support.addScript("Calendar.setup(%s);", setup);
     }
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/TextArea.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/TextArea.java?rev=596506&r1=596505&r2=596506&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/TextArea.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/TextArea.java Mon Nov 19 17:12:28 2007
@@ -15,7 +15,6 @@
 package org.apache.tapestry.corelib.components;
 
 import org.apache.tapestry.MarkupWriter;
-import org.apache.tapestry.annotations.AfterRender;
 import org.apache.tapestry.corelib.base.AbstractTextField;
 
 /**
@@ -29,20 +28,22 @@
     @Override
     protected final void writeFieldTag(MarkupWriter writer, String value)
     {
-        writer.element("textarea", "name", getElementName(), "id", getClientId());
+        writer.element("textarea",
+
+                       "name", getElementName(),
+
+                       "id", getClientId());
 
         // Save until needed in after()
 
         _value = value;
     }
 
-    @AfterRender
-    final void after(MarkupWriter writer)
+    final void afterRender(MarkupWriter writer)
     {
         // TextArea will not have a template.
 
-        if (_value != null)
-            writer.write(_value.toString());
+        if (_value != null) writer.write(_value);
 
         writer.end(); // textarea
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/TextField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/TextField.java?rev=596506&r1=596505&r2=596506&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/TextField.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/TextField.java Mon Nov 19 17:12:28 2007
@@ -27,16 +27,15 @@
     @Override
     protected final void writeFieldTag(MarkupWriter writer, String value)
     {
-        writer.element(
-                "input",
-                "type",
-                "text",
-                "name",
-                getElementName(),
-                "id",
-                getClientId(),
-                "value",
-                value);
+        writer.element("input",
+
+                       "type", "text",
+
+                       "name", getElementName(),
+
+                       "id", getClientId(),
+
+                       "value", value);
     }
 
     final void afterRender(MarkupWriter writer)

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java?rev=596506&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java Mon Nov 19 17:12:28 2007
@@ -0,0 +1,195 @@
+package org.apache.tapestry.corelib.mixins;
+
+import org.apache.tapestry.*;
+import org.apache.tapestry.annotations.Environmental;
+import org.apache.tapestry.annotations.InjectContainer;
+import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.annotations.Path;
+import org.apache.tapestry.internal.util.Holder;
+import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.ioc.services.TypeCoercer;
+import org.apache.tapestry.json.JSONArray;
+import org.apache.tapestry.json.JSONObject;
+import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.services.MarkupWriterFactory;
+import org.apache.tapestry.services.Request;
+import org.apache.tapestry.util.TextStreamResponse;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A mixin for a text field that allows for autocompletion of text fields. This is based on Prototype's autocompleter
+ * control.
+ * <p/>
+ * The mixin renders an (initially invisible) progress indicator after the field (it will also be after
+ * the error icon most fields render). The progress indicator is made visible during the request to the server.
+ * The mixin then renders a &lt;div&gt; that will be filled in on the client
+ * side with dynamically obtained selections.
+ * <p/>
+ * Multiple selection on the client is enabled by binding the tokens parameter (however, the mixin doesn't
+ * help split multiple selections up on the server, that is still your code's responsibility).
+ * <p/>
+ * The container is responsible for providing an event handler for event "providecompletions".  The context
+ * will be the partial input string sent from the client.  The return value should be an array or list of
+ * completions, in presentation order.  I.e.
+ * <p/>
+ * <pre>
+ * String[] onProvideCompletionsFromMyField(String input)
+ * {
+ *   return . . .;
+ * }
+ * </pre>
+ */
+public class Autocomplete
+{
+    static final String EVENT_NAME = "autocomplete";
+    private static final String PARAM_NAME = "t:input";
+
+    /**
+     * The field component to which this mixin is attached.
+     */
+    @InjectContainer
+    private Field _field;
+
+    @Inject
+    private ComponentResources _resources;
+
+    @Environmental
+    private PageRenderSupport _pageRenderSupport;
+
+    @Inject
+    private Request _request;
+
+    @Inject
+    private TypeCoercer _coercer;
+
+    @Inject
+    private MarkupWriterFactory _factory;
+
+    @Inject
+    @Path("classpath:org/apache/tapestry/ajax-loader.gif")
+    private Asset _loader;
+
+    /**
+     * Overwrites the default minimum characters to trigger a server round trip (the default is 1).
+     */
+    @Parameter(defaultPrefix = "literal")
+    private int _minChars;
+
+
+    /**
+     * Overrides the default check frequency for determining whether to send a server request.
+     * The default is .4 seconds.
+     */
+    @Parameter(defaultPrefix = "literal")
+    private double _frequency;
+
+    /**
+     * If given, then the autocompleter will support multiple input values, seperated by
+     * any of the individual characters in the string.
+     */
+    @Parameter(defaultPrefix = "literal")
+    private String _tokens;
+
+    /**
+     * Mixin afterRender phrase occurs after the component itself. This is where we write the &lt;div&gt;
+     * element and the JavaScript.
+     *
+     * @param writer
+     */
+    void afterRender(MarkupWriter writer)
+    {
+        String id = _field.getClientId();
+
+        String menuId = id + ":menu";
+        String loaderId = id + ":loader";
+
+        // This image is made visible while the request is being processed.
+        // To be honest, I think Prototype hides it too soon, it should wait
+        // until the <div> is fully positioned and updated.
+
+        writer.element("img",
+
+                       "src", _loader.toClientURL(),
+
+                       "class", "t-invisible",
+
+                       "id", loaderId);
+        writer.end();
+
+        writer.element("div",
+
+                       "id", menuId,
+
+                       "class", "t-autocomplete-menu");
+        writer.end();
+
+        Link link = _resources.createActionLink(EVENT_NAME, false);
+
+
+        JSONObject config = new JSONObject();
+        config.put("paramName", PARAM_NAME);
+        config.put("indicator", loaderId);
+
+        if (_resources.isBound("minChars")) config.put("minChars", _minChars);
+
+        if (_resources.isBound("frequency")) config.put("frequency", _frequency);
+
+        if (_resources.isBound("tokens"))
+        {
+            JSONArray tokens = new JSONArray();
+            for (int i = 0; i < _tokens.length(); i++)
+            {
+                tokens.put(_tokens.substring(i, i + 1));
+            }
+
+            config.put("tokens", tokens);
+        }
+
+        _pageRenderSupport.addScript("new Ajax.Autocompleter('%s', '%s', '%s', %s);", id, menuId, link, config);
+    }
+
+    Object onAutocomplete()
+    {
+        String input = _request.getParameter(PARAM_NAME);
+
+        final Holder<List> matchesHolder = Holder.create();
+
+        // Default it to an empty list.
+
+        matchesHolder.put(Collections.emptyList());
+
+        ComponentEventHandler handler = new ComponentEventHandler()
+        {
+            public boolean handleResult(Object result, Component component, String methodDescription)
+            {
+                List matches = _coercer.coerce(result, List.class);
+
+                matchesHolder.put(matches);
+
+                return true;
+            }
+        };
+
+        _resources.triggerEvent("providecompletions", new Object[]{input}, handler);
+
+        MarkupWriter writer = _factory.newMarkupWriter();
+
+        // T4.1 has more flexibility, it can decorate the options with icons, etc.
+        // But this will do for now.
+
+        writer.element("ul");
+
+        for (Object o : matchesHolder.get())
+        {
+            writer.element("li");
+            writer.write(o.toString());
+            writer.end();
+        }
+
+        writer.end(); // ul
+
+        return new TextStreamResponse("text/html", writer.toString());
+    }
+}

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

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

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css?rev=596506&r1=596505&r2=596506&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/default.css Mon Nov 19 17:12:28 2007
@@ -314,3 +314,26 @@
     padding: none;
 }
 
+DIV.t-autocomplete-menu UL {
+    border: 2px outset #cc9933;
+    background-color: #cc9933;
+    magin-left: 12px;
+    padding: 4px 6px;
+    width: 300px;
+    height: 360px;
+    overflow: auto;
+}
+
+DIV.t-autocomplete-menu LI {
+    color: white;
+    list-style-type: none;
+    padding: 0px;
+    margin: 0px;
+    border-bottom: 1px solid black;
+    cursor: pointer;
+}
+
+DIV.t-autocomplete-menu LI.selected {
+    color: black;
+    font-weight: bold;
+}
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js?rev=596506&r1=596505&r2=596506&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js Mon Nov 19 17:12:28 2007
@@ -369,5 +369,3 @@
         element.removeClassName("t-invisible");
     });
 });
-
- 
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt?rev=596506&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt Mon Nov 19 17:12:28 2007
@@ -0,0 +1,145 @@
+ ---
+ Tapestry Ajax Support
+ ---
+
+Tapestry Ajax Support
+
+  Tapestry includes sophisticated JavaScript and Ajax support, based on the
+  {{{http://www.prototypejs.org/}Prototype}} and
+  {{{http://script.aculo.us/}Scriptaculous}} libraries.  These libraries are
+  all packaged with Tapestry itself ... no extra download required.
+
+  The goal for Tapestry is to have many basic and useful components available within the
+  application itself, and make it easy for other JavaScript widgets to be encapsulated as
+  Tapestry components.
+
+  Ajax support takes the form of new components and, occasionally,
+  {{{mixins.html}component mixins}}.  
+
+Basic JavaScript
+
+  The general strategy in Tapestry is that any significant amount of JavaScript should be packaged up
+  as a static JavaScript library, a .js file that can be downloaded to the client.
+
+  Page specific JavaScript should be in the form of minimal statements to initialize objects, referencing
+  the JavaScript libraries.
+
+  Most of this is accomplished via the
+  {{{../../apidocs/org/apache/tapestry/PageRenderSupport.html}PageRenderSupport}} object.
+
+  PageRenderSupport include a number of methods that will be used by components, or event by
+  services that are called from components.
+
+* addScriptLink()
+
+  <<<void addScriptLink(Asset... scriptAssets);>>>
+
+  This method adds a link to a script file, a JavaScript library.  A component can inject such a script and
+  pass one or more of assets to this method.  Tapestry will ensure that the necessary \<link\> elements
+  are added to the <top> of the document (just inside the \<head\> element).
+
+  Adding the same asset multiple times does <not> create duplicate links.  The subsequent ones are simply
+  ignored.  In this way, each component can add the assets it needs, without worrying about conflicts
+  with other components.
+
+  Note that the Prototype, Scriptaculous and the base Tapestry library (which largely consists of
+  support for form input validation) are included automatically.
+
+* addScript()
+
+  <<<void addScript(String format, Object... arguments);>>>
+
+  This method adds some initialization JavaScript to the page.  By <initialization> we mean that
+  it goes at the bottom of the document, and will only be executed when the document has finished loading
+  on the client (i.e., from the window.onload event handler).
+  
+  When calling the method, the format string can include standard substitutions (such as '%s')
+  for arguments.  This saves you the trouble of calling String.format() yourself.  In any case, the
+  formatting JavaScript is added to the script block.
+
+* Injecting PageRenderSupport
+
+  PageRenderSupport is an <environmental> object, so you will normally inject it via the
+  {{{../../apidocs/org/apache/tapestry/annotations/Environmental.html}Environmental}} annotation:
+
++---+
+  @Environmental
+  private PageRenderSupport _pageRenderSupport;
++---+
+
+  Environmental only works inside components and occasionally a service may want to
+  inject PageRenderSupport.  Fortunately, a proxy of PageRenderSupport has been set up.  The upshot of which
+  is, you may also:
+
++---+
+  @Inject
+  private PageRenderSupport _pageRenderSupport;
++----+
+
+  ... or, in a service implementation constructor:
+
++---+
+  public MyServiceImpl(PageRenderSupport support)
+  {
+    . . .
+  }
++---+
+
+  Inside a component, you should use Environmental, to highlight the fact that PageRenderSupport (like most
+  environmental objects) is only available during rendering, not during action requests.
+
+Autocomplete Mixin
+
+  The
+  {{{../../apidocs/org/apache/tapestry/corelib/mixins/Autocomplete.html}Autocomplete}}
+   mixin exists to allow a text field to query the server for completions for a partially
+  entered phrase.  It is often used in situations where the field exists to select a single value from
+  a large set, too large to succesfully download to the client as a drop down list; for example, when the
+  number of values to select from is numbered in the thousands.
+
+  Autocomplete can be added to an existing text field:
+
++---+
+  <t:textfield t:id="accountName" t:mixins="autocomplete" size="100"/>
++---+
+
+
+  The mixin can be configured in a number of ways, see the
+  {{{../component-parameters.html}component reference}}.
+
+  When the user types into the field, the client-side JavaScript will send a request to the server to
+  get completions.
+
+  You must write an event handler to provide these completions.  The name of the event is "providecompletions".
+  The context is the partial input value, and the return value will be converted into the selections
+  for the user.
+
+  For example:
+
++---+
+  List<String> onProvideCompletionsFromAccountName(String partial)
+  {
+    List<Account> matches = _accountDAO.findByPartialAccountName(partial);
+
+    List<String> result = new ArrayList<String>():
+
+    for (Account a : matches)
+    {
+      result.add(a.getName());
+    }
+
+    return result;
+  }
++---+
+
+  This presumes that <<<findByPartialAccountName()>>> will sort the values, otherwise you will probably
+  want to sort them.  Certainly the Autocomplete mixin does <not> do any sorting.
+
+  You can return an object array, a list, even a single object.  You may return objects instead of strings ... and
+  <<<toString()>>> will be used to convert them into client-side strings.
+
+  Tapestry's default stylesheet includes entries for controlling the look of the floating popup of selections.
+
+  You may override <<<DIV.t-autocomplete-menu UL>>> to change the main look and feel,
+  <<<DIV.t-autocomplete-menu LI>>> for a normal item in the popup list, and
+   <<<DIV.t-autocomplete-menu LI.selected>>> for the element under the cursor (or selecting using the arrow keys).
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt?rev=596506&r1=596505&r2=596506&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt Mon Nov 19 17:12:28 2007
@@ -13,6 +13,9 @@
   Progress on Tapestry 5 is really taking off. This space lists some cool new features that have been added
   recently.
 
+  * We're finally starting to see some Ajax support, beginning with the
+  {{{../apidocs/org/apache/tapestry/corelib/mixins/Autocomplete.html}Autocomplete mixin}}.
+
   * You may now customize how the TextField, PasswordField and TextArea component converts between server side values
     and client side strings, using specialized events.
 
@@ -49,68 +52,7 @@
   * Explicit \<!DOCTYPE\> declarations inside page and component templates will now be forwarded through to the client
     web browser.
     
-  * The mapping from class names to page names (or component types) has been tweaked to remove some redundancy;
-    For example,
-    class org.example.myapp.pages.edit.EditUser will now have the name "edit/User" rather than "edit/EditUser". This
-    results in shorter, clearer, more natural URLs.
-    
-  * The type of component may now be specified in a template using the element name, rather than the
-    t:type attribute (this represents an incompatible change from 5.0.2).
-    
-  * Form validation now runs on the client side (as well as on the server side) with some basic effects,
-    built on {{{http://script.taculo.us}script.taculo.us}}.
-  
-  * The default ExceptionReport page has been improved to show details of the incoming request,
-    to filter out repetitive and unnecessary data, 
-    and to display file content when an exception includes a location.
-  
-  * Action request URLs have been shortened and simplified for the common case. They may also include a query
-    parameter to identify the page's activation context.
-  
-  * {{{component-parameters.html}Component Reference Documentation}}, generated via a Maven plugin, is now available.
-  
-  * The return values for the "after" set of {{{guide/rendering.html}render phase methods}} have changed: all render phase 
-    methods return true (or void) to progress down the default path, and return false to either skip stages or return to earlier 
-    stages. This may break some existing code.
-  
-  * Component event handlers may now return a {{{../apidocs/org/apache/tapestry/StreamResponse.html}StreamResponse}}
-    to directly send a stream to the client web browser (this is intended for components that need to render
-    images, PDF, or other non-page oriented content).
-  
-  * The root URL for an application now renders the application's start page (it used to let the
-    servlet container render the static welcome page, if any). 
-  
-  * Named-based lookups of messages, resources, etc., are all case-insensitive.
-  
-  * Fast, smart, fully customizable Grid component for displaying tabular data.
-  
-  * Validating form components will use the same system as BeanEditForm to determine default validation for fields.
-  
-  * Select component will automatically provide a ValueEncoder and SelectModel when the value parameter is bound to an Enum type.
-  
-  * BeanEditForm component that creates a form and related controls to edit the properties of any JavaBean, automatically.
-    Inspired by {{{http://www.trailsframework.org/}Trails}} and {{{http://beanform.sourceforge.net/}BeanForm}} (both for Tapestry 4).
-  
-  * Case insensitve URLs.  Tapestry no longer cares about the case of the page names and component ids it puts
-    into URLs, and they are now generated in all lower-case for that clean "Web 2.0" look.  And they're 
-    shorter and "prettier", too!
-  
-  * Initial support for {{{guide/appstate.html}application state objects}}.
-  
-  * Input validation messages may now be overridden by providing a particular message key in the containing component's message catalog.
-  
-  * Property expressions may now reference public methods (with no parameters) in addition to traditional property names.
-  
-  * Page templates are now allowed to be stored in the WEB-INF , as well as on the classpath.
-  
-  * Invisible instrumentation, hiding Tapestry components inside ordinary HTML elements (a favorite feature of Tapestry 4), has been added to Tapestry 5.
-  
-  * Component parameter defaults may be computed on the fly.
-
-  * Component parameters may have default values.
-  
-  * The @ComponentClass annotation, seen in the earlier {{{../screencast.html}screencasts}} has been removed.
-  
+ 
 Changes from Tapestry 4 to Tapestry 5
 
   Tapestry 5 represents a significant advance over Tapestry 4.  The goal is to make Tapestry 5

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/site.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/site.xml?rev=596506&r1=596505&r2=596506&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/site.xml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/site.xml Mon Nov 19 17:12:28 2007
@@ -1,20 +1,20 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
-<!-- 
-   Copyright 2006, 2007 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.
--->
-
+<!-- 
+   Copyright 2006, 2007 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.
+-->
+
 <project name="Tapestry Core">
     <bannerLeft>
         <name>Tapestry 5</name>
@@ -61,6 +61,7 @@
             <item name="Input Validation" href="guide/validation.html"/>
             <item name="BeanEditForm Guide" href="guide/beaneditform.html"/>
             <item name="Component Events" href="guide/event.html"/>
+            <item name="Ajax" href="guide/ajax.html"/>
             <item name="Page Lifecycle" href="guide/lifecycle.html"/>
             <item name="Component Mixins" href="guide/mixins.html"/>
             <item name="Localization" href="guide/localization.html"/>

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/AutocompleteDemo.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/AutocompleteDemo.tml?rev=596506&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/AutocompleteDemo.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/AutocompleteDemo.tml Mon Nov 19 17:12:28 2007
@@ -0,0 +1,20 @@
+<t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+    <h1>Autocomplete Mixin Demo</h1>
+
+    <t:form>
+        <t:errors/>
+
+        <div class="t-beaneditor">
+            <div class="t-beaneditor-row">
+                <t:label for="title"/>
+                <t:textfield t:id="title" t:mixins="autocomplete" tokens=",;" size="100"/>
+            </div>
+
+            <div class="t-beaneditor-row">
+                <input type="submit" value="Show Track"/>
+            </div>
+        </div>
+    </t:form>
+
+
+</t:border>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml?rev=596506&r1=596505&r2=596506&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml Mon Nov 19 17:12:28 2007
@@ -277,6 +277,11 @@
                         -- Demo ability to provide toclient and parseclient event handler methods
                     </li>
 
+                    <li>
+                        <t:pagelink page="autocompletedemo">Autocomplete Mixin Demo</t:pagelink>
+                        -- Demo the autocomplete mixin for text fields.
+                    </li>
+
                 </ul>
             </td>
         </tr>

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/AutocompleteDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/AutocompleteDemo.java?rev=596506&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/AutocompleteDemo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/AutocompleteDemo.java Mon Nov 19 17:12:28 2007
@@ -0,0 +1,45 @@
+package org.apache.tapestry.integration.app1.pages;
+
+import org.apache.tapestry.annotations.Persist;
+import org.apache.tapestry.integration.app1.data.Track;
+import org.apache.tapestry.integration.app1.services.MusicLibrary;
+import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
+
+import java.util.Collections;
+import java.util.List;
+
+public class AutocompleteDemo
+{
+    @Inject
+    private MusicLibrary _library;
+
+    @Persist
+    private String _title;
+
+    List onProvideCompletionsFromTitle(String partialTitle) throws Exception
+    {
+        List<Track> matches = _library.findByMatchingTitle(partialTitle);
+
+        List<String> result = CollectionFactory.newList();
+
+        for (Track t : matches)
+            result.add(t.getTitle());
+
+        Collections.sort(result);
+
+        // Thread.sleep(1000);
+
+        return result;
+    }
+
+    public String getTitle()
+    {
+        return _title;
+    }
+
+    public void setTitle(String title)
+    {
+        _title = title;
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/AppModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/AppModule.java?rev=596506&r1=596505&r2=596506&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/AppModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/AppModule.java Mon Nov 19 17:12:28 2007
@@ -18,6 +18,7 @@
 import org.apache.tapestry.ioc.MappedConfiguration;
 import org.apache.tapestry.ioc.OrderedConfiguration;
 import org.apache.tapestry.ioc.annotations.Marker;
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry.services.Request;
 import org.apache.tapestry.services.RequestFilter;
 import org.apache.tapestry.services.RequestHandler;
@@ -56,8 +57,7 @@
     {
         return new RequestFilter()
         {
-            public boolean service(Request request, Response response, RequestHandler handler)
-                    throws IOException
+            public boolean service(Request request, Response response, RequestHandler handler) throws IOException
             {
                 long startTime = System.currentTimeMillis();
 
@@ -77,14 +77,12 @@
 
     public void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration,
 
-                                         @Local
-                                         RequestFilter filter)
+                                         @Local RequestFilter filter)
     {
         configuration.add("Timing", filter);
     }
 
-    public void contributeClasspathAssetAliasManager(
-            MappedConfiguration<String, String> configuration)
+    public void contributeClasspathAssetAliasManager(MappedConfiguration<String, String> configuration)
     {
         configuration.add("app1/", "org/apache/tapestry/integration/app1/");
     }
@@ -100,8 +98,7 @@
         };
     }
 
-    public static void contributeApplicationDefaults(
-            MappedConfiguration<String, String> configuration)
+    public static void contributeApplicationDefaults(MappedConfiguration<String, String> configuration)
     {
         configuration.add("tapestry.supported-locales", "en,fr");
         configuration.add("app.injected-symbol", "Symbol contributed to ApplicationDefaults");
@@ -123,6 +120,20 @@
             public List<Track> getTracks()
             {
                 return tracks;
+            }
+
+            public List<Track> findByMatchingTitle(String title)
+            {
+                String titleLower = title.toLowerCase();
+
+                List<Track> result = CollectionFactory.newList();
+
+                for (Track t : tracks)
+                {
+                    if (t.getTitle().toLowerCase().contains(titleLower)) result.add(t);
+                }
+
+                return result;
             }
         };
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/MusicLibrary.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/MusicLibrary.java?rev=596506&r1=596505&r2=596506&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/MusicLibrary.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/MusicLibrary.java Mon Nov 19 17:12:28 2007
@@ -24,4 +24,13 @@
      * Provides a list of all tracks in an indeterminate order.
      */
     List<Track> getTracks();
+
+    /**
+     * Performs a case-insensitive search, finding all tracks whose title
+     * contains the input string (ignoring case).
+     *
+     * @param title a partial title
+     * @return a list of all matches
+     */
+    List<Track> findByMatchingTitle(String title);
 }