0001: /*
0002: * Copyright (c) 2002-2003 by OpenSymphony
0003: * All rights reserved.
0004: */
0005: package com.opensymphony.webwork.components;
0006:
0007: import com.opensymphony.webwork.WebWorkConstants;
0008: import com.opensymphony.webwork.components.template.Template;
0009: import com.opensymphony.webwork.components.template.TemplateEngine;
0010: import com.opensymphony.webwork.components.template.TemplateEngineManager;
0011: import com.opensymphony.webwork.components.template.TemplateRenderingContext;
0012: import com.opensymphony.webwork.config.Configuration;
0013: import com.opensymphony.webwork.views.util.ContextUtil;
0014: import com.opensymphony.xwork.config.ConfigurationException;
0015: import com.opensymphony.xwork.util.OgnlValueStack;
0016: import org.apache.commons.logging.Log;
0017: import org.apache.commons.logging.LogFactory;
0018:
0019: import javax.servlet.http.HttpServletRequest;
0020: import javax.servlet.http.HttpServletResponse;
0021: import java.io.Writer;
0022: import java.util.Iterator;
0023: import java.util.LinkedHashMap;
0024: import java.util.List;
0025: import java.util.Map;
0026:
0027: /**
0028: * UIBean is the standard superclass of all webwork UI componentns.
0029: * It defines common webwork and html properties all UI components should present for usage.
0030: *
0031: * <!-- START SNIPPET: templateRelatedAttributes -->
0032: *
0033: * <table border="1">
0034: * <thead>
0035: * <tr>
0036: * <td>Attribute</td>
0037: * <td>Theme</td>
0038: * <td>Data Types</td>
0039: * <td>Description</td>
0040: * </tr>
0041: * </thead>
0042: * <tbody>
0043: * <tr>
0044: * <td>templateDir</td>
0045: * <td>n/a</td>
0046: * <td>String</td>
0047: * <td>define the template directory</td>
0048: * </td>
0049: * <tr>
0050: * <td>theme</td>
0051: * <td>n/a</td>
0052: * <td>String</td>
0053: * <td>define the theme name</td>
0054: * </td>
0055: * <tr>
0056: * <td>template</td>
0057: * <td>n/a</td>
0058: * <td>String</td>
0059: * <td>define the template name</td>
0060: * </td>
0061: * </tbody>
0062: * </table>
0063: *
0064: * <!-- END SNIPPET: templateRelatedAttributes -->
0065: *
0066: * <p/>
0067: *
0068: * <!-- START SNIPPET: generalAttributes -->
0069: *
0070: * <table border="1">
0071: * <thead>
0072: * <tr>
0073: * <td>Attribute</td>
0074: * <td>Theme</td>
0075: * <td>Data Types</td>
0076: * <td>Description</td>
0077: * </tr>
0078: * </thead>
0079: * <tbody>
0080: * <tr>
0081: * <td>cssClass</td>
0082: * <td>simple</td>
0083: * <td>String</td>
0084: * <td>define html class attribute</td>
0085: * </tr>
0086: * <tr>
0087: * <td>cssStyle</td>
0088: * <td>simple</td>
0089: * <td>String</td>
0090: * <td>define html style attribute</td>
0091: * </tr>
0092: * <tr>
0093: * <td>title</td>
0094: * <td>simple</td>
0095: * <td>String</td>
0096: * <td>define html title attribute</td>
0097: * </tr>
0098: * <tr>
0099: * <td>disabled</td>
0100: * <td>simple</td>
0101: * <td>String</td>
0102: * <td>define html disabled attribute</td>
0103: * </tr>
0104: * <tr>
0105: * <td>label</td>
0106: * <td>xhtml</td>
0107: * <td>String</td>
0108: * <td>define label of form element</td>
0109: * </tr>
0110: * <tr>
0111: * <td>labelPosition</td>
0112: * <td>xhtml</td>
0113: * <td>String</td>
0114: * <td>define label position of form element (top/left), default to left</td>
0115: * </tr>
0116: * <tr>
0117: * <td>requiredposition</td>
0118: * <td>xhtml</td>
0119: * <td>String</td>
0120: * <td>define required label position of form element (left/right), default to right</td>
0121: * </tr>
0122: * <tr>
0123: * <td>name</td>
0124: * <td>simple</td>
0125: * <td>String</td>
0126: * <td>Form Element's field name mapping</td>
0127: * </tr>
0128: * <tr>
0129: * <td>required</td>
0130: * <td>xhtml</td>
0131: * <td>Boolean</td>
0132: * <td>add * to label (true to add false otherwise)</td>
0133: * </tr>
0134: * <tr>
0135: * <td>tabIndex</td>
0136: * <td>simple</td>
0137: * <td>String</td>
0138: * <td>define html tabindex attribute</td>
0139: * </tr>
0140: * <tr>
0141: * <td>value</td>
0142: * <td>simple</td>
0143: * <td>Object</td>
0144: * <td>define value of form element</td>
0145: * </tr>
0146: * </tbody>
0147: * </table>
0148: *
0149: * <!-- END SNIPPET: generalAttributes -->
0150: *
0151: * <p/>
0152: *
0153: * <!-- START SNIPPET: javascriptRelatedAttributes -->
0154: *
0155: * <table border="1">
0156: * <thead>
0157: * <tr>
0158: * <td>Attribute</td>
0159: * <td>Theme</td>
0160: * <td>Data Types</td>
0161: * <td>Description</td>
0162: * </tr>
0163: * </thead>
0164: * <tbody>
0165: * <tr>
0166: * <td>onclick</td>
0167: * <td>simple</td>
0168: * <td>String</td>
0169: * <td>html javascript onclick attribute</td>
0170: * </tr>
0171: * <tr>
0172: * <td>ondbclick</td>
0173: * <td>simple</td>
0174: * <td>String</td>
0175: * <td>html javascript ondbclick attribute</td>
0176: * </tr>
0177: * <tr>
0178: * <td>onmousedown</td>
0179: * <td>simple</td>
0180: * <td>String</td>
0181: * <td>html javascript onmousedown attribute</td>
0182: * </tr>
0183: * <tr>
0184: * <td>onmouseup</td>
0185: * <td>simple</td>
0186: * <td>String</td>
0187: * <td>html javascript onmouseup attribute</td>
0188: * </tr>
0189: * <tr>
0190: * <td>onmouseover</td>
0191: * <td>simple</td>
0192: * <td>String</td>
0193: * <td>html javascript onmouseover attribute</td>
0194: * </tr>
0195: * <tr>
0196: * <td>onmouseout</td>
0197: * <td>simple</td>
0198: * <td>String</td>
0199: * <td>html javascript onmouseout attribute</td>
0200: * </tr>
0201: * <tr>
0202: * <td>onfocus</td>
0203: * <td>simple</td>
0204: * <td>String</td>
0205: * <td>html javascript onfocus attribute</td>
0206: * </tr>
0207: * <tr>
0208: * <td>onblur</td>
0209: * <td>simple</td>
0210: * <td>String</td>
0211: * <td>html javascript onblur attribute</td>
0212: * </tr>
0213: * <tr>
0214: * <td>onkeypress</td>
0215: * <td>simple</td>
0216: * <td>String</td>
0217: * <td>html javascript onkeypress attribute</td>
0218: * </tr>
0219: * <tr>
0220: * <td>onkeyup</td>
0221: * <td>simple</td>
0222: * <td>String</td>
0223: * <td>html javascript onkeyup attribute</td>
0224: * </tr>
0225: * <tr>
0226: * <td>onkeydown</td>
0227: * <td>simple</td>
0228: * <td>String</td>
0229: * <td>html javascript onkeydown attribute</td>
0230: * </tr>
0231: * <tr>
0232: * <td>onselect</td>
0233: * <td>simple</td>
0234: * <td>String</td>
0235: * <td>html javascript onselect attribute</td>
0236: * </tr>
0237: * <tr>
0238: * <td>onchange</td>
0239: * <td>simple</td>
0240: * <td>String</td>
0241: * <td>html javascript onchange attribute</td>
0242: * </tr>
0243: * </tbody>
0244: * </table>
0245: *
0246: * <!-- END SNIPPET: javascriptRelatedAttributes -->
0247: *
0248: * <p/>
0249: *
0250: * <!-- START SNIPPET: tooltipattributes -->
0251: *
0252: * <table border="1">
0253: * <tr>
0254: * <td>Attribute</td>
0255: * <td>Data Type</td>
0256: * <td>Default</td>
0257: * <td>Description</td>
0258: * </tr>
0259: * <tr>
0260: * <td>tooltip</td>
0261: * <td>String</td>
0262: * <td>none</td>
0263: * <td>Set the tooltip of this particular component</td>
0264: * </tr>
0265: * <tr>
0266: * <td>tooltipIcon</td>
0267: * <td>String</td>
0268: * <td>/webwork/static/tooltip/tooltip.gif</td>
0269: * <td>The url to the tooltip icon</td>
0270: * </tr>
0271: * <td>tooltipAboveMousePointer</td>
0272: * <td>Boolean</td>
0273: * <td>false</td>
0274: * <td>Places the tooltip above the mousepointer. Additionally applied the tooltipOffseY allows to set the vertical distance from the mousepointer.</td>
0275: * </tr>
0276: * <tr>
0277: * <td>tooltipBgColor</td>
0278: * <td>String</td>
0279: * <td>#e6ecff</td>
0280: * <td>Background color of the tooltip.</td>
0281: * </tr>
0282: * <tr>
0283: * <td>tooltipBgImg</td>
0284: * <td>String</td>
0285: * <td>none</td>
0286: * <td>Background image.</td>
0287: * </tr>
0288: * <tr>
0289: * <td>tooltipBorderWidth</td>
0290: * <td>String</td>
0291: * <td>1</td>
0292: * <td>Width of tooltip border.</td>
0293: * </tr>
0294: * <tr>
0295: * <td>tooltipBorderColor</td>
0296: * <td>String</td>
0297: * <td>#003399</td>
0298: * <td>Background color of the tooltip</td>
0299: * </tr>
0300: * <tr>
0301: * <td>tooltipDelay</td>
0302: * <td>String</td>
0303: * <td>500</td>
0304: * <td>Tooltip shows up after the specified timeout (miliseconds). A behavior similar to that of OS based tooltips.</td>
0305: * </tr>
0306: * <tr>
0307: * <td>tooltipFixCoordinateX</td>
0308: * <td>String</td>
0309: * <td>not specified</td>
0310: * <td>Fixes the tooltip to the X co-ordinates specified. Useful for example if combined with tooltipSticky attribute.</td>
0311: * </tr>
0312: * <tr>
0313: * <td>tooltipFixCoordinateY</td>
0314: * <td>String</td>
0315: * <td>not specified</td>
0316: * <td>Fixes the tooltip to the Y co-ordinates specified. Useful for example if combined with tooltipSticky attribute.</td>
0317: * </tr>
0318: * <tr>
0319: * <td>tooltipFontColor</td>
0320: * <td>String</td>
0321: * <td>#000066</td>
0322: * <td>Font color.</td>
0323: * </tr>
0324: * <tr>
0325: * <td>tooltipFontFace</td>
0326: * <td>String</td>
0327: * <td>arial,helvetica,sans-serif</td>
0328: * <td>Font face/family eg. verdana,geneva,sans-serif</td>
0329: * </tr>
0330: * <tr>
0331: * <td>tooltipFontSize</td>
0332: * <td>String</td>
0333: * <td>11px</td>
0334: * <td>Font size + unit eg. 30px</td>
0335: * </tr>
0336: * <tr>
0337: * <td>tooltipFontWeight</td>
0338: * <td>String</td>
0339: * <td>normal</td>
0340: * <td>Font weight. either normal or bold</td>
0341: * </tr>
0342: * <tr>
0343: * <td>tooltipLeftOfMousePointer</td>
0344: * <td>Boolean</td>
0345: * <td>false</td>
0346: * <td>Tooltip positioned on the left side of the mousepointer</td>
0347: * </tr>
0348: * <tr>
0349: * <td>tooltipOffsetX</td>
0350: * <td>String</td>
0351: * <td>12</td>
0352: * <td>Horizontal offset from mouse-pointer.</td>
0353: * </tr>
0354: * <tr>
0355: * <td>tooltipOffsetY</td>
0356: * <td>String</td>
0357: * <td>15</td>
0358: * <td>Vertical offset from mouse-pointer.</td>
0359: * </tr>
0360: * <tr>
0361: * <td>tooltipOpacity</td>
0362: * <td>String</td>
0363: * <td>100</td>
0364: * <td>Transparency of tooltip. Opacity is the opposite of transparency. Value must be a number between 0 (fully transparent) and 100 (opaque, no transparency). Not (yet) supported by Opera.</td>
0365: * </tr>
0366: * <tr>
0367: * <td>tooltipPadding</td>
0368: * <td>String</td>
0369: * <td>3</td>
0370: * <td>Inner spacing, ie. the spacing between border and content, for instance text or image(s)</td>
0371: * </tr>
0372: * <tr>
0373: * <td>tooltipShadowColor</td>
0374: * <td>String</td>
0375: * <td>#cccccc</td>
0376: * <td>Creates shadow with the specified color.</td>
0377: * </tr>
0378: * <tr>
0379: * <td>tooltipShadowWidth</td>
0380: * <td>String</td>
0381: * <td>5</td>
0382: * <td>Creates shodow with the specified width (offset).</td>
0383: * </tr>
0384: * <tr>
0385: * <td>tooltipStatic</td>
0386: * <td>Boolean</td>
0387: * <td>false</td>
0388: * <td>Like OS-based tooltips, the tooltip doesn't follow the movements of the mouse pointer.</td>
0389: * </tr>
0390: * <tr>
0391: * <td>tooltipSticky</td>
0392: * <td>Boolean</td>
0393: * <td>false</td>
0394: * <td>The tooltip stays fixed on its inital position until anohter tooltip is activated, or the user clicks on the document.</td>
0395: * </tr>
0396: * <tr>
0397: * <td>tooltipStayAppearTime</td>
0398: * <td>String</td>
0399: * <td>0</td>
0400: * <td>Specifies a time span in miliseconds after which the tooltip disappears, even if the mousepointer is still on the concerned HTML element, with value <=0 it acts as if no time span is defined</td>
0401: * </tr>
0402: * <tr>
0403: * <td>tooltipTextAlign</td>
0404: * <td>String</td>
0405: * <td>left</td>
0406: * <td>Aligns the text of both the title and the body of the tooltip. Either right, left or justify</td>
0407: * </tr>
0408: * <tr>
0409: * <td>tooltipTitle</td>
0410: * <td>String</td>
0411: * <td>none</td>
0412: * <td>title</td>
0413: * </tr>
0414: * <tr>
0415: * <td>tooltipTitleColor</td>
0416: * <td>String</td>
0417: * <td>#ffffff</td>
0418: * <td>Color of the title text</td>
0419: * </tr>
0420: * <tr>
0421: * <td>tooltipWidth</td>
0422: * <td>String</td>
0423: * <td>300</td>
0424: * <td>Width of tooltip</td>
0425: * </tr>
0426: * </table>
0427: *
0428: * <!-- END SNIPPET: tooltipattributes -->
0429: *
0430: *
0431: * <!-- START SNIPPET: tooltipdescription -->
0432: *
0433: * Every Form UI component (in xhtml / css_xhtml or any others that extends of them) could
0434: * have tooltip assigned to a them. The Form component's tooltip related attribute once
0435: * defined will be applicable to all form UI component that is created under it unless
0436: * explicitly overriden by having the Form UI component itself defined that tooltip attribute.
0437: *
0438: * <p/>
0439: *
0440: * In Example 1, the textfield will inherit the tooltipAboveMousePointer attribte from
0441: * its containing form. In other words, although it doesn't defined a tooltipAboveMousePointer
0442: * attribute, it will have that attribute defined as true inherited from its containing form.
0443: *
0444: * <p/>
0445: *
0446: * In Example 2, the the textfield will inherite both the tooltipAboveMousePointer and
0447: * tooltipLeftOfMousePointer attribute from its containing form but tooltipLeftOfMousePointer
0448: * attribute is overriden at the textfield itself. Hence, the textfield actually will
0449: * have tooltipAboveMousePointer defined as true, inherited from its containing form and
0450: * tooltipLeftOfMousePointer defined as false, due to overriden at the textfield itself.
0451: *
0452: * <p/>
0453: *
0454: * Example 3, 4 and 5 shows different way of setting the tooltipConfig attribute.<br/>
0455: * <b>Example 3:</b>Set tooltip config through body of param tag<br/>
0456: * <b>Example 4:</b>Set tooltip config through value attribute of param tag<br/>
0457: * <b>Example 5:</b>Set tooltip config through tooltipConfig attribute of component tag<br/>
0458: *
0459: * <!-- END SNIPPET: tooltipdescription -->
0460: *
0461: *
0462: * <pre>
0463: * <!-- START SNIPPET: tooltipexample -->
0464: *
0465: * <!-- Example 1: -->
0466: * <ww:form
0467: * tooltipConfig="#{'tooltipAboveMousePointer':'true',
0468: * 'tooltipBgColor='#eeeeee'}" .... >
0469: * ....
0470: * <ww:textfield label="Customer Name" tooltip="Enter the customer name" .... />
0471: * ....
0472: * </ww:form>
0473: *
0474: * <!-- Example 2: -->
0475: * <ww:form
0476: * tooltipConfig="#{'tooltipAboveMousePointer':'true',
0477: * 'tooltipLeftOfMousePointer':'true'}" ... >
0478: * ....
0479: * <ww:textfield label="Address"
0480: * tooltip="Enter your address"
0481: * tooltipConfig="#{'tooltipLeftOfMousePointer':'false'}" />
0482: * ....
0483: * </ww:form>
0484: *
0485: *
0486: * <-- Example 3: -->
0487: * <ww:textfield
0488: * label="Customer Name"
0489: * tooltip="One of our customer Details'">
0490: * <ww:param name="tooltipConfig">
0491: * tooltipWidth = 150 |
0492: * tooltipAboveMousePointer = false |
0493: * tooltipLeftOfMousePointer = false
0494: * </ww:param>
0495: * </ww:textfield>
0496: *
0497: *
0498: * <-- Example 4: -->
0499: * <ww:textfield
0500: * label="Customer Address"
0501: * tooltip="Enter The Customer Address" >
0502: * <ww:param
0503: * name="tooltipConfig"
0504: * value="#{'tooltipStatic':'true',
0505: * 'tooltipSticky':'true',
0506: * 'tooltipAboveMousePointer':'false',
0507: * 'tooltipLeftOfMousePointer':'false'}" />
0508: * </ww:textfield>
0509: *
0510: *
0511: * <-- Example 5: -->
0512: * <ww:textfield
0513: * label="Customer Telephone Number"
0514: * tooltip="Enter customer Telephone Number"
0515: * tooltipConfig="#{'tooltipBgColor':'#cccccc',
0516: * 'tooltipFontColor':'#eeeeee',
0517: * 'tooltipAboveMousePointer':'false',
0518: * 'tooltipLeftOfMousePointer':'false'}" /<
0519: *
0520: * <!-- END SNIPPET: tooltipexample -->
0521: * </pre>
0522: *
0523: *
0524: * @author Patrick Lightbody
0525: * @author Rene Gielen
0526: * @author Rainer Hermanns
0527: * @author tm_jee
0528: * @version $Revision: 2929 $
0529: * @since 2.2
0530: */
0531: public abstract class UIBean extends Component {
0532: private static final Log LOG = LogFactory.getLog(UIBean.class);
0533:
0534: protected HttpServletRequest request;
0535: protected HttpServletResponse response;
0536:
0537: public UIBean(OgnlValueStack stack, HttpServletRequest request,
0538: HttpServletResponse response) {
0539: super (stack);
0540: this .request = request;
0541: this .response = response;
0542: this .templateSuffix = ContextUtil.getTemplateSuffix(stack
0543: .getContext());
0544: }
0545:
0546: // The templateSuffic to use, overrides the default one if not null.
0547: protected String templateSuffix;
0548:
0549: // The template to use, overrides the default one.
0550: protected String template;
0551:
0552: // templateDir and theme attributes
0553: protected String templateDir;
0554: protected String theme;
0555:
0556: protected String cssClass;
0557: protected String cssStyle;
0558: protected String disabled;
0559: protected String label;
0560: protected String labelPosition;
0561: protected String requiredposition;
0562: protected String name;
0563: protected String required;
0564: protected String tabindex;
0565: protected String value;
0566: protected String title;
0567:
0568: // HTML scripting events attributes
0569: protected String onclick;
0570: protected String ondblclick;
0571: protected String onmousedown;
0572: protected String onmouseup;
0573: protected String onmouseover;
0574: protected String onmousemove;
0575: protected String onmouseout;
0576: protected String onfocus;
0577: protected String onblur;
0578: protected String onkeypress;
0579: protected String onkeydown;
0580: protected String onkeyup;
0581: protected String onselect;
0582: protected String onchange;
0583:
0584: // common html attributes
0585: protected String accesskey;
0586:
0587: // javascript tooltip attribute
0588: protected String tooltip;
0589: protected String tooltipConfig;
0590:
0591: public boolean end(Writer writer, String body) {
0592: evaluateParams();
0593: Template _template = null;
0594: try {
0595: _template = buildTemplateName(template,
0596: getDefaultTemplate());
0597: super .end(writer, body, false);
0598: mergeTemplate(writer, _template);
0599: } catch (Exception e) {
0600: LOG.error("an exception occurred while merging themplate ["
0601: + _template + "]", e);
0602: } finally {
0603: popComponentStack();
0604: }
0605:
0606: return false;
0607: }
0608:
0609: /**
0610: * A contract that requires each concrete UI Tag to specify which template should be used as a default. For
0611: * example, the CheckboxTab might return "checkbox.vm" while the RadioTag might return "radio.vm". This value
0612: * <strong>not</strong> begin with a '/' unless you intend to make the path absolute rather than relative to the
0613: * current theme.
0614: *
0615: * @return The name of the template to be used as the default.
0616: */
0617: protected abstract String getDefaultTemplate();
0618:
0619: protected Template buildTemplateName(String myTemplate,
0620: String myDefaultTemplate) {
0621: String template = myDefaultTemplate;
0622:
0623: if (myTemplate != null) {
0624: template = findString(myTemplate);
0625: }
0626:
0627: String templateDir = getTemplateDir();
0628: String theme = getTheme();
0629:
0630: return new Template(templateDir, theme, template);
0631:
0632: }
0633:
0634: protected void mergeTemplate(Writer writer, Template template)
0635: throws Exception {
0636: final TemplateEngine engine = TemplateEngineManager
0637: .getTemplateEngine(template, templateSuffix);
0638: if (engine == null) {
0639: throw new ConfigurationException(
0640: "Unable to find a TemplateEngine for template "
0641: + template);
0642: }
0643:
0644: if (LOG.isDebugEnabled()) {
0645: LOG.debug("Rendering template " + template);
0646: }
0647:
0648: final TemplateRenderingContext context = new TemplateRenderingContext(
0649: template, writer, getStack(), getParameters(), this );
0650: engine.renderTemplate(context);
0651: }
0652:
0653: public String getTemplateDir() {
0654: String templateDir = null;
0655:
0656: if (this .templateDir != null) {
0657: templateDir = findString(this .templateDir);
0658: }
0659:
0660: // If templateDir is not explicitly given,
0661: // try to find attribute which states the dir set to use
0662: if ((templateDir == null) || (templateDir.equals(""))) {
0663: templateDir = (String) stack.findValue("#attr.templateDir");
0664: }
0665:
0666: // Default template set
0667: if ((templateDir == null) || (templateDir.equals(""))) {
0668: templateDir = Configuration
0669: .getString(WebWorkConstants.WEBWORK_UI_TEMPLATEDIR);
0670: }
0671:
0672: // Defaults to 'template'
0673: if ((templateDir == null) || (templateDir.equals(""))) {
0674: templateDir = "template";
0675: }
0676:
0677: return templateDir;
0678: }
0679:
0680: public String getTheme() {
0681: String theme = null;
0682:
0683: if (this .theme != null) {
0684: theme = findString(this .theme);
0685: }
0686:
0687: if (theme == null || theme.equals("")) {
0688: Form form = (Form) findAncestor(Form.class);
0689: if (form != null) {
0690: theme = form.getTheme();
0691: }
0692: }
0693:
0694: // If theme set is not explicitly given,
0695: // try to find attribute which states the theme set to use
0696: if ((theme == null) || (theme.equals(""))) {
0697: theme = (String) stack.findValue("#attr.theme");
0698: }
0699:
0700: // Default theme set
0701: if ((theme == null) || (theme.equals(""))) {
0702: theme = Configuration
0703: .getString(WebWorkConstants.WEBWORK_UI_THEME);
0704: }
0705:
0706: return theme;
0707: }
0708:
0709: public void evaluateParams() {
0710: addParameter("templateDir", getTemplateDir());
0711: addParameter("theme", getTheme());
0712:
0713: String name = null;
0714:
0715: if (this .name != null) {
0716: name = findString(this .name);
0717: addParameter("name", name);
0718: }
0719:
0720: if (label != null) {
0721: addParameter("label", findString(label));
0722: }
0723:
0724: if (labelPosition != null) {
0725: addParameter("labelposition", findString(labelPosition));
0726: }
0727:
0728: if (requiredposition != null) {
0729: addParameter("requiredposition",
0730: findString(requiredposition));
0731: }
0732:
0733: if (required != null) {
0734: addParameter("required", findValue(required, Boolean.class));
0735: }
0736:
0737: if (disabled != null) {
0738: addParameter("disabled", findValue(disabled, Boolean.class));
0739: }
0740:
0741: if (tabindex != null) {
0742: addParameter("tabindex", findString(tabindex));
0743: }
0744:
0745: if (onclick != null) {
0746: addParameter("onclick", findString(onclick));
0747: }
0748:
0749: if (ondblclick != null) {
0750: addParameter("ondblclick", findString(ondblclick));
0751: }
0752:
0753: if (onmousedown != null) {
0754: addParameter("onmousedown", findString(onmousedown));
0755: }
0756:
0757: if (onmouseup != null) {
0758: addParameter("onmouseup", findString(onmouseup));
0759: }
0760:
0761: if (onmouseover != null) {
0762: addParameter("onmouseover", findString(onmouseover));
0763: }
0764:
0765: if (onmousemove != null) {
0766: addParameter("onmousemove", findString(onmousemove));
0767: }
0768:
0769: if (onmouseout != null) {
0770: addParameter("onmouseout", findString(onmouseout));
0771: }
0772:
0773: if (onfocus != null) {
0774: addParameter("onfocus", findString(onfocus));
0775: }
0776:
0777: if (onblur != null) {
0778: addParameter("onblur", findString(onblur));
0779: }
0780:
0781: if (onkeypress != null) {
0782: addParameter("onkeypress", findString(onkeypress));
0783: }
0784:
0785: if (onkeydown != null) {
0786: addParameter("onkeydown", findString(onkeydown));
0787: }
0788:
0789: if (onkeyup != null) {
0790: addParameter("onkeyup", findString(onkeyup));
0791: }
0792:
0793: if (onselect != null) {
0794: addParameter("onselect", findString(onselect));
0795: }
0796:
0797: if (onchange != null) {
0798: addParameter("onchange", findString(onchange));
0799: }
0800:
0801: if (accesskey != null) {
0802: addParameter("accesskey", findString(accesskey));
0803: }
0804:
0805: if (cssClass != null) {
0806: addParameter("cssClass", findString(cssClass));
0807: }
0808:
0809: if (cssStyle != null) {
0810: addParameter("cssStyle", findString(cssStyle));
0811: }
0812:
0813: if (title != null) {
0814: addParameter("title", findString(title));
0815: }
0816:
0817: // see if the value was specified as a parameter already
0818: if (parameters.containsKey("value")) {
0819: parameters.put("nameValue", parameters.get("value"));
0820: } else {
0821: if (evaluateNameValue()) {
0822: final Class valueClazz = getValueClassType();
0823:
0824: if (valueClazz != null) {
0825: if (value != null) {
0826: addParameter("nameValue", findValue(value,
0827: valueClazz));
0828: } else if (name != null) {
0829: String expr = name;
0830: if (altSyntax()) {
0831: expr = "%{" + expr + "}";
0832: }
0833:
0834: addParameter("nameValue", findValue(expr,
0835: valueClazz));
0836: }
0837: } else {
0838: if (value != null) {
0839: addParameter("nameValue", findValue(value));
0840: } else if (name != null) {
0841: addParameter("nameValue", findValue(name));
0842: }
0843: }
0844: }
0845: }
0846:
0847: final Form form = (Form) findAncestor(Form.class);
0848:
0849: // create HTML id element
0850: populateComponentHtmlId(form);
0851:
0852: if (form != null) {
0853: addParameter("form", form.getParameters());
0854:
0855: if (name != null) {
0856: // list should have been created by the form component
0857: List tags = (List) form.getParameters().get("tagNames");
0858: tags.add(name);
0859: }
0860: }
0861:
0862: // tooltip & tooltipConfig
0863: if (tooltipConfig != null) {
0864: addParameter("tooltipConfig", findValue(tooltipConfig));
0865: }
0866: if (tooltip != null) {
0867: addParameter("tooltip", findString(tooltip));
0868:
0869: Map tooltipConfigMap = getTooltipConfig(this );
0870:
0871: if (tooltipConfigMap.containsKey("tooltipIcon")) {
0872: addParameter("tooltipIcon", tooltipConfigMap
0873: .get("tooltipIcon"));
0874: }
0875:
0876: if (form != null) { // inform the containing form that we need tooltip javascript included
0877: form.addParameter("hasTooltip", Boolean.TRUE);
0878:
0879: // tooltipConfig defined in component itseilf will take precedence
0880: // over those defined in the containing form
0881: Map overallTooltipConfigMap = getTooltipConfig(form);
0882: overallTooltipConfigMap.putAll(tooltipConfigMap); // override parent form's tooltip config
0883:
0884: for (Iterator i = overallTooltipConfigMap.entrySet()
0885: .iterator(); i.hasNext();) {
0886: Map.Entry entry = (Map.Entry) i.next();
0887: addParameter((String) entry.getKey(), entry
0888: .getValue());
0889: }
0890: } else {
0891: LOG
0892: .warn("No ancestor Form found, javascript based tooltip will not work, however standard HTML tooltip using alt and title attribute will still work ");
0893: }
0894: }
0895: evaluateExtraParams();
0896:
0897: }
0898:
0899: protected String escape(String name) {
0900: // escape any possible values that can make the ID painful to work with in JavaScript
0901: if (name != null) {
0902: return name.replaceAll("[\\.\\[\\]]", "_");
0903: } else {
0904: return "";
0905: }
0906: }
0907:
0908: protected void evaluateExtraParams() {
0909: }
0910:
0911: protected boolean evaluateNameValue() {
0912: return true;
0913: }
0914:
0915: protected Class getValueClassType() {
0916: return String.class;
0917: }
0918:
0919: public void addFormParameter(String key, Object value) {
0920: Form form = (Form) findAncestor(Form.class);
0921: if (form != null) {
0922: form.addParameter(key, value);
0923: }
0924: }
0925:
0926: protected void enableAncestorFormCustomOnsubmit() {
0927: Form form = (Form) findAncestor(Form.class);
0928: if (form != null) {
0929: form.addParameter("customOnsubmitEnabled", Boolean.TRUE);
0930: } else {
0931: LOG
0932: .warn("Cannot find an Ancestor form, custom onsubmit is NOT enabled");
0933: }
0934: }
0935:
0936: protected Map getTooltipConfig(UIBean component) {
0937: Object tooltipConfigObj = component.getParameters().get(
0938: "tooltipConfig");
0939: Map tooltipConfig = new LinkedHashMap();
0940:
0941: if (tooltipConfigObj instanceof Map) {
0942: // we get this if its configured using
0943: // 1] UI component's tooltipConfig attribute OR
0944: // 2] <param name="tooltip" value="" /> param tag value attribute
0945:
0946: tooltipConfig = new LinkedHashMap((Map) tooltipConfigObj);
0947: } else if (tooltipConfigObj instanceof String) {
0948:
0949: // we get this if its configured using
0950: // <param name="tooltipConfig"> ... </param> tag's body
0951: String tooltipConfigStr = (String) tooltipConfigObj;
0952: String[] tooltipConfigArray = tooltipConfigStr.split("\\|");
0953:
0954: for (int a = 0; a < tooltipConfigArray.length; a++) {
0955: String[] configEntry = ((String) tooltipConfigArray[a]
0956: .trim()).split("=");
0957: String key = configEntry[0].trim();
0958: String value = null;
0959: if (configEntry.length > 1) {
0960: value = configEntry[1].trim();
0961: tooltipConfig.put(key, value.toString());
0962: } else {
0963: LOG.warn("component " + component
0964: + " tooltip config param " + key
0965: + " has no value defined, skipped");
0966: }
0967: }
0968: }
0969: return tooltipConfig;
0970: }
0971:
0972: /**
0973: * Create HTML id element for the component and populate this component parmaeter
0974: * map.
0975: *
0976: * The order is as follows :-
0977: * <ol>
0978: * <li>This component id attribute</li>
0979: * <li>[containing_form_id]_[this_component_name]</li>
0980: * <li>[this_component_name]</li>
0981: * </ol>
0982: *
0983: * @param form
0984: */
0985: protected void populateComponentHtmlId(Form form) {
0986: if (id != null) {
0987: // this check is needed for backwards compatibility with 2.1.x
0988: if (altSyntax()) {
0989: addParameter("id", findString(id));
0990: } else {
0991: addParameter("id", id);
0992: }
0993: } else if (form != null) {
0994: addParameter("id", form.getParameters().get("id") + "_"
0995: + escape(name == null ? null : findString(name)));
0996: } else {
0997: addParameter("id", escape(name == null ? null
0998: : findString(name)));
0999: }
1000: }
1001:
1002: /**
1003: * The theme (other than default) to use for rendering the element
1004: * @ww.tagattribute required="false"
1005: */
1006: public void setTheme(String theme) {
1007: this .theme = theme;
1008: }
1009:
1010: public String getTemplate() {
1011: return template;
1012: }
1013:
1014: /**
1015: * The template directory (other than default) to used to find the themes and hence the template.
1016: * @ww.tagattribute required="false"
1017: */
1018: public void setTemplateDir(String templateDir) {
1019: this .templateDir = templateDir;
1020: }
1021:
1022: /**
1023: * The template (other than default) to use for rendering the element
1024: * @ww.tagattribute required="false"
1025: */
1026: public void setTemplate(String template) {
1027: this .template = template;
1028: }
1029:
1030: /**
1031: * The css class to use for element
1032: * @ww.tagattribute required="false"
1033: */
1034: public void setCssClass(String cssClass) {
1035: this .cssClass = cssClass;
1036: }
1037:
1038: /**
1039: * The css style definitions for element ro use
1040: * @ww.tagattribute required="false"
1041: */
1042: public void setCssStyle(String cssStyle) {
1043: this .cssStyle = cssStyle;
1044: }
1045:
1046: /**
1047: * Set the html title attribute on rendered html element
1048: * @ww.tagattribute required="false"
1049: */
1050: public void setTitle(String title) {
1051: this .title = title;
1052: }
1053:
1054: /**
1055: * Set the html disabled attribute on rendered html element
1056: * @ww.tagattribute required="false"
1057: */
1058: public void setDisabled(String disabled) {
1059: this .disabled = disabled;
1060: }
1061:
1062: /**
1063: * Label expression used for rendering a element specific label
1064: * @ww.tagattribute required="false"
1065: */
1066: public void setLabel(String label) {
1067: this .label = label;
1068: }
1069:
1070: /**
1071: * deprecated.
1072: * @ww.tagattribute required="false" default="left"
1073: * @deprecated please use {@link #setLabelposition(String)} instead
1074: */
1075: public void setLabelPosition(String labelPosition) {
1076: this .labelPosition = labelPosition;
1077: }
1078:
1079: /**
1080: * define label position of form element (top/left)
1081: * @ww.tagattribute required="false"
1082: */
1083: public void setLabelposition(String labelPosition) {
1084: this .labelPosition = labelPosition;
1085: }
1086:
1087: /**
1088: * define required position of required form element (left|right)
1089: * @ww.tagattribute required="false"
1090: */
1091: public void setRequiredposition(String requiredposition) {
1092: this .requiredposition = requiredposition;
1093: }
1094:
1095: /**
1096: * The name to set for element
1097: * @ww.tagattribute required="false"
1098: */
1099: public void setName(String name) {
1100: this .name = name;
1101: }
1102:
1103: /**
1104: * If set to true, the rendered element will indicate that input is required
1105: * @ww.tagattribute required="false" type="Boolean" default="false"
1106: */
1107: public void setRequired(String required) {
1108: this .required = required;
1109: }
1110:
1111: /**
1112: * Set the html tabindex attribute on rendered html element
1113: * @ww.tagattribute required="false"
1114: */
1115: public void setTabindex(String tabindex) {
1116: this .tabindex = tabindex;
1117: }
1118:
1119: /**
1120: * Preset the value of input element.
1121: * @ww.tagattribute required="false"
1122: */
1123: public void setValue(String value) {
1124: this .value = value;
1125: }
1126:
1127: /**
1128: * Set the html onclick attribute on rendered html element
1129: * @ww.tagattribute required="false"
1130: */
1131: public void setOnclick(String onclick) {
1132: this .onclick = onclick;
1133: }
1134:
1135: /**
1136: * Set the html ondblclick attribute on rendered html element
1137: * @ww.tagattribute required="false"
1138: */
1139: public void setOndblclick(String ondblclick) {
1140: this .ondblclick = ondblclick;
1141: }
1142:
1143: /**
1144: * Set the html onmousedown attribute on rendered html element
1145: * @ww.tagattribute required="false"
1146: */
1147: public void setOnmousedown(String onmousedown) {
1148: this .onmousedown = onmousedown;
1149: }
1150:
1151: /**
1152: * Set the html onmouseup attribute on rendered html element
1153: * @ww.tagattribute required="false"
1154: */
1155: public void setOnmouseup(String onmouseup) {
1156: this .onmouseup = onmouseup;
1157: }
1158:
1159: /**
1160: * Set the html onmouseover attribute on rendered html element
1161: * @ww.tagattribute required="false"
1162: */
1163: public void setOnmouseover(String onmouseover) {
1164: this .onmouseover = onmouseover;
1165: }
1166:
1167: /**
1168: * Set the html onmousemove attribute on rendered html element
1169: * @ww.tagattribute required="false"
1170: */
1171: public void setOnmousemove(String onmousemove) {
1172: this .onmousemove = onmousemove;
1173: }
1174:
1175: /**
1176: * Set the html onmouseout attribute on rendered html element
1177: * @ww.tagattribute required="false"
1178: */
1179: public void setOnmouseout(String onmouseout) {
1180: this .onmouseout = onmouseout;
1181: }
1182:
1183: /**
1184: * Set the html onfocus attribute on rendered html element
1185: * @ww.tagattribute required="false"
1186: */
1187: public void setOnfocus(String onfocus) {
1188: this .onfocus = onfocus;
1189: }
1190:
1191: /**
1192: * Set the html onblur attribute on rendered html element
1193: * @ww.tagattribute required="false"
1194: */
1195: public void setOnblur(String onblur) {
1196: this .onblur = onblur;
1197: }
1198:
1199: /**
1200: * Set the html onkeypress attribute on rendered html element
1201: * @ww.tagattribute required="false"
1202: */
1203: public void setOnkeypress(String onkeypress) {
1204: this .onkeypress = onkeypress;
1205: }
1206:
1207: /**
1208: * Set the html onkeydown attribute on rendered html element
1209: * @ww.tagattribute required="false"
1210: */
1211: public void setOnkeydown(String onkeydown) {
1212: this .onkeydown = onkeydown;
1213: }
1214:
1215: /**
1216: * Set the html onkeyup attribute on rendered html element
1217: * @ww.tagattribute required="false"
1218: */
1219: public void setOnkeyup(String onkeyup) {
1220: this .onkeyup = onkeyup;
1221: }
1222:
1223: /**
1224: * Set the html onselect attribute on rendered html element
1225: * @ww.tagattribute required="false"
1226: */
1227: public void setOnselect(String onselect) {
1228: this .onselect = onselect;
1229: }
1230:
1231: /**
1232: * Set the html onchange attribute on rendered html element
1233: * @ww.tagattribute required="false"
1234: */
1235: public void setOnchange(String onchange) {
1236: this .onchange = onchange;
1237: }
1238:
1239: /**
1240: * Set the html accesskey attribute on rendered html ekement
1241: * @ww.tagattribute required="false"
1242: */
1243: public void setAccesskey(String accesskey) {
1244: this .accesskey = accesskey;
1245: }
1246:
1247: /**
1248: * Set the tooltip of this particular component
1249: * @ww.tagattribute required="false" type="String" default=""
1250: */
1251: public void setTooltip(String tooltip) {
1252: this .tooltip = tooltip;
1253: }
1254:
1255: /**
1256: * Set the tooltip configuration
1257: * @ww.tagattribute required="false" type="String" default=""
1258: */
1259: public void setTooltipConfig(String tooltipConfig) {
1260: this.tooltipConfig = tooltipConfig;
1261: }
1262: }
|