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.util.internal.InternalStringBuilder;
022:
023: import org.apache.beehive.netui.tags.ByRef;
024: import org.apache.beehive.netui.tags.HtmlUtils;
025: import org.apache.beehive.netui.tags.IHtmlAccessable;
026: import org.apache.beehive.netui.tags.rendering.*;
027: import org.apache.beehive.netui.util.Bundle;
028:
029: import javax.servlet.ServletRequest;
030: import javax.servlet.jsp.JspException;
031: import java.util.ArrayList;
032:
033: /**
034: * Renders a databound TextBox with the given attributes.
035: * @jsptagref.tagdescription Renders an HTML <input type="text"> tag.
036: * @example In this sample, a <netui:textBox> reads from and writes to the Form Bean's firstname property.
037: * If the submitted text is NULL, the default value is specified by the Page Flow's firstName property.
038: * <pre> <netui:textBox dataSource="actionForm.firstName"
039: * defaultValue="${pageFlow.defaultFirstName}"
040: * size="20" /></pre>
041: * @netui:tag name="textBox" description="Renders a databound TextBox with the given attributes."
042: */
043: public class TextBox extends HtmlDefaultableDataSourceTag implements
044: IFormattable, IHtmlAccessable {
045: private InputTextTag.State _state = new InputTextTag.State();
046:
047: private ArrayList _formatters;
048: private boolean _password = false;
049: private boolean _formatErrors = false;
050:
051: /**
052: * Return the name of the Tag.
053: */
054: public String getTagName() {
055: return "TextBox";
056: }
057:
058: /**
059: * This method will return the state associated with the tag. This is used by this
060: * base class to access the individual state objects created by the tags.
061: * @return a subclass of the <code>AbstractHtmlState</code> class.
062: */
063: protected AbstractHtmlState getState() {
064: return _state;
065: }
066:
067: /**
068: * Base support for the attribute tag. This is overridden to prevent setting the <code>type</code>,
069: * and <code>value</code> attributes.
070: * @param name The name of the attribute. This value may not be null or the empty string.
071: * @param value The value of the attribute. This may contain an expression.
072: * @param facet The name of a facet to which the attribute will be applied. This is optional.
073: * @throws JspException A JspException may be thrown if there is an error setting the attribute.
074: */
075: public void setAttribute(String name, String value, String facet)
076: throws JspException {
077: if (name != null) {
078: if (name.equals(TYPE) || name.equals(VALUE)) {
079: String s = Bundle.getString(
080: "Tags_AttributeMayNotBeSet",
081: new Object[] { name });
082: registerTagError(s, null);
083: } else {
084: if (name.equals(DISABLED)) {
085: setDisabled(Boolean.parseBoolean(value));
086: return;
087: } else if (name.equals(READONLY)) {
088: _state.readonly = new Boolean(value).booleanValue();
089: return;
090: } else if (name.equals(MAXLENGTH)) {
091: _state.maxlength = Integer.parseInt(value);
092: return;
093: } else if (name.equals(SIZE)) {
094: _state.size = Integer.parseInt(value);
095: return;
096: }
097: }
098: }
099:
100: super .setAttribute(name, value, facet);
101: }
102:
103: //******************************** ATTRIBUTES *******************************
104:
105: /**
106: * Set the maximum length (in characters) of the TextBox.
107: * @param maxlength the max length
108: * @jsptagref.attributedescription Integer. The maximum number of character that can be entered in the rendered <input> element.
109: * @jsptagref.databindable Read Only
110: * @jsptagref.attributesyntaxvalue <i>integer_maxLength</i>
111: * @netui:attribute required="false" rtexprvalue="true" type="int"
112: * description="The maximum number of character that can be entered in the rendered <input> element."
113: */
114: public void setMaxlength(int maxlength) {
115: _state.maxlength = maxlength;
116: }
117:
118: /**
119: * Set the password state (true means this is a password field).
120: * @param password the password state
121: * @jsptagref.attributedescription Boolean. Determines whether the password characters that the user enters into the <input> element will be disguised in the browser.
122: * @jsptagref.databindable false
123: * @jsptagref.attributesyntaxvalue <i>boolean_password</i>
124: * @netui:attribute required="false" rtexprvalue="true" type="boolean"
125: * description="Determines whether the password characters that the user enters into the <input> element will be disguised in the browser."
126: */
127: public void setPassword(boolean password) {
128: _password = password;
129: }
130:
131: /**
132: * Get the password state.
133: * @return <code>true</code> if the text box is used for passwords. <code>false</code> otherwise.
134: */
135: protected boolean getPassword() {
136: return _password;
137: }
138:
139: /**
140: * Set if this TextBox is read-only.
141: * @param readonly the read-only state
142: * @jsptagref.attributedescription Boolean. Determines if the rendered <input> element is read-only.
143: * @jsptagref.databindable false
144: * @jsptagref.attributesyntaxvalue <i>boolean_readOnly</i>
145: * @netui:attribute required="false" rtexprvalue="true" type="boolean"
146: * description="Determines if the rendered <input> element is read-only"
147: */
148: public void setReadonly(boolean readonly) {
149: _state.readonly = readonly;
150: }
151:
152: /**
153: * Set the size (in characters) of the TextBox.
154: * @param size the size
155: * @jsptagref.attributedescription Integer. The number of characters visible in the <input> element.
156: * @jsptagref.databindable Read Only
157: * @jsptagref.attributesyntaxvalue <i>integer_size</i>
158: * @netui:attribute required="false" rtexprvalue="true" type="int"
159: * description="The number of characters visible in the <input> element."
160: */
161: public void setSize(int size) {
162: _state.size = size;
163: }
164:
165: /**
166: * Sets the accessKey attribute value. This should key value of the
167: * keyboard navigation key. It is recommended not to use the following
168: * values because there are often used by browsers <code>A, C, E, F, G,
169: * H, V, left arrow, and right arrow</code>.
170: * @param accessKey the accessKey value.
171: * @jsptagref.attributedescription The keyboard navigation key for the element.
172: * The following values are not recommended because they
173: * are often used by browsers: <code>A, C, E, F, G,
174: * H, V, left arrow, and right arrow</code>
175: * @jsptagref.databindable false
176: * @jsptagref.attributesyntaxvalue <i>string_accessKey</i>
177: * @netui:attribute required="false" rtexprvalue="true" type="char"
178: * description="The keyboard navigation key for the element.
179: * The following values are not recommended because they
180: * are often used by browsers: A, C, E, F, G,
181: * H, V, left arrow, and right arrow"
182: */
183: public void setAccessKey(char accessKey) {
184: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
185: ACCESSKEY, Character.toString(accessKey));
186: }
187:
188: /**
189: * Sets the alt attribute value.
190: * @param alt the alt value.
191: * @jsptagref.attributedescription The alt attribute of the element.
192: * @jsptagref.databindable Read Only
193: * @jsptagref.attributesyntaxvalue <i>string_alt</i>
194: * @netui:attribute required="false" rtexprvalue="true"
195: * description="The alt attribute of the element."
196: */
197: public void setAlt(String alt) {
198: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL, ALT,
199: alt);
200: }
201:
202: /**
203: * Sets the tabIndex of the rendered html tag.
204: * @param tabindex the tab index.
205: * @jsptagref.attributedescription The tabIndex of the rendered HTML tag. This attribute determines the position of the
206: * tag in the sequence of page elements that the user may advance through by pressing the TAB key.
207: * @jsptagref.databindable false
208: * @jsptagref.attributesyntaxvalue <i>string_tabIndex</i>
209: * @netui:attribute required="false" rtexprvalue="true" type="int"
210: * description="The tabIndex of the rendered HTML tag. This attribute determines the position of the
211: * tag in the sequence of page elements that the user may advance through by pressing the TAB key."
212: */
213: public void setTabindex(int tabindex) {
214: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
215: TABINDEX, Integer.toString(tabindex));
216: }
217:
218: //*************************************** TAG METHODS *****************************************
219:
220: /**
221: * Prepare the TextBox's formatters.
222: * @throws JspException if a JSP exception has occurred
223: */
224: public int doStartTag() throws JspException {
225: return EVAL_BODY_BUFFERED;
226: }
227:
228: /**
229: * Render the TextBox.
230: * @throws JspException if a JSP exception has occurred
231: */
232: public int doEndTag() throws JspException {
233: ServletRequest req = pageContext.getRequest();
234:
235: // Create an appropriate "input" element based on our parameters
236: if (_password) {
237: _state.type = INPUT_PASSWORD;
238: } else {
239: _state.type = INPUT_TEXT;
240: }
241:
242: // Create the state for the input tag
243: ByRef ref = new ByRef();
244: nameHtmlControl(_state, ref);
245:
246: _state.disabled = isDisabled();
247:
248: // Create the text value of the TextBox
249: Object textObject = evaluateDataSource();
250: if ((textObject == null)
251: || (textObject.toString().length() == 0)) {
252: textObject = _defaultValue;
253: }
254:
255: // Get the text value for the textbox, the result
256: String text = null;
257: if (textObject != null) {
258: text = formatText(textObject);
259: InternalStringBuilder sb = new InternalStringBuilder(text
260: .length() + 16);
261: StringBuilderRenderAppender sbAppend = new StringBuilderRenderAppender(
262: sb);
263: HtmlUtils.filter(text, sbAppend);
264: text = sb.toString();
265: }
266: _state.value = text;
267:
268: // if there were format errors then report them
269: if (_formatErrors) {
270: if (bodyContent != null) {
271: String value = bodyContent.getString().trim();
272: bodyContent.clearBody();
273: write(value);
274: }
275: }
276:
277: if (hasErrors())
278: return reportAndExit(EVAL_PAGE);
279:
280: // create the input tag.
281: WriteRenderAppender writer = new WriteRenderAppender(
282: pageContext);
283: TagRenderingBase br = TagRenderingBase.Factory.getRendering(
284: TagRenderingBase.INPUT_TEXT_TAG, req);
285: assert (br != null);
286:
287: br.doStartTag(writer, _state);
288: br.doEndTag(writer);
289:
290: // write any script that needs to be written
291: if (!ref.isNull())
292: write((String) ref.getRef());
293:
294: localRelease();
295: return EVAL_PAGE;
296: }
297:
298: /**
299: * Release any acquired resources.
300: */
301: protected void localRelease() {
302: super .localRelease();
303:
304: _state.clear();
305:
306: _formatters = null;
307: _password = false;
308: _formatErrors = false;
309: }
310:
311: /**
312: * Adds a FormatTag.Formatter to the TextBox's set of formatters
313: * @param formatter a FormatTag.Formatter added by a child FormatTag.
314: */
315: public void addFormatter(FormatTag.Formatter formatter) {
316: if (_formatters == null)
317: _formatters = new ArrayList();
318:
319: _formatters.add(formatter);
320: }
321:
322: /**
323: * Indicate that a formatter has reported an error so the formatter should output it's
324: * body text.
325: */
326: public void formatterHasError() {
327: _formatErrors = true;
328: }
329:
330: /**
331: */
332: private String formatText(Object text) throws JspException {
333: assert (text != null) : "parameter 'text' must not be null";
334:
335: if (_formatters == null)
336: return text.toString();
337:
338: for (int i = 0; i < _formatters.size(); i++) {
339: FormatTag.Formatter currentFormatter = (FormatTag.Formatter) _formatters
340: .get(i);
341: try {
342: text = currentFormatter.format(text);
343: } catch (JspException e) {
344: registerTagError(e.getMessage(), null);
345: }
346: }
347: return text.toString();
348: }
349: }
|