001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.tags.html;
020:
021: import org.apache.beehive.netui.tags.ByRef;
022: import org.apache.beehive.netui.tags.HtmlUtils;
023: import org.apache.beehive.netui.tags.rendering.AbstractHtmlState;
024: import org.apache.beehive.netui.tags.rendering.TagRenderingBase;
025: import org.apache.beehive.netui.tags.rendering.TextAreaTag;
026: import org.apache.beehive.netui.tags.rendering.WriteRenderAppender;
027:
028: import javax.servlet.ServletRequest;
029: import javax.servlet.jsp.JspException;
030: import java.util.ArrayList;
031:
032: /**
033: * Renders a databound TextArea with the given attributes.
034: * @jsptagref.tagdescription Renders an HTML <textarea> tag.
035: *
036: * <pre> <textarea/></pre>
037: * @example In this sample a text area reads from and writes to the Form Bean's
038: * description property. If the submitted value is NULL the default value is specified
039: * by the Page Flow's
040: * defaultDescription property.
041: * <pre> <netui:textArea dataSource="actionForm.description"
042: * defaultValue="${pageFlow.defaultDescription}"
043: * cols="25" rows="3" /></pre>
044: * @netui:tag name="textArea" description="Renders a databound TextArea with the given attributes."
045: */
046: public class TextArea extends HtmlDefaultableDataSourceTag implements
047: IFormattable {
048: private TextAreaTag.State _state = new TextAreaTag.State();
049:
050: private ArrayList _formatters = null;
051: private boolean _formatErrors = false;
052:
053: /**
054: * Return the name of the Tag.
055: */
056: public String getTagName() {
057: return "TextArea";
058: }
059:
060: /**
061: * This method will return the state associated with the tag. This is used by this
062: * base class to access the individual state objects created by the tags.
063: * @return a subclass of the <code>AbstractHtmlState</code> class.
064: */
065: protected AbstractHtmlState getState() {
066: return _state;
067: }
068:
069: /**
070: * Base support for the attribute tag.
071: * @param name The name of the attribute. This value may not be null or the empty string.
072: * @param value The value of the attribute. This may contain an expression.
073: * @param facet The name of a facet to which the attribute will be applied. This is optional.
074: * @throws JspException A JspException may be thrown if there is an error setting the attribute.
075: */
076: public void setAttribute(String name, String value, String facet)
077: throws JspException {
078: if (name != null) {
079: if (name.equals(DISABLED)) {
080: setDisabled(Boolean.parseBoolean(value));
081: return;
082: } else if (name.equals(READONLY)) {
083: _state.readonly = new Boolean(value).booleanValue();
084: return;
085: } else if (name.equals(COLS)) {
086: _state.cols = Integer.parseInt(value);
087: return;
088: } else if (name.equals(ROWS)) {
089: _state.rows = Integer.parseInt(value);
090: return;
091: }
092: }
093:
094: super .setAttribute(name, value, facet);
095: }
096:
097: /**
098: * Sets the number of columns in the TextArea.
099: * @param cols the number of columns
100: * @jsptagref.attributedescription Integer. The number of columns in the <netui:textArea>.
101: * @jsptagref.databindable Read Only
102: * @jsptagref.attributesyntaxvalue <i>integer_columns</i>
103: * @netui:attribute required="false" rtexprvalue="true" type="int"
104: * description="The number of columns in the <netui:textArea>."
105: */
106: public void setCols(int cols) {
107: _state.cols = cols;
108: }
109:
110: /**
111: * Set if this TextArea is read-only.
112: * @param readonly the read-only state
113: * @jsptagref.attributedescription Boolean. Determines whether text can be entered in the <netui:textArea> or not.
114: * @jsptagref.databindable false
115: * @jsptagref.attributesyntaxvalue <i>boolean_disabled</i>
116: * @netui:attribute required="false" rtexprvalue="true" type="boolean"
117: * description="Determines whether text can be entered in the <netui:textArea> or not."
118: */
119: public void setReadonly(boolean readonly) {
120: _state.readonly = readonly;
121: }
122:
123: /**
124: * Sets the number of rows in the TextArea.
125: * @param rows the number of rows
126: * @jsptagref.attributedescription The number of rows in the <netui:textArea>
127: * @jsptagref.databindable Read Only
128: * @jsptagref.attributesyntaxvalue <i>integer_rows</i>
129: * @netui:attribute required="false" rtexprvalue="true" type="int"
130: * description="The number of rows in the <netui:textArea>"
131: */
132: public void setRows(int rows) {
133: _state.rows = rows;
134: }
135:
136: /**
137: * Prepare the TextArea's formatters.
138: * @throws JspException if a JSP exception has occurred
139: */
140: public int doStartTag() throws JspException {
141: return EVAL_BODY_BUFFERED;
142: }
143:
144: /**
145: * Render the TextArea.
146: * @throws JspException if a JSP exception has occurred
147: */
148: public int doEndTag() throws JspException {
149: ServletRequest req = pageContext.getRequest();
150: Object textObject = null;
151:
152: // Get the value of the data source. The object will not be null.
153: Object val = evaluateDataSource();
154: textObject = (val != null) ? val : "";
155: assert (textObject != null);
156:
157: // setup the rest of the state.
158: ByRef ref = new ByRef();
159: nameHtmlControl(_state, ref);
160:
161: _state.disabled = isDisabled();
162:
163: // if there were expression errors report them
164: if (hasErrors())
165: return reportAndExit(EVAL_PAGE);
166:
167: // if there were format errors then report them
168: if (_formatErrors) {
169: if (bodyContent != null) {
170: String value = bodyContent.getString().trim();
171: bodyContent.clearBody();
172: write(value);
173: }
174: }
175:
176: // create the input tag.
177: WriteRenderAppender writer = new WriteRenderAppender(
178: pageContext);
179: TagRenderingBase br = TagRenderingBase.Factory.getRendering(
180: TagRenderingBase.TEXT_AREA_TAG, req);
181: br.doStartTag(writer, _state);
182:
183: // create the text value which will be found inside the textarea.
184: if ((textObject == null)
185: || (textObject.toString().length() == 0)) {
186: textObject = _defaultValue;
187: }
188:
189: String text = formatText(textObject);
190: if (text != null) {
191: // make sure leading blank line in the text value is not interpreted
192: // just as formatting... force a new line for formatting
193: if (text.startsWith("\n") || text.startsWith("\r")) {
194: writer.append("\n");
195: }
196: HtmlUtils.filter(text, writer);
197: }
198:
199: //results.append(text);
200: br.doEndTag(writer);
201:
202: // if there are errors report them...
203: if (hasErrors())
204: return reportAndExit(EVAL_PAGE);
205:
206: // report any script
207: if (!ref.isNull())
208: write((String) ref.getRef());
209:
210: localRelease();
211: return EVAL_PAGE;
212: }
213:
214: /**
215: * Release any acquired resources.
216: */
217: protected void localRelease() {
218: super .localRelease();
219:
220: _state.clear();
221: _formatters = null;
222: _formatErrors = false;
223: }
224:
225: /**
226: * Adds a FormatTag.Formatter to the TextArea's set of formatters
227: * @param formatter a FormatTag.Formatter added by a child FormatTag.
228: */
229: public void addFormatter(FormatTag.Formatter formatter) {
230: if (_formatters == null)
231: _formatters = new ArrayList();
232:
233: _formatters.add(formatter);
234: }
235:
236: /**
237: * Indicate that a formatter has reported an error so the formatter should output it's
238: * body text.
239: */
240: public void formatterHasError() {
241: _formatErrors = true;
242: }
243:
244: /**
245: */
246: private String formatText(Object text) throws JspException {
247: if (text == null)
248: return null;
249: if (_formatters == null)
250: return text.toString();
251:
252: for (int i = 0; i < _formatters.size(); i++) {
253: FormatTag.Formatter currentFormatter = (FormatTag.Formatter) _formatters
254: .get(i);
255: try {
256: text = currentFormatter.format(text);
257: } catch (JspException e) {
258: registerTagError(e.getMessage(), null);
259: }
260: }
261: return text.toString();
262: }
263:
264: /* ==================================================================
265: *
266: * This tag's publically exposed HTML, CSS, and JavaScript attributes
267: *
268: * ==================================================================
269: */
270:
271: /**
272: * Sets the accessKey attribute value. This should key value of the
273: * keyboard navigation key. It is recommended not to use the following
274: * values because there are often used by browsers <code>A, C, E, F, G,
275: * H, V, left arrow, and right arrow</code>.
276: * @param accessKey the accessKey value.
277: * @jsptagref.attributedescription The keyboard navigation key for the element.
278: * The following values are not recommended because they
279: * are often used by browsers: <code>A, C, E, F, G,
280: * H, V, left arrow, and right arrow</code>
281: * @jsptagref.databindable false
282: * @jsptagref.attributesyntaxvalue <i>string_accessKey</i>
283: * @netui:attribute required="false" rtexprvalue="true" type="char"
284: * description="The keyboard navigation key for the element.
285: * The following values are not recommended because they
286: * are often used by browsers: A, C, E, F, G,
287: * H, V, left arrow, and right arrow"
288: */
289: public void setAccessKey(char accessKey) {
290: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
291: "accesskey", Character.toString(accessKey));
292: }
293:
294: /**
295: * Sets the tabIndex of the rendered html tag.
296: * @param tabindex the tab index.
297: * @jsptagref.attributedescription The tabIndex of the rendered HTML tag. This attribute determines the position of the
298: * tag in the sequence of page elements that the user may advance through by pressing the TAB key.
299: * @jsptagref.databindable false
300: * @jsptagref.attributesyntaxvalue <i>string_tabIndex</i>
301: * @netui:attribute required="false" rtexprvalue="true" type="int"
302: * description="The tabIndex of the rendered HTML tag. This attribute determines the position of the
303: * tag in the sequence of page elements that the user may advance through by pressing the TAB key."
304: */
305: public void setTabindex(int tabindex) {
306: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
307: TABINDEX, Integer.toString(tabindex));
308: }
309: }
|