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.HtmlUtils;
022: import org.apache.beehive.netui.tags.rendering.AbstractHtmlState;
023: import org.apache.beehive.netui.tags.rendering.SpanTag;
024: import org.apache.beehive.netui.tags.rendering.TagRenderingBase;
025: import org.apache.beehive.netui.tags.rendering.WriteRenderAppender;
026: import org.apache.beehive.netui.util.Bundle;
027: import org.apache.beehive.netui.util.logging.Logger;
028:
029: import javax.servlet.ServletRequest;
030: import javax.servlet.http.HttpServletRequest;
031: import javax.servlet.jsp.JspException;
032:
033: /**
034: * Generates styled text span based on an expression or literal value.
035: *
036: * <p>If the resulting value to be output is the <nobr>" "</nobr> String, it will output as
037: * the value <nobr><code>"&nbsp;"</code></nobr>.</p>
038: * @jsptagref.tagdescription <p>Generates styled text based on a String literal or data binding expression.
039: *
040: * <p>The <netui:span> tag is similar to the {@link Content} tag,
041: * except with respect to the way that it treats
042: * characters sensitive to HTML browsers.
043: * The <netui:span> tag filters the input string for browser-sensitive characters
044: * and replaces these characters
045: * with the corresponding entity strings. For example, if you pass the
046: * string '&amp;' to a <netui:span> tag, the string '&amp;amp;' will be written to
047: * the HTML source file, and the following will be displayed
048: * in the browser: '&amp;'.
049: *
050: * <p>The following table shows how the <netui:span> and <netui:content> tags treat HTML-sensitive characters.
051: * <blockquote>
052: * <table border="1">
053: * <tr>
054: * <td width="30%"><b>tag</b></td>
055: * <td width="30%"><b>generated HTML source</b></td>
056: * <td width="30%"><b>displayed in browser</b></td>
057: * </tr>
058: * <tr>
059: * <td><netui:content value="&amp;"/></td>
060: * <td>&amp;</td>
061: * <td>&</td>
062: * </tr>
063: * <tr>
064: * <td><netui:span value="&amp;"/></td>
065: * <td>&amp;amp;</td>
066: * <td>&amp;</td>
067: * </tr>
068: * </table>
069: * </blockquote>
070: *
071: * <p><b>Note:</b> escaping is <i>not</i> applied to browser-sensitive characters in
072: * the <code>defaultValue</code> attribute.
073: * @example In this first sample, a <netui:span> tag displays the Form Bean's firstName property.
074: * The <netui:span> tag will resolve this data binding expression, and display its value.
075: *
076: * <pre> <netui:span value="${actionForm.firstName}" /></pre>
077: *
078: * <p>In this next sample, the <code>value</code> attribute will resolve to null.
079: * This causes the <code>defaultValue</code> to be displayed. The user will see ' '.</p>
080: * <pre> <netui:span value="${pageFlow.somethingNull}" defaultValue="&nbsp;"/></pre>
081: *
082: * <p>In this next sample, the HTML will contain the text "&amp;nbsp;" and the user will
083: * see '&nbsp;'</p>
084: * <pre> <netui:span value="${pageFlow.somethingNull}" defaultValue="&amp;nbsp;"/></pre>
085: * @netui:tag name="span" description="Places formatted or dynamically generated text on the page inside an HTML span."
086: */
087: public class Span extends LabelBase implements IFormattable {
088: private static final Logger logger = Logger.getInstance(Span.class);
089:
090: private SpanTag.State _state = new SpanTag.State();
091:
092: /**
093: * Return the name of the Tag.
094: */
095: public String getTagName() {
096: return "Label";
097: }
098:
099: /**
100: * This method will return the state associated with the tag. This is used by this
101: * base class to access the individual state objects created by the tags.
102: * @return a subclass of the <code>AbstractHtmlState</code> class.
103: */
104: protected AbstractHtmlState getState() {
105: return _state;
106: }
107:
108: /**
109: * Prepare the label formatters.
110: * @throws JspException if a JSP exception has occurred
111: */
112: public int doStartTag() throws JspException {
113: return EVAL_BODY_BUFFERED;
114: }
115:
116: /**
117: * Render the label.
118: * @throws JspException if a JSP exception has occurred
119: */
120: public int doEndTag() throws JspException {
121: boolean usingDefault = false;
122: boolean bypassEscape = false;
123:
124: String scriptId = null;
125: ServletRequest req = pageContext.getRequest();
126:
127: Object labelObject = null;
128:
129: // if this is not client side binding, evalute the value
130: if (_value != null)
131: labelObject = _value;
132: else {
133: if (_defaultValue != null) {
134: labelObject = _defaultValue;
135: bypassEscape = HtmlUtils.containsEntity(_defaultValue
136: .toString());
137: } else {
138: logger.warn(Bundle.getString(
139: "Tags_LabelExpressionNull", _value));
140: labelObject = DEFAULT_NULL_TEXT;
141: }
142: usingDefault = true;
143: }
144:
145: // we assume that tagId will over have override id if both
146: // are defined.
147: if (_state.id != null) {
148: scriptId = renderNameAndId((HttpServletRequest) req,
149: _state, null);
150: }
151:
152: // push the evaluated expression when we are not client side bound...
153: String labelValue = (usingDefault && !_formatDefaultValue) ? labelObject
154: .toString()
155: : formatText(labelObject);
156:
157: // if there were errors in the formatters, report them.
158: if (_formatterErrors) {
159: if (bodyContent != null) {
160: String value = bodyContent.getString().trim();
161: bodyContent.clearBody();
162: write(value);
163: }
164: }
165:
166: if (hasErrors())
167: return reportAndExit(EVAL_PAGE);
168:
169: WriteRenderAppender writer = new WriteRenderAppender(
170: pageContext);
171: TagRenderingBase br = TagRenderingBase.Factory.getRendering(
172: TagRenderingBase.SPAN_TAG, req);
173: br.doStartTag(writer, _state);
174:
175: if (!bypassEscape)
176: filter(labelValue, writer, _escapeWhiteSpace);
177: else
178: write(labelValue);
179:
180: br.doEndTag(writer);
181:
182: if (scriptId != null)
183: write(scriptId);
184:
185: localRelease();
186: return EVAL_PAGE;
187: }
188:
189: /**
190: * Release any acquired resources.
191: */
192: protected void localRelease() {
193: super.localRelease();
194: _state.clear();
195: }
196: }
|