View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    * 
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   */
19  package org.apache.myfaces.shared.renderkit.html;
20  
21  import org.apache.myfaces.shared.config.MyfacesConfig;
22  import org.apache.myfaces.shared.renderkit.JSFAttr;
23  import org.apache.myfaces.shared.renderkit.RendererUtils;
24  import org.apache.myfaces.shared.renderkit.html.util.FormInfo;
25  import org.apache.myfaces.shared.renderkit.html.util.JavascriptUtils;
26  
27  import javax.faces.component.UICommand;
28  import javax.faces.component.UIComponent;
29  import javax.faces.component.ValueHolder;
30  import javax.faces.component.html.HtmlCommandButton;
31  import javax.faces.context.ExternalContext;
32  import javax.faces.context.FacesContext;
33  import javax.faces.context.ResponseWriter;
34  import javax.faces.event.ActionEvent;
35  import java.io.IOException;
36  import java.util.Map;
37  
38  /***
39   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
40   * @author Thomas Spiegl
41   * @author Anton Koinov
42   * @version $Revision: 941950 $ $Date: 2010-05-06 17:03:41 -0500 (Thu, 06 May 2010) $
43   */
44  public class HtmlButtonRendererBase
45      extends HtmlRenderer
46  {
47      private static final String IMAGE_BUTTON_SUFFIX_X = ".x";
48      private static final String IMAGE_BUTTON_SUFFIX_Y = ".y";
49  
50      public static final String ACTION_FOR_LIST = "org.apache.myfaces.ActionForList";
51  
52      public void decode(FacesContext facesContext, UIComponent uiComponent)
53      {
54          org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext, uiComponent, UICommand.class);
55  
56          //super.decode must not be called, because value is handled here
57          if (!isReset(uiComponent) && isSubmitted(facesContext, uiComponent))
58          {
59              uiComponent.queueEvent(new ActionEvent(uiComponent));
60  
61              org.apache.myfaces.shared.renderkit.RendererUtils.initPartialValidationAndModelUpdate(uiComponent, facesContext);
62          }
63      }
64  
65      private static boolean isReset(UIComponent uiComponent)
66      {
67          return "reset".equals((String) uiComponent.getAttributes().get(HTML.TYPE_ATTR));
68      }
69  
70      private static boolean isSubmitted(FacesContext facesContext, UIComponent uiComponent)
71      {
72          String clientId = uiComponent.getClientId(facesContext);
73          Map paramMap = facesContext.getExternalContext().getRequestParameterMap();
74          return paramMap.containsKey(clientId) || paramMap.containsKey(clientId + IMAGE_BUTTON_SUFFIX_X) || paramMap.containsKey(clientId + IMAGE_BUTTON_SUFFIX_Y);
75      }
76  
77      public void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
78              throws IOException
79      {
80          org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext, uiComponent, UICommand.class);
81  
82          String clientId = uiComponent.getClientId(facesContext);
83  
84          ResponseWriter writer = facesContext.getResponseWriter();
85          
86          // If we have javascript enabled, and autoscroll is enabled, 
87          // we should write the form submit script
88          // (define oamSetHiddenInput, oamClearHiddenInput, oamSubmitForm)
89          // because oamSetHiddenInput is called on onclick function
90          if (JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
91          {        
92              if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll()) {
93                  HtmlRendererUtils.renderFormSubmitScript(facesContext);
94              }
95          }
96  
97          writer.startElement(HTML.INPUT_ELEM, uiComponent);
98  
99          writer.writeAttribute(HTML.ID_ATTR, clientId, org.apache.myfaces.shared.renderkit.JSFAttr.ID_ATTR);
100         writer.writeAttribute(HTML.NAME_ATTR, clientId, JSFAttr.ID_ATTR);
101 
102         String image = getImage(uiComponent);
103 
104         ExternalContext externalContext = facesContext.getExternalContext();
105 
106         if (image != null)
107         {
108             writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_IMAGE, org.apache.myfaces.shared.renderkit.JSFAttr.TYPE_ATTR);
109             String src = facesContext.getApplication().getViewHandler().getResourceURL(
110                     facesContext, image);
111             writer.writeURIAttribute(HTML.SRC_ATTR, externalContext.encodeResourceURL(src),
112                                      org.apache.myfaces.shared.renderkit.JSFAttr.IMAGE_ATTR);
113         }
114         else
115         {
116             String type = getType(uiComponent);
117 
118             if (type == null || !isReset(uiComponent))
119             {
120                 type = HTML.INPUT_TYPE_SUBMIT;
121             }
122             writer.writeAttribute(HTML.TYPE_ATTR, type, org.apache.myfaces.shared.renderkit.JSFAttr.TYPE_ATTR);
123             Object value = getValue(uiComponent);
124             if (value != null)
125             {
126                 writer.writeAttribute(org.apache.myfaces.shared.renderkit.html.HTML.VALUE_ATTR, value, org.apache.myfaces.shared.renderkit.JSFAttr.VALUE_ATTR);
127             }
128         }
129         if (JavascriptUtils.isJavascriptAllowed(externalContext))
130         {
131             StringBuffer onClick = buildOnClick(uiComponent, facesContext, writer);
132             if (onClick.length() != 0){
133                 writer.writeAttribute(HTML.ONCLICK_ATTR, onClick.toString(), null);
134             }
135             HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
136                                                    HTML.BUTTON_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED_AND_ONCLICK);
137         }
138         else
139         {
140             HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
141                                                    HTML.BUTTON_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED);
142         }
143 
144         if (isDisabled(facesContext, uiComponent))
145         {
146             writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, org.apache.myfaces.shared.renderkit.JSFAttr.DISABLED_ATTR);
147         }
148         
149         if (isReadonly(facesContext, uiComponent))
150         {
151             writer.writeAttribute(HTML.READONLY_ATTR, Boolean.TRUE, org.apache.myfaces.shared.renderkit.JSFAttr.READONLY_ATTR);
152         }
153 
154         writer.endElement(HTML.INPUT_ELEM);
155         
156         HtmlFormRendererBase.renderScrollHiddenInputIfNecessary(
157             findNestingForm(uiComponent, facesContext).getForm(), facesContext, writer);
158     }
159 
160 
161     protected StringBuffer buildOnClick(UIComponent uiComponent, FacesContext facesContext, ResponseWriter writer)
162         throws IOException
163     {
164         /* DUMMY STUFF
165         //Find form
166         UIComponent parent = uiComponent.getParent();
167         while (parent != null && !(parent instanceof UIForm))
168         {
169             parent = parent.getParent();
170         }
171 
172         UIForm nestingForm = null;
173         String formName;
174 
175         if (parent != null)
176         {
177             //link is nested inside a form
178             nestingForm = (UIForm)parent;
179             formName = nestingForm.getClientId(facesContext);
180 
181         }
182         else
183         {
184             //not nested in form, we must add a dummy form at the end of the document
185             formName = DummyFormUtils.DUMMY_FORM_NAME;
186             //dummyFormResponseWriter = DummyFormUtils.getDummyFormResponseWriter(facesContext);
187             //dummyFormResponseWriter.setWriteDummyForm(true);
188             DummyFormUtils.setWriteDummyForm(facesContext, true);
189         }
190         */
191         FormInfo formInfo = findNestingForm(uiComponent, facesContext);
192         if (formInfo == null)
193         {
194             throw new IllegalArgumentException("Component " + uiComponent.getClientId(facesContext) + " must be embedded in an form");
195         }
196         String formName = formInfo.getFormName();
197         UIComponent nestingForm = formInfo.getForm();
198         
199         StringBuffer onClick = new StringBuffer();
200         String commandOnClick = (String)uiComponent.getAttributes().get(HTML.ONCLICK_ATTR);
201 
202         if (commandOnClick != null)
203         {
204             onClick.append(commandOnClick);
205             onClick.append(';');
206         }
207 
208         if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext()) ||
209             MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isRenderHiddenFieldsForLinkParams() )
210         {
211             //call the script to clear the form (clearFormHiddenParams_<formName>) method
212             HtmlRendererUtils.appendClearHiddenCommandFormParamsFunctionCall(onClick, formName);
213         }
214 
215         if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll()) {
216             HtmlRendererUtils.appendAutoScrollAssignment(onClick, formName);
217         }
218 
219         //The hidden field has only sense if isRenderClearJavascriptOnButton is
220         //set to true. In other case, this hidden field should not be rendered.
221         //if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext()))
222         //{
223             //add hidden field for the case there is no commandLink in the form
224             //String hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo);
225             //addHiddenCommandParameter(facesContext, nestingForm, hiddenFieldName);
226         //}
227 
228         return onClick;
229     }
230 
231     protected void addHiddenCommandParameter(FacesContext facesContext, UIComponent nestingForm, String hiddenFieldName)
232     {
233         if (nestingForm != null)
234         {
235             HtmlFormRendererBase.addHiddenCommandParameter(facesContext, nestingForm, hiddenFieldName);
236         }
237     }
238 
239     /***
240      * find nesting form<br />
241      * need to be overrideable to deal with dummyForm stuff in tomahawk.
242      */
243     protected FormInfo findNestingForm(UIComponent uiComponent, FacesContext facesContext)
244     {
245         return RendererUtils.findNestingForm(uiComponent, facesContext);
246     }
247 
248     protected boolean isDisabled(FacesContext facesContext, UIComponent uiComponent)
249     {
250         //TODO: overwrite in extended HtmlButtonRenderer and check for enabledOnUserRole
251         if (uiComponent instanceof HtmlCommandButton)
252         {
253             return ((HtmlCommandButton)uiComponent).isDisabled();
254         }
255 
256         return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(uiComponent, HTML.DISABLED_ATTR, false);
257         
258     }
259 
260     protected boolean isReadonly(FacesContext facesContext, UIComponent uiComponent)
261     {
262         if (uiComponent instanceof HtmlCommandButton)
263         {
264             return ((HtmlCommandButton)uiComponent).isReadonly();
265         }
266         return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(uiComponent, HTML.READONLY_ATTR, false);
267     }
268 
269     private String getImage(UIComponent uiComponent)
270     {
271         if (uiComponent instanceof HtmlCommandButton)
272         {
273             return ((HtmlCommandButton)uiComponent).getImage();
274         }
275         return (String)uiComponent.getAttributes().get(JSFAttr.IMAGE_ATTR);
276     }
277 
278     private String getType(UIComponent uiComponent)
279     {
280         if (uiComponent instanceof HtmlCommandButton)
281         {
282             return ((HtmlCommandButton)uiComponent).getType();
283         }
284         return (String)uiComponent.getAttributes().get(org.apache.myfaces.shared.renderkit.JSFAttr.TYPE_ATTR);
285     }
286 
287     private Object getValue(UIComponent uiComponent)
288     {
289         if (uiComponent instanceof ValueHolder)
290         {
291             return ((ValueHolder)uiComponent).getValue();
292         }
293         return uiComponent.getAttributes().get(JSFAttr.VALUE_ATTR);
294     }
295 }