View Javadoc

1   /**
2    * This file is part of the equanda project.
3    *
4    * The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
7    *
8    * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
9    * ANY KIND, either express or implied. See the License for the specific language governing rights and
10   * limitations under the License.
11   *
12   * Alternatively, the contents of this file may be used under the terms of
13   * either the GNU General Public License Version 2 or later (the "GPL"), or
14   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
15   * in which case the provisions of the GPL or the LGPL are applicable instead
16   * of those above. If you wish to allow use of your version of this file only
17   * under the terms of either the GPL or the LGPL, and not to allow others to
18   * use your version of this file under the terms of the MPL, indicate your
19   * decision by deleting the provisions above and replace them with the notice
20   * and other provisions required by the GPL or the LGPL. If you do not delete
21   * the provisions above, a recipient may use your version of this file under
22   * the terms of any one of the MPL, the GPL or the LGPL.
23   */
24  
25  package org.equanda.tapestry5.components;
26  
27  import org.apache.tapestry5.*;
28  import org.apache.tapestry5.annotations.Environmental;
29  import org.apache.tapestry5.annotations.IncludeJavaScriptLibrary;
30  import org.apache.tapestry5.annotations.Parameter;
31  import org.apache.tapestry5.corelib.base.AbstractTextField;
32  import org.apache.tapestry5.ioc.annotations.Inject;
33  
34  /**
35   * A variation on the tapestry builtin TextField component. The main difference being that this one can also contain
36   * zone and context parameters. The zone is updated when a value is defined in the text field.
37   * Note that due to limitations in tapestry, the zone contents should not contain form elements.
38   *
39   * @author <a href="mailto:joachim@progs.be">Joachim Van der Auwera</a>
40   */
41  @IncludeJavaScriptLibrary( { "${tapestry.scriptaculous}/prototype.js",
42                               "classpath:/org/equanda/tapestry5/resources/t5equanda.js" } )
43  public class TextField
44      extends AbstractTextField
45  {
46      @Inject
47      private ComponentResources resources;
48  
49      @Environmental
50      private RenderSupport renderSupport;
51  
52      /**
53       * The context for the link (optional parameter). This list of values will be converted into strings and included in
54       * the URI. The strings will be coerced back to whatever their values are and made available to event handler
55       * methods.
56       */
57      @Parameter
58      private Object[] context;
59  
60      /** Binding the zone parameter turns the link into a an Ajax control that causes the related zone to be updated. */
61      @Parameter( defaultPrefix = BindingConstants.LITERAL )
62      private String zone;
63  
64      protected Link createLink( Object[] contextArray )
65      {
66          return resources.createEventLink( "change", contextArray );
67      }
68  
69      @Override
70      protected void writeFieldTag( MarkupWriter writer, String value )
71      {
72          writer.element( "input",
73                          "type", "text",
74                          "name", getControlName(),
75                          "id", getClientId(),
76                          "value", value,
77                          "size", getWidth() );
78      }
79  
80      final void afterRender( MarkupWriter writer )
81      {
82          writer.end(); // input
83          if ( null != zone )
84          {
85              String urlStart = createLink( context ).toAbsoluteURI();
86              String urlEnd = "";
87              int pos = getUrlSplit( urlStart );
88              if ( pos > 0 )
89              {
90                  urlEnd = urlStart.substring( pos );
91                  urlStart = urlStart.substring( 0, pos ) + "/";
92              }
93              renderSupport.addScript( "element = $('%s');\n" +
94                  // Update the element with the id of zone div. This may be changed dynamically on the client side.
95                  "$T(element).zoneId = '%s';\n" +
96                  "element.observe(\"change\", function(event) { eqTfzu( event, '%s/', '%s' ); });\n",
97                  getClientId(), zone, urlStart, urlEnd );
98          }
99      }
100 
101     private int getUrlSplit( String url )
102     {
103         int p1 = url.indexOf( '?' );
104         int p2 = url.indexOf( ';' );
105         if ( -1 == p1 ) return p2;
106         if ( -1 == p2 ) return p1;
107         return p1 < p2 ? p1 : p2;
108     }
109 }