001// Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 
002// The Molly framework is freely distributable under the terms of an
003// MIT-style license. For details, see the molly pages web site at:
004// http://www.mollypages.org/. Use, modify, have fun !
005
006package fc.web.forms;
007
008import javax.servlet.*;
009import javax.servlet.http.*;
010import java.io.*;
011import java.util.*;
012import java.util.regex.*;
013
014import fc.jdbc.*;
015import fc.io.*;
016import fc.util.*;
017
018/**
019A HTML TextArea
020*/
021public final class TextArea extends AbstractText
022{
023private WrapType wrap;
024private int    rows = 0;
025private int    cols = 0;
026//private String   classname = getClass().getName();
027
028/** 
029Creates a new textarea element with a initial value of "" (the
030empty string). No initial rows/cols are specified which will have
031the effect of rendering this field with the browsers default.
032**/
033public TextArea(String name)
034  {
035  this(name, "", 0, 0);
036  }
037
038/** 
039Creates a new textarea element with a initial value of "" and
040the specified rows/cols.
041**/
042public TextArea(String name, int rows, int cols)
043  {
044  this(name, "", rows, cols);
045  }
046  
047/**
048Creates a new text element with the specified initial value.
049If the specified value is <tt>null</tt>, then the initial
050value is set to "" (the empty string)
051**/
052public TextArea(String name, String value)
053  {
054  this(name, value, 0, 0);
055  }
056
057/**
058Creates a new text element with the specified initial value
059and rows/cols.
060**/
061public TextArea(String name, String value, int rows, int cols)
062  {
063  super(name, value);
064  this.rows = rows;
065  this.cols = cols;
066  }
067
068public Field.Type getType() {
069  return Field.Type.TEXTAREA;
070  }
071  
072public void renderImpl(FormData fd, Writer writer) throws IOException 
073  {
074  String value = getRenderValue(fd);
075  
076  writer.write("<textarea ");
077
078  if (! enabled || ! isEnabled(fd)) {
079    writer.write(" disabled");
080    }
081  
082  writer.write(" name='");
083  writer.write(name);
084  writer.write("'");
085
086  if (rows > 0) {
087    writer.write(" rows='");
088    
089    // this is tricky, Writer != PrintWriter
090    // and a int value will be treated as a character code
091    // so writer.write(10) will write a newline, not '10'
092    // writer.write(rows);  
093    writer.write(String.valueOf(rows));
094    writer.write("'"); 
095    }
096  
097  if (cols > 0) {
098    writer.write(" cols='");
099    writer.write(String.valueOf(cols));
100    writer.write("'"); 
101    }
102
103  if (wrap != null) {
104    writer.write(" wrap='");
105    writer.write(wrap.type);
106    writer.write("'"); 
107    }
108      
109  if (renderStyleTag) {
110    writer.write(" style='");
111    writer.write(styleTag);
112    writer.write("'");
113    }
114    
115  final int arlen = arbitraryString.size();
116  for (int n = 0; n < arlen; n++) {
117    writer.write(" ");
118    writer.write(arbitraryString.get(n).toString());
119    }
120
121  writer.write(">");
122  writer.write(sanitizedValue(value));
123  writer.write("</textarea>");
124  }
125        
126  
127/** 
128This value (if set) is rendered as the html <tt>COLS</tt> tag.
129
130@return this object for method chaining convenience
131**/
132public TextArea setCols(int cols) {
133  this.cols = cols;
134  return this;
135  } 
136      
137/** 
138This value (if set) is rendered as the html <tt>ROWS</tt> tag.
139
140@return this object for method chaining convenience
141**/
142public TextArea setRows(int rows) {
143  this.rows = rows;
144  return this;
145  } 
146
147/** 
148Sets the wrapping mode of this text box. This value (if set) is
149rendered as the html <tt>WRAP</tt> tag. By default the wrap
150value is not set (and hence not rendered).
151
152@return this object for method chaining convenience
153**/
154public TextArea setWrap(WrapType wrap) {
155  this.wrap = wrap;
156  return this;
157  }
158
159//we need to sanitize our value since if we set to "</textarea>"
160//the browser will think the value indicates the end of the
161//textarea
162static final Pattern pat = Pattern.compile("(?i)</textarea>");
163private String sanitizedValue(String value) 
164  {
165  if ( value == null || value.equals("") ) {
166    return "";     
167    }
168    
169  Matcher matcher = pat.matcher(value);
170  String newval = matcher.replaceAll("&lt;/textarea&gt;");
171  return newval;
172  }
173    
174/** 
175From the HTML spec:
176<br>
177<ol>
178  <li>OFF disables word wrap. Text the user types is
179  displayed with the exact line breaks that the user types.
180  If the user explicitly inserts a line break, however, the
181  break is included as part of the text area's value. The
182  user has to scroll horizontally to see the ends of lines
183  that do not fit in the text area element.
184  <li>HARD causes word wrap, and the line breaks are
185  included when the form is submitted. The text wraps inside
186  the text area element, and that the user does not need to
187  scroll horizontally.
188  <li>SOFT causes word wrap, but the line breaks are not
189  included when the form is submitted
190</ol>
191**/   
192public static class WrapType {
193  private String type;
194  private WrapType(String type) { this.type = type; }
195    public static final WrapType OFF = new WrapType ("off");
196  public static final WrapType HARD = new WrapType ("hard");
197  public static final WrapType SOFT = new WrapType ("soft");
198  }   
199    
200}          //~class TextArea