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.AbstractClassicTag;
022: import org.apache.beehive.netui.tags.IAttributeConsumer;
023: import org.apache.beehive.netui.tags.IHtmlAttrs;
024: import org.apache.beehive.netui.tags.TagConfig;
025: import org.apache.beehive.netui.tags.javascript.ScriptRequestState;
026: import org.apache.beehive.netui.tags.rendering.AbstractHtmlControlState;
027: import org.apache.beehive.netui.tags.rendering.AbstractHtmlState;
028: import org.apache.beehive.netui.util.Bundle;
029:
030: import javax.servlet.http.HttpServletRequest;
031: import javax.servlet.jsp.JspException;
032: import javax.servlet.jsp.tagext.Tag;
033:
034: /**
035: * [Base] Anchor, Form, Image, ImageAnchor (Image), Label, SelectOption
036: * [FocusBase] Button, CheckBoxOption, ImageButton, RadioButtonOption
037: * [DataSource] FileUpload
038: * [DefaultableDatSource] CheckBox, TextArea, TextBox
039: * [OptionsDataSource] Select
040: * [GroupDataSource] CheckBoxGroup, RadioButtonGroup
041: */
042: abstract public class HtmlBaseTag extends AbstractClassicTag implements
043: HtmlConstants, IAttributeConsumer, IHtmlAttrs {
044:
045: /**
046: * This method will return the state associated with the tag. This is used by this
047: * base class to access the individual state objects created by the tags.
048: * @return a subclass of the <code>AbstractHtmlState</code> class.
049: */
050: abstract protected AbstractHtmlState getState();
051:
052: //***************************** The IHtmlCore properties *********************************/
053:
054: /**
055: * Sets the style of the rendered html tag.
056: * @param style the html style.
057: * @jsptagref.attributedescription Specifies style information for the current element.
058: * @jsptagref.databindable false
059: * @jsptagref.attributesyntaxvalue <i>string_style</i>
060: * @netui:attribute required="false" rtexprvalue="true"
061: * description="Specifies style information for the current element."
062: */
063: public void setStyle(String style) {
064: if ("".equals(style))
065: return;
066: AbstractHtmlState tsh = getState();
067: tsh.style = style;
068: }
069:
070: /**
071: * Sets the style class of the rendered html tag.
072: * @param styleClass the html style class.
073: * @jsptagref.attributedescription The style class (a style sheet selector).
074: * @jsptagref.databindable false
075: * @jsptagref.attributesyntaxvalue <i>string_styleClass</i>
076: * @netui:attribute required="false" rtexprvalue="true"
077: * description="The style class (a style sheet selector)."
078: */
079: public void setStyleClass(String styleClass) {
080: if ("".equals(styleClass))
081: return;
082: AbstractHtmlState tsh = getState();
083: tsh.styleClass = styleClass;
084: }
085:
086: /**
087: * Set the ID of the tag.
088: * @param tagId the tagId. A value is required.
089: * @jsptagref.attributedescription <p>String value. Sets the <code>id</code> (or <code>name</code>) attribute of the rendered HTML tag.
090: * Note that the real id attribute rendered in the browser may be
091: * changed by the application container (for example, Portal containers may change
092: * the rendered id value to ensure the uniqueness of
093: * id's on the page). In this case, the real id rendered
094: * in the browser may be looked up
095: * through the JavaScript function <code>lookupIdByTagId( tagId, tag )</code>.
096: *
097: * <p>For example, assume that some tag's <code>tagId</code> attribute is set to <code>foo</code>.
098: *
099: * <pre> <netui:textBox <b>tagId="foo"</b> /></pre>
100: *
101: * <p>Then the following JavaScript function will return the real id attribute rendered in the browser:
102: *
103: * <pre> lookupIdByTagId( "foo", this )</pre>
104: *
105: * <p>To get a <netui:form> element and all of its children elements in JavaScript, use
106: * the same JavaScript function <code>lookupIdByTagId( tagId, tag )</code>. For example,
107: * assume that there is a <netui:form> whose
108: * tagId attribute is set to <code>bar</code>.
109: *
110: * <pre> <netui:form <b>tagId="bar"</b> ></pre>
111: *
112: * <p>Then the following JavaScript function will return the <netui:form> element
113: * and its children (packaged as an array).
114: *
115: * <pre> document[lookupIdByTagId( "bar", this )]</pre>
116: *
117: * <p>To retreive the value entered into a <netui:textBox> within the <netui:form> tag, use the following
118: * JavaScript expression.
119: *
120: * <pre> document[lookupIdByTagId("bar", this)][lookupIdByTagId("foo", this)].value</pre>
121: *
122: * <p>The second parameter ensures that the JavaScript function
123: * begins its search within the correct Portlet scope. Pass the
124: * JavaScript keyword <code>this</code> as the second parameter.
125: * @jsptagref.databindable false
126: * @jsptagref.attributesyntaxvalue <i>string_tagId</i>
127: * @netui:attribute required="false" rtexprvalue="true"
128: * description="String value. Sets the id (or name) attribute of the rendered HTML tag. "
129: */
130: public void setTagId(String tagId) throws JspException {
131: // JSP 2.0 EL will convert a null into a empty string "".
132: // If we get a "" we will display an error.
133: AbstractHtmlState tsh = getState();
134: tsh.id = setRequiredValueAttribute(tagId, "tagId");
135: }
136:
137: /**
138: * Return the ID of the tag. The id may be rewritten by the container (such
139: * as a portal) to make sure it is unique. JavaScript may lookup the actual id
140: * of the element by looking it up in the <code>netui_names</code> table written
141: * into the HTML.
142: * @return the tagId.
143: */
144: public String getTagId() {
145: AbstractHtmlState tsh = getState();
146: return tsh.id;
147: }
148:
149: /**
150: * Sets the value of the title attribute.
151: * @param title
152: * @jsptagref.attributedescription The title.
153: * @jsptagref.databindable false
154: * @jsptagref.attributesyntaxvalue <i>string_title</i>
155: * @netui:attribute required="false" rtexprvalue="true"
156: * description="The title. "
157: */
158: public void setTitle(String title) {
159: AbstractHtmlState tsh = getState();
160: tsh.registerAttribute(AbstractHtmlState.ATTR_GENERAL, TITLE,
161: title);
162: }
163:
164: /******************** the HtmlI18n properties ******************************************/
165: /**
166: * Sets the lang attribute for the HTML element.
167: * @param lang
168: * @jsptagref.attributedescription Sets the language code for the base language of an
169: * element's attribute values and text content.
170: * @jsptagref.databindable false
171: * @jsptagref.attributesyntaxvalue <i>string_lang</i>
172: * @netui:attribute required="false" rtexprvalue="true"
173: * description="Sets the language code for the base language of an element's attribute values and text content."
174: */
175: public void setLang(String lang) {
176: AbstractHtmlState tsh = getState();
177: tsh.registerAttribute(AbstractHtmlState.ATTR_GENERAL, LANG,
178: lang);
179: }
180:
181: /**
182: * Sets the dir attribute for the HTML element.
183: * @param dir
184: * @jsptagref.attributedescription Specifies the direction of text. (<code>LTR | RTL</code>)
185: * @jsptagref.databindable false
186: * @jsptagref.attributesyntaxvalue <i>string_dir</i>
187: * @netui:attribute required="false" rtexprvalue="true"
188: * description="Specifies the direction of text. (LTR | RTL)"
189: */
190: public void setDir(String dir) {
191: AbstractHtmlState tsh = getState();
192: tsh.registerAttribute(AbstractHtmlState.ATTR_GENERAL, DIR, dir);
193: }
194:
195: //******************* the HtmlEvent Properties ****************************************
196: /**
197: * Gets the onClick javascript event.
198: * @return the onClick event.
199: */
200: public String getOnClick() {
201: AbstractHtmlState tsh = getState();
202: return tsh.getAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
203: ONCLICK);
204: }
205:
206: /**
207: * Sets the onClick javascript event.
208: * @param onclick the onClick event.
209: * @jsptagref.attributedescription The onClick JavaScript event.
210: * @jsptagref.databindable false
211: * @jsptagref.attributesyntaxvalue <i>string_onClick</i>
212: * @netui:attribute required="false" rtexprvalue="true"
213: * description="The onClick JavaScript event."
214: */
215: public void setOnClick(String onclick) {
216: AbstractHtmlState tsh = getState();
217: tsh.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
218: ONCLICK, onclick);
219: }
220:
221: /**
222: * Sets the onDblClick javascript event.
223: * @param ondblclick the onDblClick event.
224: * @jsptagref.attributedescription The onDblClick JavaScript event.
225: * @jsptagref.databindable false
226: * @jsptagref.attributesyntaxvalue <i>string_onDblClick</i>
227: * @netui:attribute required="false" rtexprvalue="true"
228: * description="The onDblClick JavaScript event."
229: */
230: public void setOnDblClick(String ondblclick) {
231: AbstractHtmlState tsh = getState();
232: tsh.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
233: ONDBLCLICK, ondblclick);
234: }
235:
236: /**
237: * Sets the onKeyDown javascript event.
238: * @param onkeydown the onKeyDown event.
239: * @jsptagref.attributedescription The onKeyDown JavaScript event.
240: * @jsptagref.databindable false
241: * @jsptagref.attributesyntaxvalue <i>string_onKeyDown</i>
242: * @netui:attribute required="false" rtexprvalue="true"
243: * description="The onKeyDown JavaScript event."
244: */
245: public void setOnKeyDown(String onkeydown) {
246: AbstractHtmlState tsh = getState();
247: tsh.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
248: ONKEYDOWN, onkeydown);
249: }
250:
251: /**
252: * Sets the onKeyPress javascript event.
253: * @param onkeypress the onKeyPress event.
254: * @jsptagref.attributedescription The onKeyPress JavaScript event.
255: * @jsptagref.databindable false
256: * @jsptagref.attributesyntaxvalue <i>string_onKeyPress</i>
257: * @netui:attribute required="false" rtexprvalue="true"
258: * description="The onKeyPress JavaScript event."
259: */
260: public void setOnKeyPress(String onkeypress) {
261: AbstractHtmlState tsh = getState();
262: tsh.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
263: ONKEYPRESS, onkeypress);
264: }
265:
266: /**
267: * Sets the onKeyUp javascript event.
268: * @param onkeyup the onKeyUp event.
269: * @jsptagref.attributedescription The onKeyUp JavaScript event.
270: * @jsptagref.databindable false
271: * @jsptagref.attributesyntaxvalue <i>string_onKeyUp</i>
272: * @netui:attribute required="false" rtexprvalue="true"
273: * description="The onKeyUp JavaScript event."
274: */
275: public void setOnKeyUp(String onkeyup) {
276: AbstractHtmlState tsh = getState();
277: tsh.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
278: ONKEYUP, onkeyup);
279: }
280:
281: /**
282: * Sets the onMouseDown javascript event.
283: * @param onmousedown the onMouseDown event.
284: * @jsptagref.attributedescription The onMouseDown JavaScript event.
285: * @jsptagref.databindable false
286: * @jsptagref.attributesyntaxvalue <i>string_onMouseDown</i>
287: * @netui:attribute required="false" rtexprvalue="true"
288: * description="The onMouseDown JavaScript event."
289: */
290: public void setOnMouseDown(String onmousedown) {
291: AbstractHtmlState tsh = getState();
292: tsh.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
293: ONMOUSEDOWN, onmousedown);
294: }
295:
296: /**
297: * Sets the onMouseMove javascript event.
298: * @param onmousemove the onMouseMove event.
299: * @jsptagref.attributedescription The onMouseMove JavaScript event.
300: * @jsptagref.databindable false
301: * @jsptagref.attributesyntaxvalue <i>string_onMouseMove</i>
302: * @netui:attribute required="false" rtexprvalue="true"
303: * description="The onMouseMove JavaScript event."
304: */
305: public void setOnMouseMove(String onmousemove) {
306: AbstractHtmlState tsh = getState();
307: tsh.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
308: ONMOUSEMOVE, onmousemove);
309: }
310:
311: /**
312: * Sets the onMouseOut javascript event.
313: * @param onmouseout the onMouseOut event.
314: * @jsptagref.attributedescription The onMouseOut JavaScript event.
315: * @jsptagref.databindable false
316: * @jsptagref.attributesyntaxvalue <i>string_onMouseOut</i>
317: * @netui:attribute required="false" rtexprvalue="true"
318: * description="The onMouseOut JavaScript event."
319: */
320: public void setOnMouseOut(String onmouseout) {
321: AbstractHtmlState tsh = getState();
322: tsh.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
323: ONMOUSEOUT, onmouseout);
324: }
325:
326: /**
327: * Sets the onMouseOver javascript event.
328: * @param onmouseover the onMouseOver event.
329: * @jsptagref.attributedescription The onMouseOver JavaScript event.
330: * @jsptagref.databindable false
331: * @jsptagref.attributesyntaxvalue <i>string_onMouseOver</i>
332: * @netui:attribute required="false" rtexprvalue="true"
333: * description="The onMouseOver JavaScript event."
334: */
335: public void setOnMouseOver(String onmouseover) {
336: AbstractHtmlState tsh = getState();
337: tsh.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
338: ONMOUSEOVER, onmouseover);
339: }
340:
341: /**
342: * Sets the onMouseUp javascript event.
343: * @param onmouseup the onMouseUp event.
344: * @jsptagref.attributedescription The onMouseUp JavaScript event.
345: * @jsptagref.databindable false
346: * @jsptagref.attributesyntaxvalue <i>string_onMouseUp</i>
347: * @netui:attribute required="false" rtexprvalue="true"
348: * description="The onMouseUp JavaScript event."
349: */
350: public void setOnMouseUp(String onmouseup) {
351: AbstractHtmlState tsh = getState();
352: tsh.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT,
353: ONMOUSEUP, onmouseup);
354: }
355:
356: //******************* Helper Routines *********************************/
357:
358: protected String getJavaScriptAttribute(String name) {
359: AbstractHtmlState tsh = getState();
360: return tsh
361: .getAttribute(AbstractHtmlState.ATTR_JAVASCRIPT, name);
362: }
363:
364: /**
365: * Attribute implementation.
366: * @param name
367: * @param value
368: * @param tsh
369: * @throws JspException
370: */
371: protected void setStateAttribute(String name, String value,
372: AbstractHtmlState tsh) throws JspException {
373: boolean error = false;
374:
375: // validate the name attribute, in the case of an error simply return.
376: if (name == null || name.length() <= 0) {
377: String s = Bundle.getString("Tags_AttributeNameNotSet");
378: registerTagError(s, null);
379: error = true;
380: }
381:
382: // it's not legal to set the id or name attributes this way
383: if (name != null && (name.equals(ID) || name.equals(NAME))) {
384: String s = Bundle.getString("Tags_AttributeMayNotBeSet",
385: new Object[] { name });
386: registerTagError(s, null);
387: }
388: if (error)
389: return;
390:
391: // if there is a style or class we will let them override the base
392: if (name.equals(CLASS)) {
393: tsh.styleClass = value;
394: return;
395: } else if (name.equals(STYLE)) {
396: tsh.style = value;
397: return;
398: }
399: tsh.registerAttribute(AbstractHtmlState.ATTR_GENERAL, name,
400: value);
401: }
402:
403: /**
404: * Base support for the <code>attribute</code> tag. This requires that the tag buffer their body and
405: * write attribute in the end tag. For the HTML tags it is not legal to set
406: * the <code>id</code> or <code>name</code> attributes. In addition, the base tag does
407: * not allow facets to be set. If the attribute is legal it will be added to the
408: * general expression map stored in the <code>AbstractHtmlState</code> of the tag.
409: * @param name The name of the attribute. This value may not be null or the empty string.
410: * @param value The value of the attribute. This may contain an expression.
411: * @param facet The name of a facet to which the attribute will be applied. This is optional.
412: * @throws JspException A JspException may be thrown if there is an error setting the attribute.
413: */
414: public void setAttribute(String name, String value, String facet)
415: throws JspException {
416: if (facet != null) {
417: String s = Bundle.getString(
418: "Tags_AttributeFacetNotSupported",
419: new Object[] { facet });
420: registerTagError(s, null);
421: }
422: AbstractHtmlState tsh = getState();
423: setStateAttribute(name, value, tsh);
424: }
425:
426: /**
427: * Assumptions:
428: * <ul>
429: * <li>The state.name must be fully formed or the "real name" of the form.</li>
430: * <li>The state.id is the tagId value set on the tag and <b>has not</b> be rewritten yet to form the "real id"</li>
431: * </ul>
432: * @param state
433: * @param parentForm
434: * @return String
435: */
436: protected final String renderNameAndId(HttpServletRequest request,
437: AbstractHtmlState state, Form parentForm) {
438: // if id is not set then we need to exit
439: if (state.id == null)
440: return null;
441:
442: // check to see if this is an instance of a HTML Control
443: boolean ctrlState = (state instanceof AbstractHtmlControlState);
444:
445: // form keeps track of this so that it can add this control to it's focus map
446: if (parentForm != null && ctrlState) {
447: AbstractHtmlControlState hcs = (AbstractHtmlControlState) state;
448: if (hcs.name == null && parentForm.isFocusSet())
449: hcs.name = state.id;
450: parentForm.addTagID(state.id,
451: ((AbstractHtmlControlState) state).name);
452: }
453:
454: // rewrite the id, save the original value so it can be used in maps
455: String id = state.id;
456: state.id = getIdForTagId(id);
457:
458: // Legacy Java Script support -- This writes out a single table with both the id and names
459: // mixed. This is legacy support to match the pre beehive behavior.
460: String idScript = null;
461: if (TagConfig.isLegacyJavaScript()) {
462: ScriptRequestState srs = ScriptRequestState
463: .getScriptRequestState(request);
464: if (!ctrlState) {
465: idScript = srs.mapLegacyTagId(getScriptReporter(), id,
466: state.id);
467: } else {
468: AbstractHtmlControlState cState = (AbstractHtmlControlState) state;
469: if (cState.name != null)
470: idScript = srs.mapLegacyTagId(getScriptReporter(),
471: id, cState.name);
472: else
473: idScript = srs.mapLegacyTagId(getScriptReporter(),
474: id, state.id);
475: }
476: }
477:
478: // map the tagId to the real id
479: String name = null;
480: if (ctrlState) {
481: AbstractHtmlControlState cState = (AbstractHtmlControlState) state;
482: name = cState.name;
483: }
484:
485: String script = renderDefaultNameAndId(
486: (HttpServletRequest) pageContext.getRequest(), state,
487: id, name);
488: if (script != null) {
489: if (idScript != null) {
490: idScript = idScript + script;
491: } else {
492: idScript = script;
493: }
494: }
495: return idScript;
496: }
497:
498: protected String renderDefaultNameAndId(HttpServletRequest request,
499: AbstractHtmlState state, String id, String name) {
500:
501: // map the tagId to the real id
502: String script = null;
503: if (TagConfig.isDefaultJavaScript()) {
504: ScriptRequestState srs = ScriptRequestState
505: .getScriptRequestState(request);
506: script = srs.mapTagId(getScriptReporter(), id, state.id,
507: name);
508: }
509: return script;
510: }
511:
512: /**
513: * Free the state variables of this base class.
514: */
515: protected void localRelease() {
516: super.localRelease();
517: }
518: }
|