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.IHtmlAccessable;
022: import org.apache.beehive.netui.tags.rendering.*;
023: import org.apache.beehive.netui.util.Bundle;
024:
025: import javax.servlet.ServletRequest;
026: import javax.servlet.http.HttpServletRequest;
027: import javax.servlet.jsp.JspException;
028: import javax.servlet.jsp.tagext.Tag;
029:
030: /**
031: * A radio button whose state is determined by its enclosing RadioButtonGroup.
032: * @jsptagref.tagdescription Generates a single radiobutton option in a group of options.
033: *
034: * <p>The <radioButtonOption> tag must have a parent {@link RadioButtonGroup} tag.
035: * @example In this example, three radiobuttons are generated in the browser.
036: *
037: * <pre> <netui:form action="processData">
038: * <netui:radioButtonGroup dataSource="actionForm.selection">
039: * <netui:radioButtonOption value="value1">Display Text 1</netui:radioButtonOption><br>
040: * <netui:radioButtonOption value="value2">Display Text 2</netui:radioButtonOption><br>
041: * <netui:radioButtonOption value="value3">Display Text 3</netui:radioButtonOption><br>
042: * </netui:radioButtonGroup>
043: * <netui:button value="Submit" />
044: * </netui:form></pre>
045: * @netui:tag name="radioButtonOption" description="A radio button whose state is determined by its enclosing netui:RadioButtonGroup."
046: */
047: public class RadioButtonOption extends HtmlFocusBaseTag implements
048: IHtmlAccessable {
049: private InputBooleanTag.State _state = new InputBooleanTag.State();
050: private SpanTag.State _spanState = new SpanTag.State();
051: private String _text;
052:
053: /**
054: * Return the name of the Tag.
055: */
056: public String getTagName() {
057: return "RadioButtonOption";
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. This is overridden to prevent setting the <code>type</code>
071: * and <code>value</code> attribute.
072: * @param name The name of the attribute
073: * @param value The value of the attribute
074: * @param facet The name of a facet to which the attribute will be applied. This is optional.
075: * @throws JspException A JspException may be thrown if there is an error setting the attribute.
076: */
077: public void setAttribute(String name, String value, String facet)
078: throws JspException {
079: if (name != null) {
080: if (name.equals(TYPE) || name.equals(VALUE)
081: || name.equals(CHECKED)) {
082: String s = Bundle.getString(
083: "Tags_AttributeMayNotBeSet",
084: new Object[] { name });
085: registerTagError(s, null);
086: } else {
087: if (name.equals(DISABLED)) {
088: setDisabled(Boolean.parseBoolean(value));
089: return;
090: }
091: }
092: }
093: if (facet != null && facet.equals("label")) {
094: setStateAttribute(name, value, _spanState);
095: return;
096: }
097: super .setAttribute(name, value, facet);
098: }
099:
100: /**
101: * Set the label style for each contained RadioButtonOption.
102: * The label style here will override a labelStyle at the RadioButtonGroup level.
103: * @param labelStyle the label style
104: * @jsptagref.attributedescription The style of the label for each contained <netui:radioButtonOption> tag.
105: * @jsptagref.databindable false
106: * @jsptagref.attributesyntaxvalue <i>string_labelStyle</i>
107: * @netui:attribute required="false" rtexprvalue="true"
108: * description="The style of the label for each contained <netui:radioButtonOption> tag."
109: */
110: public void setLabelStyle(String labelStyle) {
111: _spanState.style = setNonEmptyValueAttribute(labelStyle);
112: }
113:
114: /**
115: * Set the label style class for each contained RadioButtonOption.
116: * The label style class here will override a labelStyleClass at the RadioButtonGroup level.
117: * @param labelStyleClass the label style
118: * @jsptagref.attributedescription The class of the labels for each contained <netui:radioButtonOption> tag.
119: * @jsptagref.databindable false
120: * @jsptagref.attributesyntaxvalue <i>string_class</i>
121: * @netui:attribute required="false" rtexprvalue="true"
122: * description="The class of the labels for each contained <netui:radioButtonOption> tag."
123: */
124: public void setLabelStyleClass(String labelStyleClass) {
125: _spanState.styleClass = setNonEmptyValueAttribute(labelStyleClass);
126: }
127:
128: /**
129: * Set the value of this RadioButtonOption.
130: * @param value the RadioButtonOption value
131: * @jsptagref.attributedescription A literal or data binding expression.
132: * @jsptagref.databindable Read Only
133: * @jsptagref.attributesyntaxvalue <i>string_or_expression_value</i>
134: * @netui:attribute required="true" rtexprvalue="true" type="java.lang.Object"
135: * description="The value of the option."
136: */
137: public void setValue(Object value) throws JspException {
138: if (value != null)
139: _state.value = value.toString();
140: else
141: _state.value = null;
142: }
143:
144: /**
145: * Process the start of this tag.
146: * @throws JspException if a JSP exception has occurred
147: */
148: public int doStartTag() throws JspException {
149:
150: Tag parentTag = findAncestorWithClass(this ,
151: RadioButtonGroup.class);
152: if (parentTag == null) {
153: String s = Bundle
154: .getString("Tags_RadioButtonOptionNoRadioButtonGroup");
155: registerTagError(s, null);
156: return SKIP_BODY;
157: }
158:
159: RadioButtonGroup parent = (RadioButtonGroup) parentTag;
160: if ((parent.getOptionsDataSource() != null)
161: && !parent.isRepeater()) {
162: String s = Bundle
163: .getString("Tags_RadioOptionParentHasOptionsDataSource");
164: parent.registerTagError(s, null);
165: return SKIP_BODY;
166: }
167:
168: return EVAL_BODY_BUFFERED;
169:
170: }
171:
172: /**
173: * Process the body text of this tag (if any).
174: * @throws JspException if a JSP exception has occurred
175: */
176: public int doAfterBody() throws JspException {
177: String text = bodyContent.getString();
178: if (text != null) {
179: text = text.trim();
180: bodyContent.clearBody();
181: if (text.length() > 0)
182: _text = text;
183: }
184: return SKIP_BODY;
185: }
186:
187: /**
188: * Process the end of this tag.
189: * @throws JspException if a JSP exception has occurred
190: */
191: public int doEndTag() throws JspException {
192: if (hasErrors())
193: return reportAndExit(EVAL_PAGE);
194:
195: ServletRequest req = pageContext.getRequest();
196: ConstantRendering cr = TagRenderingBase.Factory
197: .getConstantRendering(req);
198:
199: // this was verified in doBeginTag
200: RadioButtonGroup parent = (RadioButtonGroup) findAncestorWithClass(
201: this , RadioButtonGroup.class);
202: assert (parent != null);
203: boolean repeat = parent.isRepeater();
204:
205: // Generate an HTML <input type='radio'> element
206: WriteRenderAppender writer = new WriteRenderAppender(
207: pageContext);
208: if (parent.isVertical()) {
209: cr.TR_TD(writer);
210: }
211: _state.type = INPUT_RADIO;
212: _state.name = parent.getQualifiedDataSourceName();
213: if (_state.id != null) {
214: String tagId = _state.id;
215: _state.id = getIdForTagId(_state.id);
216: String script = renderDefaultNameAndId(
217: (HttpServletRequest) req, _state, tagId,
218: _state.name);
219: if (script != null) {
220: write(script);
221: }
222: }
223:
224: // set the checked and disabled states
225: _state.checked = new Boolean(parent.isMatched(_state.value,
226: null)).booleanValue();
227: _state.disabled = isDisabled();
228: if (!_state.disabled)
229: _state.disabled = parent.isDisabled();
230:
231: TagRenderingBase br = TagRenderingBase.Factory.getRendering(
232: TagRenderingBase.INPUT_BOOLEAN_TAG, req);
233: br.doStartTag(writer, _state);
234:
235: // if this is in a repeater, then we only output the <input tag>
236: if (repeat) {
237: localRelease();
238: return EVAL_PAGE;
239: }
240:
241: if (_spanState.style == null) {
242: _spanState.style = parent.getLabelStyle();
243: }
244: if (_spanState.styleClass == null) {
245: _spanState.styleClass = parent.getLabelStyleClass();
246: }
247:
248: TagRenderingBase spanTag = TagRenderingBase.Factory
249: .getRendering(TagRenderingBase.SPAN_TAG, req);
250: spanTag.doStartTag(writer, _spanState);
251: if (_text == null)
252: write(_state.value);
253: else
254: write(_text);
255: spanTag.doEndTag(writer);
256:
257: if (parent.isVertical()) {
258: cr.end_TD_TR(writer);
259: }
260:
261: // Continue evaluating this page
262: localRelease();
263: return EVAL_PAGE;
264:
265: }
266:
267: /**
268: * Release any acquired resources.
269: */
270: protected void localRelease() {
271: super .localRelease();
272:
273: _state.clear();
274: _spanState.clear();
275:
276: _text = null;
277: }
278:
279: /* ==================================================================
280: *
281: * This tag's publically exposed HTML, CSS, and JavaScript attributes
282: *
283: * ==================================================================
284: */
285: /**
286: * Sets the accessKey attribute value. This should key value of the
287: * keyboard navigation key. It is recommended not to use the following
288: * values because there are often used by browsers <code>A, C, E, F, G,
289: * H, V, left arrow, and right arrow</code>.
290: * @param accessKey the accessKey value.
291: * @jsptagref.attributedescription The keyboard navigation key for the element.
292: * The following values are not recommended because they
293: * are often used by browsers: <code>A, C, E, F, G,
294: * H, V, left arrow, and right arrow</code>
295: * @jsptagref.databindable false
296: * @jsptagref.attributesyntaxvalue <i>string_accessKey</i>
297: * @netui:attribute required="false" rtexprvalue="true" type="char"
298: * description=" The keyboard navigation key for the element.
299: * The following values are not recommended because they
300: * are often used by browsers: A, C, E, F, G,
301: * H, V, left arrow, and right arrow"
302: */
303: public void setAccessKey(char accessKey) {
304: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
305: ACCESSKEY, Character.toString(accessKey));
306: }
307:
308: /**
309: * Sets the alt attribute value.
310: * @param alt the alt value.
311: * @jsptagref.attributedescription The alt attribute of the element.
312: * @jsptagref.databindable Read Only
313: * @jsptagref.attributesyntaxvalue <i>string_alt</i>
314: * @netui:attribute required="false" rtexprvalue="true"
315: * description="The alt attribute of the element."
316: */
317: public void setAlt(String alt) {
318: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL, ALT,
319: alt);
320: }
321:
322: /**
323: * Sets the tabIndex of the rendered html tag.
324: * @param tabindex the tab index.
325: * @jsptagref.attributedescription The tabIndex of the rendered HTML tag. This attribute determines the position of the
326: * tag in the sequence of page elements that the user may advance through by pressing the TAB key.
327: * @jsptagref.databindable false
328: * @jsptagref.attributesyntaxvalue <i>string_tabIndex</i>
329: * @netui:attribute required="false" rtexprvalue="true" type="char"
330: * description="The tabIndex of the rendered HTML tag. This attribute determines the position of the
331: * tag in the sequence of page elements that the user may advance through by pressing the TAB key."
332: */
333: public void setTabindex(int tabindex) {
334: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
335: TABINDEX, Integer.toString(tabindex));
336: }
337: }
|