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: // java imports
022:
023: import org.apache.beehive.netui.tags.IHtmlAccessable;
024: import org.apache.beehive.netui.tags.rendering.*;
025: import org.apache.beehive.netui.util.Bundle;
026:
027: import javax.servlet.ServletRequest;
028: import javax.servlet.http.HttpServletRequest;
029: import javax.servlet.jsp.JspException;
030: import javax.servlet.jsp.tagext.Tag;
031:
032: // external imports
033:
034: /**
035: * A checkbox whose state is determined by its enclosing CheckBoxGroup.
036: * @jsptagref.tagdescription Renders a single HTML checkbox within a group of checkboxes.
037: *
038: * The <netui:checkBoxOption> tags must have a parent
039: * {@link CheckBoxGroup} tag (which
040: * determines the data binding for the <netui:checkBoxOption> tags).
041: * @example In this sample, a set of <checkBoxOption> tags are submitted
042: * to the <code>processData</code> action method.
043: *
044: * <pre> <netui:form action="processData">
045: * <netui:checkBoxGroup dataSource="actionForm.data" defaultValue="${actionForm.defaultChoices}">
046: * <netui:checkBoxOption value="wantSpecialCDOffers">Do you want to be notified of special CD offers?</netui:checkBoxOption><br>
047: * <netui:checkBoxOption value="wantSpecialDVDOffers">Do you want to be notified of special DVD offers?</netui:checkBoxOption><br>
048: * </netui:checkBoxGroup>
049: * <netui:button value="Submit" type="submit"/>
050: * </netui:form></pre>
051: * @netui:tag name="checkBoxOption" description="A checkbox whose state is determined by its enclosing CheckBoxGroup."
052: */
053: public class CheckBoxOption extends HtmlFocusBaseTag implements
054: IHtmlAccessable {
055: private InputBooleanTag.State _state = new InputBooleanTag.State();
056: private SpanTag.State _spanState = new SpanTag.State();
057: private String _text; // The message text to be displayed to the user for this tag (if any)
058: private Boolean _defaultValue;
059:
060: /**
061: * Return the name of the Tag.
062: */
063: public String getTagName() {
064: return "CheckBoxOption";
065: }
066:
067: /**
068: * This method will return the state associated with the tag. This is used by this
069: * base class to access the individual state objects created by the tags.
070: * @return a subclass of the <code>AbstractHtmlState</code> class.
071: */
072: protected AbstractHtmlState getState() {
073: return _state;
074: }
075:
076: /**
077: * Base support for the attribute tag. This is overridden to prevent setting the <code>type</code>,
078: * <code>checked</code>, and <code>value</code> attributes.
079: * @param name The name of the attribute. This value may not be null or the empty string.
080: * @param value The value of the attribute. This may contain an expression.
081: * @param facet The name of a facet to which the attribute will be applied. This is optional.
082: * @throws JspException A JspException may be thrown if there is an error setting the attribute.
083: */
084: public void setAttribute(String name, String value, String facet)
085: throws JspException {
086: if (name != null) {
087: if (name.equals(TYPE) || name.equals(VALUE)
088: || name.equals(CHECKED)) {
089: String s = Bundle.getString(
090: "Tags_AttributeMayNotBeSet",
091: new Object[] { name });
092: registerTagError(s, null);
093: } else {
094: if (name.equals(DISABLED)) {
095: setDisabled(Boolean.parseBoolean(value));
096: return;
097: }
098: }
099: }
100: if (facet != null && facet.equals("label")) {
101: setStateAttribute(name, value, _spanState);
102: return;
103: }
104: super .setAttribute(name, value, facet);
105: }
106:
107: /**
108: * Set the label style for each contained CheckBoxOption.
109: * The label style here will override a labelStyle at the CheckBoxGroup level.
110: * @param labelStyle the label style
111: * @jsptagref.attributedescription The style of the text displayed by the rendered checkbox.
112: * @jsptagref.databindable false
113: * @jsptagref.attributesyntaxvalue <i>string_label</i>
114: * @netui:attribute required="false" rtexprvalue="true"
115: * description="The style of the text displayed by the rendered checkbox."
116: */
117: public void setLabelStyle(String labelStyle) {
118: _spanState.style = setNonEmptyValueAttribute(labelStyle);
119: }
120:
121: /**
122: * Set the label style class for each contained CheckBoxOption.
123: * The label style class here will override a labelStyleClass at the CheckBoxGroup level.
124: * @param labelStyleClass the label style
125: * @jsptagref.attributedescription The class of the text displayed by the rendered checkbox.
126: * @jsptagref.databindable false
127: * @jsptagref.attributesyntaxvalue <i>string_class</i>
128: * @netui:attribute required="false" rtexprvalue="true"
129: * description="The class of the text displayed by the rendered checkbox."
130: */
131: public void setLabelStyleClass(String labelStyleClass) {
132: _spanState.styleClass = setNonEmptyValueAttribute(labelStyleClass);
133: }
134:
135: /**
136: * Set the value of this CheckBoxOption.
137: * @param value the CheckBoxOption value
138: * @jsptagref.attributedescription A String literal or a data binding expression. The value attribute determines the value submitted
139: * by the checkbox.
140: * @jsptagref.databindable true
141: * @jsptagref.attributesyntaxvalue <i>string_literal_or_expression_value</i>
142: * @netui:attribute required="false" rtexprvalue="true"
143: * description="A String literal or a data binding expression. The value attribute determines the value submitted
144: * by the checkbox."
145: */
146: public void setValue(Object value) throws JspException {
147: if (value != null)
148: _state.value = value.toString();
149: else
150: _state.value = null;
151: }
152:
153: /**
154: * Sets the default value (can be an expression).
155: * @param defaultValue the default value
156: * @jsptagref.attributedescription The boolean value or expression to be used as the default value.
157: * @jsptagref.databindable true
158: * @jsptagref.attributesyntaxvalue <i>boolean_defaultValue</i>
159: * @netui:attribute required="false" rtexprvalue="true" type="boolean"
160: * description="Sets the default value."
161: */
162: public void setDefaultValue(boolean defaultValue)
163: throws JspException {
164: _defaultValue = Boolean.valueOf(defaultValue);
165: }
166:
167: /**
168: * Process the start of this tag.
169: * @throws JspException if a JSP exception has occurred
170: */
171: public int doStartTag() throws JspException {
172: // verify that the parent is a CheckBoxGroup
173: Tag parentTag = findAncestorWithClass(this , CheckBoxGroup.class);
174: if (parentTag == null) {
175: String s = Bundle
176: .getString("Tags_CheckBoxOptionNoCheckBoxGroup");
177: registerTagError(s, null);
178: return SKIP_BODY;
179: }
180:
181: CheckBoxGroup parent = (CheckBoxGroup) parentTag;
182: if ((parent.getOptionsDataSource() != null && !parent
183: .isRepeater())) {
184: String s = Bundle
185: .getString("Tags_CheckBoxOptionParentHasOptionsDataSource");
186: parent.registerTagError(s, null);
187: return SKIP_BODY;
188: }
189:
190: // Do nothing until doEndTag() is called
191: return EVAL_BODY_BUFFERED;
192: }
193:
194: /**
195: * Process the body text of this tag (if any).
196: * @throws JspException if a JSP exception has occurred
197: */
198: public int doAfterBody() throws JspException {
199: String text = bodyContent.getString();
200: if (text != null) {
201: bodyContent.clearBody();
202: text = text.trim();
203: if (text.length() > 0)
204: _text = text;
205: }
206: return SKIP_BODY;
207: }
208:
209: /**
210: * Process the end of this tag.
211: * @throws JspException if a JSP exception has occurred
212: */
213: public int doEndTag() throws JspException {
214: if (hasErrors())
215: return reportAndExit(EVAL_PAGE);
216:
217: // we verified that the parent was a CheckboxGroup in the doBeginTag()
218: ServletRequest req = pageContext.getRequest();
219: CheckBoxGroup parent = (CheckBoxGroup) findAncestorWithClass(
220: this , CheckBoxGroup.class);
221: ConstantRendering cr = TagRenderingBase.Factory
222: .getConstantRendering(req);
223: boolean repeat = parent.isRepeater();
224:
225: // create the writer
226: WriteRenderAppender writer = new WriteRenderAppender(
227: pageContext);
228: if (!repeat && parent.isVertical()) {
229: cr.TR_TD(writer);
230: }
231:
232: _state.type = INPUT_CHECKBOX;
233: _state.name = parent.getQualifiedDataSourceName();
234: if (_state.id != null) {
235: String tagId = _state.id;
236: _state.id = getIdForTagId(_state.id);
237: /* This has been commented out because we can't set focus on checkbox options
238: because they don't have a unique name.
239: Form parentForm = getNearestForm();
240: if (parentForm != null)
241: parentForm.addTagID(tagId, _state.name);
242: */
243: String script = renderDefaultNameAndId(
244: (HttpServletRequest) req, _state, tagId,
245: _state.name);
246: if (script != null) {
247: write(script);
248: }
249: }
250:
251: // Disabled on the option itself will override the parent setting this.
252: // We check to see if the option actuall had disabled set on it, if not then look
253: // at the parent.
254: if (parent.isMatched(_state.value, _defaultValue))
255: _state.checked = true;
256: _state.disabled = isDisabled();
257: if (!_state.disabled)
258: _state.disabled = parent.isDisabled();
259:
260: TagRenderingBase br = TagRenderingBase.Factory.getRendering(
261: TagRenderingBase.INPUT_BOOLEAN_TAG, req);
262: br.doStartTag(writer, _state);
263: br.doEndTag(writer);
264:
265: if (repeat && !parent.isDisabled()) {
266: parent.createHiddenField(writer);
267: }
268:
269: // if this is in a repeater, then we only output the <input tag>
270: if (repeat) {
271: //write(results.toString());
272: localRelease();
273: return EVAL_PAGE;
274: }
275:
276: if (_spanState.style == null) {
277: _spanState.style = parent.getLabelStyle();
278: }
279: if (_spanState.styleClass == null) {
280: _spanState.styleClass = parent.getLabelStyleClass();
281: }
282:
283: TagRenderingBase spanTag = TagRenderingBase.Factory
284: .getRendering(TagRenderingBase.SPAN_TAG, req);
285: spanTag.doStartTag(writer, _spanState);
286: if (_text == null)
287: write(_state.value);
288: else
289: write(_text);
290: spanTag.doEndTag(writer);
291:
292: if (parent.isVertical()) {
293: cr.end_TD_TR(writer);
294: }
295:
296: // Continue evaluating this page
297: localRelease();
298: return EVAL_PAGE;
299:
300: }
301:
302: /**
303: * Release any acquired resources.
304: */
305: protected void localRelease() {
306: super .localRelease();
307:
308: _state.clear();
309: _spanState.clear();
310: _text = null;
311: }
312:
313: /* ==================================================================
314: *
315: * This tag's publically exposed HTML, CSS, and JavaScript attributes
316: *
317: * ==================================================================
318: */
319:
320: /**
321: * Sets the accessKey attribute value. This should key value of the
322: * keyboard navigation key. It is recommended not to use the following
323: * values because there are often used by browsers <code>A, C, E, F, G,
324: * H, V, left arrow, and right arrow</code>.
325: * @param accessKey the accessKey value.
326: * @jsptagref.attributedescription The keyboard navigation key for the element.
327: * The following values are not recommended because they
328: * are often used by browsers: <code>A, C, E, F, G,
329: * H, V, left arrow, and right arrow</code>
330: * @jsptagref.databindable false
331: * @jsptagref.attributesyntaxvalue <i>string_accessKey</i>
332: * @netui:attribute required="false" rtexprvalue="true" type="char"
333: * description="The keyboard navigation key for the element.
334: * The following values are not recommended because they
335: * are often used by browsers: A, C, E, F, G,
336: * H, V, left arrow, and right arrow"
337: */
338: public void setAccessKey(char accessKey) {
339: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
340: ACCESSKEY, Character.toString(accessKey));
341: }
342:
343: /**
344: * Sets the alt attribute value.
345: * @param alt the alt value.
346: * @jsptagref.attributedescription The alt attribute of the element.
347: * @jsptagref.databindable Read Only
348: * @jsptagref.attributesyntaxvalue <i>string_alt</i>
349: * @netui:attribute required="false" rtexprvalue="true"
350: * description="The alt attribute of the element."
351: */
352: public void setAlt(String alt) {
353: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL, ALT,
354: alt);
355: }
356:
357: /**
358: * Sets the tabIndex of the rendered html tag.
359: * @param tabindex the tab index.
360: * @jsptagref.attributedescription The tabIndex of the rendered HTML tag. This attribute determines the position of the
361: * tag in the sequence of page elements that the user may advance through by pressing the TAB key.
362: * @jsptagref.databindable false
363: * @jsptagref.attributesyntaxvalue <i>string_tabIndex</i>
364: * @netui:attribute required="false" rtexprvalue="true" type="int"
365: * description="The tabIndex of the rendered HTML tag. This attribute determines the position of the
366: * tag in the sequence of page elements that the user may advance through by pressing the TAB key."
367: */
368: public void setTabindex(int tabindex) {
369: _state.registerAttribute(AbstractHtmlState.ATTR_GENERAL,
370: TABINDEX, Integer.toString(tabindex));
371: }
372: }
|