| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.struts2.components; |
| |
| import com.opensymphony.xwork2.config.ConfigurationException; |
| import com.opensymphony.xwork2.inject.Inject; |
| import com.opensymphony.xwork2.util.ValueStack; |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.logging.log4j.LogManager; |
| import org.apache.logging.log4j.Logger; |
| import org.apache.struts2.StrutsConstants; |
| import org.apache.struts2.StrutsException; |
| import org.apache.struts2.components.template.Template; |
| import org.apache.struts2.components.template.TemplateEngine; |
| import org.apache.struts2.components.template.TemplateEngineManager; |
| import org.apache.struts2.components.template.TemplateRenderingContext; |
| import org.apache.struts2.util.TextProviderHelper; |
| import org.apache.struts2.views.TagAttribute; |
| import org.apache.struts2.views.annotations.StrutsTagAttribute; |
| import org.apache.struts2.views.util.ContextUtil; |
| |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import java.io.Writer; |
| import java.util.HashMap; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * <p> |
| * UIBean is the standard superclass of all Struts UI components. |
| * It defines common Struts and html properties all UI components should present for usage. |
| * </p> |
| * <!-- START SNIPPET: templateRelatedAttributes --> |
| * |
| * <table border="1" summary=""> |
| * <thead> |
| * <tr> |
| * <td>Attribute</td> |
| * <td>Theme</td> |
| * <td>Data Types</td> |
| * <td>Description</td> |
| * </tr> |
| * </thead> |
| * <tbody> |
| * <tr> |
| * <td>templateDir</td> |
| * <td>n/a</td> |
| * <td>String</td> |
| * <td>define the template directory</td> |
| * </tr> |
| * <tr> |
| * <td>theme</td> |
| * <td>n/a</td> |
| * <td>String</td> |
| * <td>define the theme name</td> |
| * </tr> |
| * <tr> |
| * <td>template</td> |
| * <td>n/a</td> |
| * <td>String</td> |
| * <td>define the template name</td> |
| * </tr> |
| * <tr> |
| * <td>themeExpansionToken</td> |
| * <td>n/a</td> |
| * <td>String</td> |
| * <td>special token (defined with struts.ui.theme.expansion.token) used to search for template in parent theme |
| * (don't use it separately!)</td> |
| * </tr> |
| * <tr> |
| * <td>expandTheme</td> |
| * <td>n/a</td> |
| * <td>String</td> |
| * <td>concatenation of themeExpansionToken and theme which tells internal template loader mechanism |
| * to try load template from current theme and then from parent theme (and parent theme, and so on) |
| * when used with <#include/> directive</td> |
| * </tr> |
| * </tbody> |
| * </table> |
| * |
| * <!-- END SNIPPET: templateRelatedAttributes --> |
| * |
| * <!-- START SNIPPET: generalAttributes --> |
| * |
| * <table border="1" summary=""> |
| * <thead> |
| * <tr> |
| * <td>Attribute</td> |
| * <td>Theme</td> |
| * <td>Data Types</td> |
| * <td>Description</td> |
| * </tr> |
| * </thead> |
| * <tbody> |
| * <tr> |
| * <td>cssClass</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>define html class attribute</td> |
| * </tr> |
| * <tr> |
| * <td>cssStyle</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>define html style attribute</td> |
| * </tr> |
| * <tr> |
| * <td>cssErrorClass</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>error class attribute</td> |
| * </tr> |
| * <tr> |
| * <td>cssErrorStyle</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>error style attribute</td> |
| * </tr> |
| * <tr> |
| * <td>title</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>define html title attribute</td> |
| * </tr> |
| * <tr> |
| * <td>disabled</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>define html disabled attribute</td> |
| * </tr> |
| * <tr> |
| * <td>label</td> |
| * <td>xhtml</td> |
| * <td>String</td> |
| * <td>define label of form element</td> |
| * </tr> |
| * <tr> |
| * <td>labelPosition</td> |
| * <td>xhtml</td> |
| * <td>String</td> |
| * <td>define label position of form element (top/left), default to left</td> |
| * </tr> |
| * <tr> |
| * <td>requiredPosition</td> |
| * <td>xhtml</td> |
| * <td>String</td> |
| * <td>define required label position of form element (left/right), default to right</td> |
| * </tr> |
| * <tr> |
| * <td>errorPosition</td> |
| * <td>xhtml</td> |
| * <td>String</td> |
| * <td>define error position of form element (top|bottom), default to top</td> |
| * </tr> |
| * <tr> |
| * <td>name</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>Form Element's field name mapping</td> |
| * </tr> |
| * <tr> |
| * <td>requiredLabel</td> |
| * <td>xhtml</td> |
| * <td>Boolean</td> |
| * <td>add * to label (true to add false otherwise)</td> |
| * </tr> |
| * <tr> |
| * <td>tabIndex</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>define html tabindex attribute</td> |
| * </tr> |
| * <tr> |
| * <td>value</td> |
| * <td>simple</td> |
| * <td>Object</td> |
| * <td>define value of form element</td> |
| * </tr> |
| * </tbody> |
| * </table> |
| * |
| * <!-- END SNIPPET: generalAttributes --> |
| * |
| * <!-- START SNIPPET: javascriptRelatedAttributes --> |
| * |
| * <table border="1" summary=""> |
| * <thead> |
| * <tr> |
| * <td>Attribute</td> |
| * <td>Theme</td> |
| * <td>Data Types</td> |
| * <td>Description</td> |
| * </tr> |
| * </thead> |
| * <tbody> |
| * <tr> |
| * <td>onclick</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onclick attribute</td> |
| * </tr> |
| * <tr> |
| * <td>ondblclick</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript ondbclick attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onmousedown</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onmousedown attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onmouseup</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onmouseup attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onmouseover</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onmouseover attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onmouseout</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onmouseout attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onfocus</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onfocus attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onblur</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onblur attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onkeypress</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onkeypress attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onkeyup</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onkeyup attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onkeydown</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onkeydown attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onselect</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onselect attribute</td> |
| * </tr> |
| * <tr> |
| * <td>onchange</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>html javascript onchange attribute</td> |
| * </tr> |
| * </tbody> |
| * </table> |
| * |
| * <!-- END SNIPPET: javascriptRelatedAttributes --> |
| * |
| * <!-- START SNIPPET: tooltipattributes --> |
| * |
| * <table border="1" summary=""> |
| * <tr> |
| * <td>Attribute</td> |
| * <td>Data Type</td> |
| * <td>Default</td> |
| * <td>Description</td> |
| * </tr> |
| * <tr> |
| * <td>tooltip</td> |
| * <td>String</td> |
| * <td>none</td> |
| * <td>Set the tooltip of this particular component</td> |
| * </tr> |
| * <tr> |
| * <td>jsTooltipEnabled</td> |
| * <td>String</td> |
| * <td>false</td> |
| * <td>Enable js tooltip rendering</td> |
| * </tr> |
| * <tr> |
| * <td>tooltipIcon</td> |
| * <td>String</td> |
| * <td>/struts/static/tooltip/tooltip.gif</td> |
| * <td>The url to the tooltip icon</td> |
| * <tr> |
| * <td>tooltipDelay</td> |
| * <td>String</td> |
| * <td>500</td> |
| * <td>Tooltip shows up after the specified timeout (miliseconds). A behavior similar to that of OS based tooltips.</td> |
| * </tr> |
| * <tr> |
| * <td>key</td> |
| * <td>simple</td> |
| * <td>String</td> |
| * <td>The name of the property this input field represents. This will auto populate the name, label, and value</td> |
| * </tr> |
| * </table> |
| * |
| * <!-- END SNIPPET: tooltipattributes --> |
| * |
| * |
| * <!-- START SNIPPET: tooltipdescription --> |
| * <p> |
| * <b>tooltipConfig is deprecated, use individual tooltip configuration attributes instead </b> |
| * </p> |
| * |
| * <p> |
| * Every Form UI component (in xhtml / css_xhtml or any other that extends them) can |
| * have tooltips assigned to them. The Form component's tooltip related attribute, once |
| * defined, will be applied to all form UI components that are created under it unless |
| * explicitly overridden by having the Form UI component itself defined with their own tooltip attribute. |
| * </p> |
| * |
| * <p> |
| * In Example 1, the textfield will inherit the tooltipDelay and tooltipIconPath attribute from |
| * its containing form. In other words, although it doesn't define a tooltipIconPath |
| * attribute, it will have that attribute inherited from its containing form. |
| * </p> |
| * |
| * <p> |
| * In Example 2, the textfield will inherit both the tooltipDelay and |
| * tooltipIconPath attribute from its containing form, but the tooltipDelay |
| * attribute is overridden at the textfield itself. Hence, the textfield actually will |
| * have its tooltipIcon defined as /myImages/myIcon.gif, inherited from its containing form, and |
| * tooltipDelay defined as 5000. |
| * </p> |
| * |
| * <p> |
| * Example 3, 4 and 5 show different ways of setting the tooltip configuration attribute.<br> |
| * <b>Example 3:</b> Set tooltip config through the body of the param tag<br> |
| * <b>Example 4:</b> Set tooltip config through the value attribute of the param tag<br> |
| * <b>Example 5:</b> Set tooltip config through the tooltip attributes of the component tag<br> |
| * </p> |
| * |
| * <!-- END SNIPPET: tooltipdescription --> |
| * |
| * |
| * <pre> |
| * <!-- START SNIPPET: tooltipexample --> |
| * |
| * <!-- Example 1: --> |
| * <s:form |
| * tooltipDelay="500" |
| * tooltipIconPath="/myImages/myIcon.gif" .... > |
| * .... |
| * <s:textfield label="Customer Name" tooltip="Enter the customer name" .... /> |
| * .... |
| * </s:form> |
| * |
| * <!-- Example 2: --> |
| * <s:form |
| * tooltipDelay="500" |
| * tooltipIconPath="/myImages/myIcon.gif" .... > |
| * .... |
| * <s:textfield label="Address" |
| * tooltip="Enter your address" |
| * tooltipDelay="5000" /> |
| * .... |
| * </s:form> |
| * |
| * |
| * <-- Example 3: --> |
| * <s:textfield |
| * label="Customer Name" |
| * tooltip="One of our customer Details"> |
| * <s:param name="tooltipDelay"> |
| * 500 |
| * </s:param> |
| * <s:param name="tooltipIconPath"> |
| * /myImages/myIcon.gif |
| * </s:param> |
| * </s:textfield> |
| * |
| * |
| * <-- Example 4: --> |
| * <s:textfield |
| * label="Customer Address" |
| * tooltip="Enter The Customer Address" > |
| * <s:param |
| * name="tooltipDelay" |
| * value="500" /> |
| * </s:textfield> |
| * |
| * |
| * <-- Example 5: --> |
| * <s:textfield |
| * label="Customer Telephone Number" |
| * tooltip="Enter customer Telephone Number" |
| * tooltipDelay="500" |
| * tooltipIconPath="/myImages/myIcon.gif" /> |
| * |
| * <!-- END SNIPPET: tooltipexample --> |
| * </pre> |
| * |
| */ |
| public abstract class UIBean extends Component { |
| private static final Logger LOG = LogManager.getLogger(UIBean.class); |
| |
| protected HttpServletRequest request; |
| protected HttpServletResponse response; |
| |
| public UIBean(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { |
| super(stack); |
| this.request = request; |
| this.response = response; |
| this.templateSuffix = ContextUtil.getTemplateSuffix(stack.getContext()); |
| } |
| |
| // The templateSuffic to use, overrides the default one if not null. |
| protected String templateSuffix; |
| |
| // The template to use, overrides the default one. |
| protected String template; |
| |
| // templateDir and theme attributes |
| protected String templateDir; |
| protected String theme; |
| |
| // shortcut, sets label, name, and value |
| protected String key; |
| |
| protected TagAttribute id = TagAttribute.NULL; |
| protected String cssClass; |
| protected String cssStyle; |
| protected String cssErrorClass; |
| protected String cssErrorStyle; |
| protected String disabled; |
| protected String label; |
| protected String labelPosition; |
| protected String labelSeparator; |
| protected String requiredPosition; |
| protected String errorPosition; |
| protected String name; |
| protected String requiredLabel; |
| protected String tabindex; |
| protected String value; |
| protected String title; |
| |
| // HTML scripting events attributes |
| protected String onclick; |
| protected String ondblclick; |
| protected String onmousedown; |
| protected String onmouseup; |
| protected String onmouseover; |
| protected String onmousemove; |
| protected String onmouseout; |
| protected String onfocus; |
| protected String onblur; |
| protected String onkeypress; |
| protected String onkeydown; |
| protected String onkeyup; |
| protected String onselect; |
| protected String onchange; |
| |
| // common html attributes |
| protected String accesskey; |
| |
| // javascript tooltip attribute |
| protected String tooltip; |
| protected String tooltipConfig; |
| protected String javascriptTooltip; |
| protected String tooltipDelay; |
| protected String tooltipCssClass; |
| protected String tooltipIconPath; |
| |
| // dynamic attributes |
| protected Map<String, Object> dynamicAttributes = new HashMap<>(); |
| |
| protected String defaultTemplateDir; |
| protected String defaultUITheme; |
| protected String uiThemeExpansionToken; |
| protected TemplateEngineManager templateEngineManager; |
| |
| @Inject(StrutsConstants.STRUTS_UI_TEMPLATEDIR) |
| public void setDefaultTemplateDir(String dir) { |
| this.defaultTemplateDir = dir; |
| } |
| |
| @Inject(StrutsConstants.STRUTS_UI_THEME) |
| public void setDefaultUITheme(String theme) { |
| this.defaultUITheme = theme; |
| } |
| |
| @Inject(StrutsConstants.STRUTS_UI_THEME_EXPANSION_TOKEN) |
| public void setUIThemeExpansionToken(String uiThemeExpansionToken) { |
| this.uiThemeExpansionToken = uiThemeExpansionToken; |
| } |
| |
| @Inject |
| public void setTemplateEngineManager(TemplateEngineManager mgr) { |
| this.templateEngineManager = mgr; |
| } |
| |
| @Override |
| public boolean end(Writer writer, String body) { |
| evaluateParams(); |
| try { |
| super.end(writer, body, false); |
| mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate())); |
| } catch (Exception e) { |
| throw new StrutsException(e); |
| } |
| finally { |
| popComponentStack(); |
| } |
| |
| return false; |
| } |
| |
| /** |
| * A contract that requires each concrete UI Tag to specify which template should be used as a default. For |
| * example, the CheckboxTab might return "checkbox.vm" while the RadioTag might return "radio.vm". This value |
| * <strong>not</strong> begin with a '/' unless you intend to make the path absolute rather than relative to the |
| * current theme. |
| * |
| * @return The name of the template to be used as the default. |
| */ |
| protected abstract String getDefaultTemplate(); |
| |
| protected Template buildTemplateName(String myTemplate, String myDefaultTemplate) { |
| String template = myDefaultTemplate; |
| |
| if (myTemplate != null) { |
| template = findString(myTemplate); |
| } |
| |
| String templateDir = getTemplateDir(); |
| String theme = getTheme(); |
| |
| return new Template(templateDir, theme, template); |
| |
| } |
| |
| protected void mergeTemplate(Writer writer, Template template) throws Exception { |
| final TemplateEngine engine = templateEngineManager.getTemplateEngine(template, templateSuffix); |
| if (engine == null) { |
| throw new ConfigurationException("Unable to find a TemplateEngine for template " + template); |
| } |
| |
| LOG.debug("Rendering template {}", template); |
| |
| final TemplateRenderingContext context = new TemplateRenderingContext(template, writer, getStack(), getParameters(), this); |
| engine.renderTemplate(context); |
| } |
| |
| public String getTemplateDir() { |
| String templateDir = null; |
| |
| if (this.templateDir != null) { |
| templateDir = findString(this.templateDir); |
| } |
| |
| // If templateDir is not explicitly given, |
| // try to find attribute which states the dir set to use |
| if (StringUtils.isBlank(templateDir)) { |
| templateDir = stack.findString("#attr.templateDir"); |
| } |
| |
| // Default template set |
| if (StringUtils.isBlank(templateDir)) { |
| templateDir = defaultTemplateDir; |
| } |
| |
| // Defaults to 'template' |
| if (StringUtils.isBlank(templateDir)) { |
| templateDir = "template"; |
| } |
| |
| return templateDir; |
| } |
| |
| public String getTheme() { |
| String theme = null; |
| |
| if (this.theme != null) { |
| theme = findString(this.theme); |
| } |
| |
| if (StringUtils.isBlank(theme)) { |
| Form form = (Form) findAncestor(Form.class); |
| if (form != null) { |
| theme = form.getTheme(); |
| } |
| } |
| |
| // If theme set is not explicitly given, |
| // try to find attribute which states the theme set to use |
| if (StringUtils.isBlank(theme)) { |
| theme = stack.findString("#attr.theme"); |
| } |
| |
| // Default theme set |
| if (StringUtils.isBlank(theme)) { |
| theme = defaultUITheme; |
| } |
| |
| return theme; |
| } |
| |
| public void evaluateParams() { |
| String templateDir = getTemplateDir(); |
| String theme = getTheme(); |
| |
| addParameter("templateDir", templateDir); |
| addParameter("theme", theme); |
| addParameter("template", template != null ? findString(template) : getDefaultTemplate()); |
| addParameter("dynamicAttributes", dynamicAttributes); |
| addParameter("themeExpansionToken", uiThemeExpansionToken); |
| addParameter("expandTheme", uiThemeExpansionToken + theme); |
| |
| String name = null; |
| String providedLabel = null; |
| |
| if (this.key != null) { |
| |
| if(this.name == null) { |
| this.name = key; |
| } |
| |
| if(this.label == null) { |
| // lookup the label from a TextProvider (default value is the key) |
| providedLabel = TextProviderHelper.getText(key, key, stack); |
| } |
| } |
| |
| if (this.name != null) { |
| name = findString(this.name); |
| addParameter("name", name); |
| } |
| |
| if (label != null) { |
| addParameter("label", findString(label)); |
| } else { |
| if (providedLabel != null) { |
| // label found via a TextProvider |
| addParameter("label", providedLabel); |
| } |
| } |
| |
| if (labelSeparator != null) { |
| addParameter("labelseparator", findString(labelSeparator)); |
| } |
| |
| if (labelPosition != null) { |
| addParameter("labelposition", findString(labelPosition)); |
| } |
| |
| if (requiredPosition != null) { |
| addParameter("requiredPosition", findString(requiredPosition)); |
| } |
| |
| if (errorPosition != null) { |
| addParameter("errorposition", findString(errorPosition)); |
| } |
| |
| if (requiredLabel != null) { |
| addParameter("required", findValue(requiredLabel, Boolean.class)); |
| } |
| |
| if (disabled != null) { |
| addParameter("disabled", findValue(disabled, Boolean.class)); |
| } |
| |
| if (tabindex != null) { |
| addParameter("tabindex", findString(tabindex)); |
| } |
| |
| if (onclick != null) { |
| addParameter("onclick", findString(onclick)); |
| } |
| |
| if (ondblclick != null) { |
| addParameter("ondblclick", findString(ondblclick)); |
| } |
| |
| if (onmousedown != null) { |
| addParameter("onmousedown", findString(onmousedown)); |
| } |
| |
| if (onmouseup != null) { |
| addParameter("onmouseup", findString(onmouseup)); |
| } |
| |
| if (onmouseover != null) { |
| addParameter("onmouseover", findString(onmouseover)); |
| } |
| |
| if (onmousemove != null) { |
| addParameter("onmousemove", findString(onmousemove)); |
| } |
| |
| if (onmouseout != null) { |
| addParameter("onmouseout", findString(onmouseout)); |
| } |
| |
| if (onfocus != null) { |
| addParameter("onfocus", findString(onfocus)); |
| } |
| |
| if (onblur != null) { |
| addParameter("onblur", findString(onblur)); |
| } |
| |
| if (onkeypress != null) { |
| addParameter("onkeypress", findString(onkeypress)); |
| } |
| |
| if (onkeydown != null) { |
| addParameter("onkeydown", findString(onkeydown)); |
| } |
| |
| if (onkeyup != null) { |
| addParameter("onkeyup", findString(onkeyup)); |
| } |
| |
| if (onselect != null) { |
| addParameter("onselect", findString(onselect)); |
| } |
| |
| if (onchange != null) { |
| addParameter("onchange", findString(onchange)); |
| } |
| |
| if (accesskey != null) { |
| addParameter("accesskey", findString(accesskey)); |
| } |
| |
| if (cssClass != null) { |
| addParameter("cssClass", findString(cssClass)); |
| } |
| |
| if (cssStyle != null) { |
| addParameter("cssStyle", findString(cssStyle)); |
| } |
| |
| if (cssErrorClass != null) { |
| addParameter("cssErrorClass", findString(cssErrorClass)); |
| } |
| |
| if (cssErrorStyle != null) { |
| addParameter("cssErrorStyle", findString(cssErrorStyle)); |
| } |
| |
| if (title != null) { |
| addParameter("title", findString(title)); |
| } |
| |
| |
| // see if the value was specified as a parameter already |
| if (parameters.containsKey("value")) { |
| parameters.put("nameValue", parameters.get("value")); |
| } else { |
| if (evaluateNameValue()) { |
| final Class valueClazz = getValueClassType(); |
| |
| if (valueClazz != null) { |
| if (value != null) { |
| addParameter("nameValue", findValue(value, valueClazz)); |
| } else if (name != null) { |
| String expr = completeExpressionIfAltSyntax(name); |
| |
| addParameter("nameValue", findValue(expr, valueClazz)); |
| } |
| } else { |
| if (value != null) { |
| addParameter("nameValue", findValue(value)); |
| } else if (name != null) { |
| addParameter("nameValue", findValue(name)); |
| } |
| } |
| } |
| } |
| |
| final Form form = (Form) findAncestor(Form.class); |
| |
| // create HTML id element |
| populateComponentHtmlId(form); |
| |
| if (form != null ) { |
| addParameter("form", form.getParameters()); |
| |
| if ( name != null ) { |
| // list should have been created by the form component |
| List<String> tags = (List<String>) form.getParameters().get("tagNames"); |
| tags.add(name); |
| } |
| } |
| |
| |
| // tooltip & tooltipConfig |
| if (tooltipConfig != null) { |
| addParameter("tooltipConfig", findValue(tooltipConfig)); |
| } |
| if (tooltip != null) { |
| addParameter("tooltip", findString(tooltip)); |
| |
| Map tooltipConfigMap = getTooltipConfig(this); |
| |
| if (form != null) { // inform the containing form that we need tooltip javascript included |
| form.addParameter("hasTooltip", Boolean.TRUE); |
| |
| // tooltipConfig defined in component itself will take precedence |
| // over those defined in the containing form |
| Map overallTooltipConfigMap = getTooltipConfig(form); |
| overallTooltipConfigMap.putAll(tooltipConfigMap); // override parent form's tooltip config |
| |
| for (Object o : overallTooltipConfigMap.entrySet()) { |
| Map.Entry entry = (Map.Entry) o; |
| addParameter((String) entry.getKey(), entry.getValue()); |
| } |
| } |
| else { |
| LOG.warn("No ancestor Form found, javascript based tooltip will not work, however standard HTML tooltip using alt and title attribute will still work"); |
| } |
| |
| //TODO: this is to keep backward compatibility, remove once when tooltipConfig is dropped |
| String jsTooltipEnabled = (String) getParameters().get("jsTooltipEnabled"); |
| if (jsTooltipEnabled != null) |
| this.javascriptTooltip = jsTooltipEnabled; |
| |
| //TODO: this is to keep backward compatibility, remove once when tooltipConfig is dropped |
| String tooltipIcon = (String) getParameters().get("tooltipIcon"); |
| if (tooltipIcon != null) |
| this.addParameter("tooltipIconPath", tooltipIcon); |
| if (this.tooltipIconPath != null) |
| this.addParameter("tooltipIconPath", findString(this.tooltipIconPath)); |
| |
| //TODO: this is to keep backward compatibility, remove once when tooltipConfig is dropped |
| String tooltipDelayParam = (String) getParameters().get("tooltipDelay"); |
| if (tooltipDelayParam != null) |
| this.addParameter("tooltipDelay", tooltipDelayParam); |
| if (this.tooltipDelay != null) |
| this.addParameter("tooltipDelay", findString(this.tooltipDelay)); |
| |
| if (this.javascriptTooltip != null) { |
| Boolean jsTooltips = (Boolean) findValue(this.javascriptTooltip, Boolean.class); |
| //TODO use a Boolean model when tooltipConfig is dropped |
| this.addParameter("jsTooltipEnabled", jsTooltips.toString()); |
| |
| if (form != null) |
| form.addParameter("hasTooltip", jsTooltips); |
| if (this.tooltipCssClass != null) |
| this.addParameter("tooltipCssClass", findString(this.tooltipCssClass)); |
| } |
| } |
| |
| evaluateExtraParams(); |
| } |
| |
| protected String escape(String name) { |
| // escape any possible values that can make the ID painful to work with in JavaScript |
| if (name != null) { |
| return name.replaceAll("[\\/\\.\\[\\]\'\"]", "_"); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Ensures an unescaped attribute value cannot be vulnerable to XSS attacks |
| * |
| * @param val The value to check |
| * @return The escaped value |
| */ |
| protected String ensureAttributeSafelyNotEscaped(String val) { |
| if (val != null) { |
| return val.replaceAll("\"", """); |
| } else { |
| return null; |
| } |
| } |
| |
| protected void evaluateExtraParams() { |
| } |
| |
| protected boolean evaluateNameValue() { |
| return true; |
| } |
| |
| protected Class getValueClassType() { |
| return String.class; |
| } |
| |
| public void addFormParameter(String key, Object value) { |
| Form form = (Form) findAncestor(Form.class); |
| if (form != null) { |
| form.addParameter(key, value); |
| } |
| } |
| |
| protected void enableAncestorFormCustomOnsubmit() { |
| Form form = (Form) findAncestor(Form.class); |
| if (form != null) { |
| form.addParameter("customOnsubmitEnabled", Boolean.TRUE); |
| } else { |
| if (LOG.isWarnEnabled()) { |
| LOG.warn("Cannot find an Ancestor form, custom onsubmit is NOT enabled"); |
| } |
| } |
| } |
| |
| protected Map getTooltipConfig(UIBean component) { |
| Object tooltipConfigObj = component.getParameters().get("tooltipConfig"); |
| Map<String, String> tooltipConfig = new LinkedHashMap<>(); |
| |
| if (tooltipConfigObj instanceof Map) { |
| // we get this if its configured using |
| // 1] UI component's tooltipConfig attribute OR |
| // 2] <param name="tooltip" value="" /> param tag value attribute |
| |
| tooltipConfig = new LinkedHashMap<>((Map) tooltipConfigObj); |
| } else if (tooltipConfigObj instanceof String) { |
| |
| // we get this if its configured using |
| // <param name="tooltipConfig"> ... </param> tag's body |
| String tooltipConfigStr = (String) tooltipConfigObj; |
| String[] tooltipConfigArray = tooltipConfigStr.split("\\|"); |
| |
| for (String aTooltipConfigArray : tooltipConfigArray) { |
| String[] configEntry = aTooltipConfigArray.trim().split("="); |
| String key = configEntry[0].trim(); |
| String value; |
| if (configEntry.length > 1) { |
| value = configEntry[1].trim(); |
| tooltipConfig.put(key, value); |
| } else { |
| LOG.warn("component {} tooltip config param {} has no value defined, skipped", component, key); |
| } |
| } |
| } |
| if (component.javascriptTooltip != null) |
| tooltipConfig.put("jsTooltipEnabled", component.javascriptTooltip); |
| if (component.tooltipIconPath != null) |
| tooltipConfig.put("tooltipIcon", component.tooltipIconPath); |
| if (component.tooltipDelay != null) |
| tooltipConfig.put("tooltipDelay", component.tooltipDelay); |
| return tooltipConfig; |
| } |
| |
| /** |
| * Create HTML id element for the component and populate this component parameter |
| * map. Additionally, a parameter named escapedId is populated which contains the found id value filtered by |
| * {@link #escape(String)}, needed eg. for naming Javascript identifiers based on the id value. |
| * |
| * The order is as follows :- |
| * <ol> |
| * <li>This component id attribute</li> |
| * <li>[containing_form_id]_[this_component_name]</li> |
| * <li>[this_component_name]</li> |
| * </ol> |
| * |
| * @param form enclosing form tag |
| */ |
| protected void populateComponentHtmlId(Form form) { |
| TagAttribute tryId; |
| String generatedId; |
| if (id != null && !id.isNull()) { |
| // this check is needed for backwards compatibility with 2.1.x |
| tryId = findStringIfAltSyntax(id); |
| } else if (null == (generatedId = escape(name != null ? findString(name) : null))) { |
| LOG.debug("Cannot determine id attribute for [{}], consider defining id, name or key attribute!", this); |
| tryId = TagAttribute.NULL; |
| } else if (form != null) { |
| tryId = TagAttribute.evaluated(((TagAttribute)form.getParameters().get("id")).getValue() + "_" + generatedId); |
| } else { |
| tryId = TagAttribute.evaluated(generatedId); |
| } |
| |
| //fix for https://issues.apache.org/jira/browse/WW-4299 |
| //do not assign value to id if tryId is null |
| if (!tryId.isNull()) { |
| id = tryId; |
| addParameter("id", tryId); |
| addParameter("escapedId", tryId.escaped()); |
| } |
| } |
| |
| /** |
| * Get's the id for referencing element. |
| * @return the id for referencing element. |
| */ |
| public TagAttribute getId() { |
| return id; |
| } |
| |
| @StrutsTagAttribute(description="HTML id attribute") |
| public void setId(String id) { |
| this.id = TagAttribute.raw(id); |
| } |
| |
| @StrutsTagAttribute(description="The template directory.") |
| public void setTemplateDir(String templateDir) { |
| this.templateDir = templateDir; |
| } |
| |
| @StrutsTagAttribute(description="The theme (other than default) to use for rendering the element") |
| public void setTheme(String theme) { |
| this.theme = theme; |
| } |
| |
| public String getTemplate() { |
| return template; |
| } |
| |
| @StrutsTagAttribute(description="The template (other than default) to use for rendering the element") |
| public void setTemplate(String template) { |
| this.template = template; |
| } |
| |
| @StrutsTagAttribute(description="The css class to use for element") |
| public void setCssClass(String cssClass) { |
| this.cssClass = cssClass; |
| } |
| |
| @StrutsTagAttribute(description="The css class to use for element - it's an alias of cssClass attribute.") |
| public void setClass(String cssClass) { |
| this.cssClass = cssClass; |
| } |
| |
| @StrutsTagAttribute(description="The css style definitions for element to use") |
| public void setCssStyle(String cssStyle) { |
| this.cssStyle = cssStyle; |
| } |
| |
| @StrutsTagAttribute(description="The css style definitions for element to use - it's an alias of cssStyle attribute.") |
| public void setStyle(String cssStyle) { |
| this.cssStyle = cssStyle; |
| } |
| |
| @StrutsTagAttribute(description="The css error class to use for element") |
| public void setCssErrorClass(String cssErrorClass) { |
| this.cssErrorClass = cssErrorClass; |
| } |
| |
| @StrutsTagAttribute(description="The css error style definitions for element to use") |
| public void setCssErrorStyle(String cssErrorStyle) { |
| this.cssErrorStyle = cssErrorStyle; |
| } |
| |
| @StrutsTagAttribute(description="Set the html title attribute on rendered html element") |
| public void setTitle(String title) { |
| this.title = title; |
| } |
| |
| @StrutsTagAttribute(description="Set the html disabled attribute on rendered html element") |
| public void setDisabled(String disabled) { |
| this.disabled = disabled; |
| } |
| |
| @StrutsTagAttribute(description="Label expression used for rendering an element specific label") |
| public void setLabel(String label) { |
| this.label = label; |
| } |
| |
| @StrutsTagAttribute(description="String that will be appended to the label", defaultValue=":") |
| public void setLabelSeparator(String labelseparator) { |
| this.labelSeparator = labelseparator; |
| } |
| |
| @StrutsTagAttribute(description="Define label position of form element (top/left)") |
| public void setLabelposition(String labelPosition) { |
| this.labelPosition = labelPosition; |
| } |
| |
| @StrutsTagAttribute(description="Define required position of required form element (left|right)") |
| public void setRequiredPosition(String requiredPosition) { |
| this.requiredPosition = requiredPosition; |
| } |
| |
| @StrutsTagAttribute(description="Define error position of form element (top|bottom)") |
| public void setErrorPosition(String errorPosition) { |
| this.errorPosition = errorPosition; |
| } |
| |
| @StrutsTagAttribute(description="The name to set for element") |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| @StrutsTagAttribute(description="If set to true, the rendered element will indicate that input is required", type="Boolean", defaultValue="false") |
| public void setRequiredLabel(String requiredLabel) { |
| this.requiredLabel = requiredLabel; |
| } |
| |
| @StrutsTagAttribute(description="Set the html tabindex attribute on rendered html element") |
| public void setTabindex(String tabindex) { |
| this.tabindex = tabindex; |
| } |
| |
| @StrutsTagAttribute(description="Preset the value of input element.") |
| public void setValue(String value) { |
| this.value = value; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onclick attribute on rendered html element") |
| public void setOnclick(String onclick) { |
| this.onclick = onclick; |
| } |
| |
| @StrutsTagAttribute(description="Set the html ondblclick attribute on rendered html element") |
| public void setOndblclick(String ondblclick) { |
| this.ondblclick = ondblclick; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onmousedown attribute on rendered html element") |
| public void setOnmousedown(String onmousedown) { |
| this.onmousedown = onmousedown; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onmouseup attribute on rendered html element") |
| public void setOnmouseup(String onmouseup) { |
| this.onmouseup = onmouseup; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onmouseover attribute on rendered html element") |
| public void setOnmouseover(String onmouseover) { |
| this.onmouseover = onmouseover; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onmousemove attribute on rendered html element") |
| public void setOnmousemove(String onmousemove) { |
| this.onmousemove = onmousemove; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onmouseout attribute on rendered html element") |
| public void setOnmouseout(String onmouseout) { |
| this.onmouseout = onmouseout; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onfocus attribute on rendered html element") |
| public void setOnfocus(String onfocus) { |
| this.onfocus = onfocus; |
| } |
| |
| @StrutsTagAttribute(description=" Set the html onblur attribute on rendered html element") |
| public void setOnblur(String onblur) { |
| this.onblur = onblur; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onkeypress attribute on rendered html element") |
| public void setOnkeypress(String onkeypress) { |
| this.onkeypress = onkeypress; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onkeydown attribute on rendered html element") |
| public void setOnkeydown(String onkeydown) { |
| this.onkeydown = onkeydown; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onkeyup attribute on rendered html element") |
| public void setOnkeyup(String onkeyup) { |
| this.onkeyup = onkeyup; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onselect attribute on rendered html element") |
| public void setOnselect(String onselect) { |
| this.onselect = onselect; |
| } |
| |
| @StrutsTagAttribute(description="Set the html onchange attribute on rendered html element") |
| public void setOnchange(String onchange) { |
| this.onchange = onchange; |
| } |
| |
| @StrutsTagAttribute(description="Set the html accesskey attribute on rendered html element") |
| public void setAccesskey(String accesskey) { |
| this.accesskey = accesskey; |
| } |
| |
| @StrutsTagAttribute(description="Set the tooltip of this particular component") |
| public void setTooltip(String tooltip) { |
| this.tooltip = tooltip; |
| } |
| |
| @StrutsTagAttribute(description="Deprecated. Use individual tooltip configuration attributes instead.") |
| public void setTooltipConfig(String tooltipConfig) { |
| this.tooltipConfig = tooltipConfig; |
| } |
| |
| @StrutsTagAttribute(description="Set the key (name, value, label) for this particular component") |
| public void setKey(String key) { |
| this.key = key; |
| } |
| |
| @StrutsTagAttribute(description="Use JavaScript to generate tooltips", type="Boolean", defaultValue="false") |
| public void setJavascriptTooltip(String javascriptTooltip) { |
| this.javascriptTooltip = javascriptTooltip; |
| } |
| |
| @StrutsTagAttribute(description="CSS class applied to JavaScrip tooltips", defaultValue="StrutsTTClassic") |
| public void setTooltipCssClass(String tooltipCssClass) { |
| this.tooltipCssClass = tooltipCssClass; |
| } |
| |
| @StrutsTagAttribute(description="Delay in milliseconds, before showing JavaScript tooltips ", |
| defaultValue="Classic") |
| public void setTooltipDelay(String tooltipDelay) { |
| this.tooltipDelay = tooltipDelay; |
| } |
| |
| @StrutsTagAttribute(description="Icon path used for image that will have the tooltip") |
| public void setTooltipIconPath(String tooltipIconPath) { |
| this.tooltipIconPath = tooltipIconPath; |
| } |
| |
| public void setDynamicAttributes(Map<String, Object> tagDynamicAttributes) { |
| for (Map.Entry<String, Object> entry : tagDynamicAttributes.entrySet()) { |
| String key = entry.getKey(); |
| |
| if (!isValidTagAttribute(key)) { |
| dynamicAttributes.put(key, entry.getValue()); |
| } |
| } |
| } |
| |
| @Override |
| /** |
| * supports dynamic attributes for freemarker ui tags |
| * @see https://issues.apache.org/jira/browse/WW-3174 |
| * @see https://issues.apache.org/jira/browse/WW-4166 |
| */ |
| public void copyParams(Map params) { |
| super.copyParams(params); |
| for (Object o : params.entrySet()) { |
| Map.Entry entry = (Map.Entry) o; |
| String key = (String) entry.getKey(); |
| if (!isValidTagAttribute(key) && !key.equals("dynamicAttributes")) { |
| dynamicAttributes.put(key, entry.getValue()); |
| } |
| } |
| } |
| |
| } |