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 java.io.IOException;
22  import java.util.Collection;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.Map;
26  
27  import javax.faces.component.UICommand;
28  import javax.faces.component.UIComponent;
29  import javax.faces.component.UIParameter;
30  import javax.faces.component.ValueHolder;
31  import javax.faces.component.behavior.ClientBehavior;
32  import javax.faces.component.behavior.ClientBehaviorContext;
33  import javax.faces.component.behavior.ClientBehaviorHolder;
34  import javax.faces.component.html.HtmlCommandButton;
35  import javax.faces.component.html.HtmlCommandLink;
36  import javax.faces.context.FacesContext;
37  import javax.faces.context.ResponseWriter;
38  import javax.faces.event.ActionEvent;
39  
40  import org.apache.myfaces.shared.config.MyfacesConfig;
41  import org.apache.myfaces.shared.renderkit.ClientBehaviorEvents;
42  import org.apache.myfaces.shared.renderkit.JSFAttr;
43  import org.apache.myfaces.shared.renderkit.RendererUtils;
44  import org.apache.myfaces.shared.renderkit.html.util.FormInfo;
45  import org.apache.myfaces.shared.renderkit.html.util.JavascriptUtils;
46  import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
47  import org.apache.myfaces.shared.util._ComponentUtils;
48  
49  public class HtmlButtonRendererBase
50      extends HtmlRenderer
51  {
52      private static final String IMAGE_BUTTON_SUFFIX_X = ".x";
53      private static final String IMAGE_BUTTON_SUFFIX_Y = ".y";
54  
55      public static final String ACTION_FOR_LIST = "org.apache.myfaces.ActionForList";
56  
57      public void decode(FacesContext facesContext, UIComponent uiComponent)
58      {
59          org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(
60                  facesContext, uiComponent, UICommand.class);
61  
62          //super.decode must not be called, because value is handled here
63          boolean disabled = isDisabled(facesContext, uiComponent);
64          // MYFACES-3960 Decode, decode client behavior and queue action event at the end
65          boolean activateActionEvent = !isReset(uiComponent) && isSubmitted(facesContext, uiComponent) &&
66              !disabled;
67          if (activateActionEvent)
68          {
69              org.apache.myfaces.shared.renderkit.RendererUtils.initPartialValidationAndModelUpdate(
70                      uiComponent, facesContext);
71          }
72          
73          if (uiComponent instanceof ClientBehaviorHolder &&
74                  !disabled)
75          {
76              HtmlRendererUtils.decodeClientBehaviors(facesContext, uiComponent);
77          }
78          
79          if (activateActionEvent)
80          {
81              uiComponent.queueEvent(new ActionEvent(uiComponent));
82          }
83      }
84  
85      private static boolean isReset(UIComponent uiComponent)
86      {
87          return "reset".equals((String) uiComponent.getAttributes().get(HTML.TYPE_ATTR));
88      }
89      
90      private static boolean isButton(UIComponent uiComponent)
91      {
92          return "button".equals((String) uiComponent.getAttributes().get(HTML.TYPE_ATTR));
93      }
94  
95      private static boolean isSubmitted(FacesContext facesContext, UIComponent uiComponent)
96      {
97          String clientId = uiComponent.getClientId(facesContext);
98          Map paramMap = facesContext.getExternalContext().getRequestParameterMap();
99          FormInfo formInfo = _ComponentUtils.findNestingForm(uiComponent, facesContext);
100         String hiddenLink = null;
101          
102         if (formInfo != null)
103         {
104             hiddenLink = (String) facesContext.getExternalContext().getRequestParameterMap().get(
105                 HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo, facesContext));
106         }
107         return paramMap.containsKey(clientId) || paramMap.containsKey(clientId + IMAGE_BUTTON_SUFFIX_X) 
108             || paramMap.containsKey(clientId + IMAGE_BUTTON_SUFFIX_Y)
109             || (hiddenLink != null && hiddenLink.equals (clientId))
110             || HtmlRendererUtils.isPartialOrBehaviorSubmit(facesContext, clientId);
111     }
112 
113     @Override
114     public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
115     {
116         org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(
117                 facesContext, uiComponent, UICommand.class);
118 
119         String clientId = uiComponent.getClientId(facesContext);
120 
121         ResponseWriter writer = facesContext.getResponseWriter();
122         
123         // commandButton does not need to be nested in a form since JSF 2.0
124         FormInfo formInfo = findNestingForm(uiComponent, facesContext);
125 
126         boolean reset = isReset(uiComponent);
127         boolean button = isButton(uiComponent);
128 
129         Map<String, List<ClientBehavior>> behaviors = null;
130         if (uiComponent instanceof ClientBehaviorHolder)
131         {
132             behaviors = ((ClientBehaviorHolder) uiComponent).getClientBehaviors();
133             if (!behaviors.isEmpty())
134             {
135                 ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
136             }
137         }
138         
139         // If we are nested in a form, and we have javascript enabled, and autoscroll is enabled, 
140         // we should write the form submit script
141         // (define oamSetHiddenInput, oamClearHiddenInput, oamSubmitForm)
142         // because oamSetHiddenInput is called on onclick function
143         List<UIComponent> childrenList = null;
144         if (getChildCount(uiComponent) > 0)
145         {
146             childrenList = getChildren(uiComponent);
147         }
148         else
149         {
150            childrenList = Collections.emptyList();
151         }
152         List<UIParameter> validParams = HtmlRendererUtils.getValidUIParameterChildren(
153                 facesContext, childrenList, false, false);
154         
155         if (formInfo != null 
156                 && (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll() ||
157                         (validParams != null && !validParams.isEmpty() )))
158         {        
159             HtmlRendererUtils.renderFormSubmitScript(facesContext);
160         }
161         
162         String commandOnclick = (String)uiComponent.getAttributes().get(HTML.ONCLICK_ATTR);
163         
164         if (commandOnclick != null && (validParams != null && !validParams.isEmpty() ) )
165         {
166             ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
167         }
168 
169         writer.startElement(HTML.INPUT_ELEM, uiComponent);
170 
171         writer.writeAttribute(HTML.ID_ATTR, clientId, org.apache.myfaces.shared.renderkit.JSFAttr.ID_ATTR);
172         writer.writeAttribute(HTML.NAME_ATTR, clientId, JSFAttr.ID_ATTR);
173 
174         String image = RendererUtils.getIconSrc(facesContext, uiComponent, JSFAttr.IMAGE_ATTR);
175         if (image != null)
176         {
177             writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_IMAGE, 
178                     org.apache.myfaces.shared.renderkit.JSFAttr.TYPE_ATTR);
179             writer.writeURIAttribute(HTML.SRC_ATTR, image, org.apache.myfaces.shared.renderkit.JSFAttr.IMAGE_ATTR);
180         }
181         else
182         {
183             String type = getType(uiComponent);
184 
185             if (type == null || (!reset && !button))
186             {
187                 type = HTML.INPUT_TYPE_SUBMIT;
188             }
189             writer.writeAttribute(HTML.TYPE_ATTR, type, org.apache.myfaces.shared.renderkit.JSFAttr.TYPE_ATTR);
190             Object value = getValue(uiComponent);
191             if (value != null)
192             {
193                 writer.writeAttribute(org.apache.myfaces.shared.renderkit.html.HTML.VALUE_ATTR, value, 
194                         org.apache.myfaces.shared.renderkit.JSFAttr.VALUE_ATTR);
195             }
196         }
197         
198         if ((HtmlRendererUtils.hasClientBehavior(ClientBehaviorEvents.CLICK, behaviors, facesContext) ||
199              HtmlRendererUtils.hasClientBehavior(ClientBehaviorEvents.ACTION, behaviors, facesContext)))
200         {
201             if (!reset && !button)
202             {
203                 String onClick = buildBehaviorizedOnClick(
204                         uiComponent, behaviors, facesContext, writer, formInfo, validParams);
205                 if (onClick.length() != 0)
206                 {
207                     writer.writeAttribute(HTML.ONCLICK_ATTR, onClick, null);
208                 }
209             }
210             else
211             {
212                 Collection<ClientBehaviorContext.Parameter> paramList = 
213                     HtmlRendererUtils.getClientBehaviorContextParameters(
214                         HtmlRendererUtils.mapAttachedParamsToStringValues(facesContext, uiComponent));
215                     
216                 String onClick = HtmlRendererUtils.buildBehaviorChain(facesContext, uiComponent,
217                         ClientBehaviorEvents.CLICK, paramList, ClientBehaviorEvents.ACTION, paramList, behaviors,
218                         commandOnclick , null);
219                 if (onClick.length() != 0)
220                 {
221                     writer.writeAttribute(HTML.ONCLICK_ATTR, onClick, null);
222                 }
223             }
224             
225             Map<String, Object> attributes = uiComponent.getAttributes(); 
226             
227             HtmlRendererUtils.buildBehaviorChain(
228                     facesContext, uiComponent, ClientBehaviorEvents.DBLCLICK, null, behaviors,   
229                         (String) attributes.get(HTML.ONDBLCLICK_ATTR), "");
230         }
231         else
232         {
233             //fallback into the pre 2.0 code to keep backwards compatibility with libraries which rely on internals
234             if (!reset && !button)
235             {
236                 StringBuilder onClick = buildOnClick(uiComponent, facesContext, writer, validParams);
237                 if (onClick.length() != 0)
238                 {
239                     writer.writeAttribute(HTML.ONCLICK_ATTR, onClick.toString(), null);
240                 }
241             }
242             else
243             {
244                 HtmlRendererUtils.renderHTMLStringAttribute(writer, uiComponent, HTML.ONCLICK_ATTR, HTML.ONCLICK_ATTR);
245             }
246         }
247         
248         //if (javascriptAllowed)
249         //{
250             if (isCommonPropertiesOptimizationEnabled(facesContext))
251             {
252                 CommonPropertyUtils.renderButtonPassthroughPropertiesWithoutDisabledAndEvents(writer, 
253                         CommonPropertyUtils.getCommonPropertiesMarked(uiComponent), uiComponent);
254             }
255             else
256             {
257                 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
258                                                        HTML.BUTTON_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED_AND_EVENTS);
259             }
260         //}
261 
262         if (behaviors != null && !behaviors.isEmpty())
263         {
264             HtmlRendererUtils.renderBehaviorizedEventHandlersWithoutOnclick(
265                     facesContext, writer, uiComponent, behaviors);
266             HtmlRendererUtils.renderBehaviorizedFieldEventHandlers(facesContext, writer, uiComponent, behaviors);
267         }
268         else
269         {
270             if (isCommonPropertiesOptimizationEnabled(facesContext))
271             {
272                 long commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(uiComponent);
273                 CommonPropertyUtils.renderEventPropertiesWithoutOnclick(writer, commonPropertiesMarked, uiComponent);
274                 CommonPropertyUtils.renderCommonFieldEventProperties(writer, commonPropertiesMarked, uiComponent);
275             }
276             else
277             {
278                 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
279                         HTML.EVENT_HANDLER_ATTRIBUTES_WITHOUT_ONCLICK);
280                 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
281                         HTML.COMMON_FIELD_EVENT_ATTRIBUTES);
282             }
283         }
284 
285         if (isDisabled(facesContext, uiComponent))
286         {
287             writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, 
288                     org.apache.myfaces.shared.renderkit.JSFAttr.DISABLED_ATTR);
289         }
290         
291         if (isReadonly(facesContext, uiComponent))
292         {
293             writer.writeAttribute(HTML.READONLY_ATTR, Boolean.TRUE, 
294                     org.apache.myfaces.shared.renderkit.JSFAttr.READONLY_ATTR);
295         }
296     }
297     
298     public void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
299             throws IOException
300     {
301         ResponseWriter writer = facesContext.getResponseWriter();
302 
303         writer.endElement(HTML.INPUT_ELEM);
304         
305         FormInfo formInfo = findNestingForm(uiComponent, facesContext);
306         if (formInfo != null)
307         {
308             HtmlFormRendererBase.renderScrollHiddenInputIfNecessary(
309                     formInfo.getForm(), facesContext, writer);
310         }
311         
312         // render the UIParameter children of the commandButton (since 2.0)
313         /*
314         List<UIParameter> validParams = HtmlRendererUtils.getValidUIParameterChildren(
315                 facesContext, uiComponent.getChildren(), false, false);
316         for (UIParameter param : validParams)
317         {
318             HtmlInputHidden parameterComponent = new HtmlInputHidden();
319             parameterComponent.setId(param.getName());
320             parameterComponent.setValue(param.getValue());
321             parameterComponent.encodeAll(facesContext);
322         }*/
323     }
324 
325     protected String buildBehaviorizedOnClick(UIComponent uiComponent, Map<String, List<ClientBehavior>> behaviors, 
326                                               FacesContext facesContext, ResponseWriter writer, 
327                                               FormInfo nestedFormInfo, List<UIParameter> validParams)
328         throws IOException
329     {
330         //we can omit autoscroll here for now maybe we should check if it is an ajax 
331         //behavior and omit it only in this case
332         StringBuilder userOnClick = new StringBuilder();
333         //user onclick part 
334         String commandOnClick = (String) uiComponent.getAttributes().get(HTML.ONCLICK_ATTR);
335 
336         if (commandOnClick != null)
337         {
338             userOnClick.append(commandOnClick);
339             userOnClick.append(';');
340         }
341 
342         StringBuilder rendererOnClick = new StringBuilder();
343 
344         if (nestedFormInfo != null) 
345         {
346             // There is no clean way to detect if a "submit" behavior has been added to the component, 
347             // so to keep things simple, if the button is submit type, it is responsibility of the 
348             // developer to add a client behavior that submit the form, for example using a f:ajax tag.
349             // Otherwise, there will be a situation where a full submit could be trigger after an ajax
350             // operation. Note we still need to append two scripts if necessary: autoscroll and clear
351             // hidden fields, because this code is called for a submit button.
352             //if (behaviors.isEmpty() && validParams != null && !validParams.isEmpty() )
353             //{
354             //    rendererOnClick.append(buildServerOnclick(facesContext, uiComponent, 
355             //            uiComponent.getClientId(facesContext), nestedFormInfo, validParams));
356             //}
357             //else
358             //{
359                 String formName = nestedFormInfo.getFormName();
360                 if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext()))
361                 {
362                     //call the script to clear the form (clearFormHiddenParams_<formName>) method
363                     HtmlRendererUtils.appendClearHiddenCommandFormParamsFunctionCall(rendererOnClick, formName);
364                 }
365         
366                 if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll())
367                 {
368                     HtmlRendererUtils.appendAutoScrollAssignment(rendererOnClick, formName);
369                 }
370             //}
371         }
372 
373         //according to the specification in jsf.util.chain jdocs and the spec document we have to use
374         //jsf.util.chain to chain the functions and
375         Collection<ClientBehaviorContext.Parameter> paramList = HtmlRendererUtils.getClientBehaviorContextParameters(
376                 HtmlRendererUtils.mapAttachedParamsToStringValues(facesContext, uiComponent));
377         
378         return HtmlRendererUtils.buildBehaviorChain(facesContext, uiComponent,
379                 ClientBehaviorEvents.CLICK, paramList, ClientBehaviorEvents.ACTION, paramList, behaviors,
380                 userOnClick.toString() , rendererOnClick.toString());
381     }
382     
383     protected String buildServerOnclick(FacesContext facesContext, UIComponent component, 
384             String clientId, FormInfo formInfo, List<UIParameter> validParams) throws IOException
385     {
386         UIComponent nestingForm = formInfo.getForm();
387         String formName = formInfo.getFormName();
388 
389         StringBuilder onClick = new StringBuilder();
390 
391         if (RendererUtils.isAdfOrTrinidadForm(formInfo.getForm()))
392         {
393             onClick.append("submitForm('");
394             onClick.append(formInfo.getForm().getClientId(facesContext));
395             onClick.append("',1,{source:'");
396             onClick.append(component.getClientId(facesContext));
397             onClick.append("'});return false;");
398         }
399         else
400         {
401             StringBuilder params = addChildParameters(facesContext, nestingForm, validParams);
402 
403             String target = getTarget(component);
404 
405             onClick.append("return ").
406                 append(HtmlRendererUtils.SUBMIT_FORM_FN_NAME_JSF2).append("('").
407                 append(formName).append("','").
408                 append(component.getClientId(facesContext)).append("'");
409 
410             if (params.length() > 2 || target != null)
411             {
412                 onClick.append(",").
413                     append(target == null ? "null" : ("'" + target + "'")).append(",").
414                     append(params);
415             }
416             onClick.append(");");
417 
418             //Not necessary since we are using oamSetHiddenInput to create input hidden fields
419             //render hidden field - todo: in here for backwards compatibility
420             //String hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo);
421             //addHiddenCommandParameter(facesContext, nestingForm, hiddenFieldName);
422 
423         }
424         return onClick.toString();
425     }
426     
427     private StringBuilder addChildParameters(FacesContext context, 
428             UIComponent nestingForm, List<UIParameter> validParams)
429     {
430         //add child parameters
431         StringBuilder params = new StringBuilder();
432         params.append("[");
433         
434         for (UIParameter param : validParams) 
435         {
436             String name = param.getName();
437 
438             //Not necessary, since we are using oamSetHiddenInput to create hidden fields
439             if (MyfacesConfig.getCurrentInstance(context.getExternalContext()).isRenderHiddenFieldsForLinkParams())
440             {
441                 addHiddenCommandParameter(context, nestingForm, name);
442             }
443 
444             Object value = param.getValue();
445 
446             //UIParameter is no ValueHolder, so no conversion possible - calling .toString on value....
447             // MYFACES-1832 bad charset encoding for f:param
448             // if HTMLEncoder.encode is called, then
449             // when is called on writer.writeAttribute, encode method
450             // is called again so we have a duplicated encode call.
451             // MYFACES-2726 All '\' and "'" chars must be escaped 
452             // because there will be inside "'" javascript quotes, 
453             // otherwise the value will not correctly restored when
454             // the command is post.
455             //String strParamValue = value != null ? value.toString() : "";
456             String strParamValue = "";
457             if (value != null)
458             {
459                 strParamValue = value.toString();
460                 StringBuilder buff = null;
461                 for (int i = 0; i < strParamValue.length(); i++)
462                 {
463                     char c = strParamValue.charAt(i); 
464                     if (c == '\'' || c == '\\')
465                     {
466                         if (buff == null)
467                         {
468                             buff = new StringBuilder();
469                             buff.append(strParamValue.substring(0,i));
470                         }
471                         buff.append('\\');
472                         buff.append(c);
473                     }
474                     else if (buff != null)
475                     {
476                         buff.append(c);
477                     }
478                 }
479                 if (buff != null)
480                 {
481                     strParamValue = buff.toString();
482                 }
483             }
484 
485             if (params.length() > 1) 
486             {
487                 params.append(",");
488             }
489 
490             params.append("['");
491             params.append(name);
492             params.append("','");
493             params.append(strParamValue);
494             params.append("']");
495         }
496         params.append("]");
497         return params;
498     }
499 
500     private String getTarget(UIComponent component)
501     {
502         // for performance reason: double check for the target attribute
503         String target;
504         if (component instanceof HtmlCommandLink)
505         {
506             target = ((HtmlCommandLink) component).getTarget();
507         }
508         else
509         {
510             target = (String) component.getAttributes().get(HTML.TARGET_ATTR);
511         }
512         return target;
513     }
514 
515     protected StringBuilder buildOnClick(UIComponent uiComponent, FacesContext facesContext,
516                                         ResponseWriter writer, List<UIParameter> validParams)
517         throws IOException
518     {
519         /* DUMMY STUFF
520         //Find form
521         UIComponent parent = uiComponent.getParent();
522         while (parent != null && !(parent instanceof UIForm))
523         {
524             parent = parent.getParent();
525         }
526 
527         UIForm nestingForm = null;
528         String formName;
529 
530         if (parent != null)
531         {
532             //link is nested inside a form
533             nestingForm = (UIForm)parent;
534             formName = nestingForm.getClientId(facesContext);
535 
536         }
537         else
538         {
539             //not nested in form, we must add a dummy form at the end of the document
540             formName = DummyFormUtils.DUMMY_FORM_NAME;
541             //dummyFormResponseWriter = DummyFormUtils.getDummyFormResponseWriter(facesContext);
542             //dummyFormResponseWriter.setWriteDummyForm(true);
543             DummyFormUtils.setWriteDummyForm(facesContext, true);
544         }
545         */
546         StringBuilder onClick = new StringBuilder();
547         String commandOnClick = (String) uiComponent.getAttributes().get(HTML.ONCLICK_ATTR);
548 
549         if (commandOnClick != null)
550         {
551             onClick.append("var cf = function(){");
552             onClick.append(commandOnClick);
553             onClick.append('}');
554             onClick.append(';');
555             onClick.append("var oamSF = function(){");
556         }
557         
558         FormInfo nestedFormInfo = findNestingForm(uiComponent, facesContext);
559         
560         if (nestedFormInfo != null)
561         {
562             String formName = nestedFormInfo.getFormName();
563             
564             if (validParams != null && !validParams.isEmpty() )
565             {
566                 StringBuilder params = addChildParameters(
567                         facesContext, nestedFormInfo.getForm(), validParams);
568 
569                 String target = getTarget(uiComponent);
570 
571                 onClick.append("return ").
572                     append(HtmlRendererUtils.SUBMIT_FORM_FN_NAME_JSF2).append("('").
573                     append(formName).append("','").
574                     append(uiComponent.getClientId(facesContext)).append("'");
575 
576                 if (params.length() > 2 || target != null)
577                 {
578                     onClick.append(",").
579                         append(target == null ? "null" : ("'" + target + "'")).append(",").
580                         append(params);
581                 }
582                 onClick.append(");");
583 
584                 //Not necessary since we are using oamSetHiddenInput to create input hidden fields
585                 //render hidden field - todo: in here for backwards compatibility
586                 if (MyfacesConfig.getCurrentInstance(
587                         facesContext.getExternalContext()).isRenderHiddenFieldsForLinkParams())
588                 {
589                     String hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(
590                             nestedFormInfo, facesContext);
591                     addHiddenCommandParameter(facesContext, nestedFormInfo.getForm(), hiddenFieldName);
592                 }
593             }
594             else
595             {
596         
597                 if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext()) ||
598                         MyfacesConfig.getCurrentInstance(
599                                 facesContext.getExternalContext()).isRenderHiddenFieldsForLinkParams() )
600                 {
601                     //call the script to clear the form (clearFormHiddenParams_<formName>) method
602                     HtmlRendererUtils.appendClearHiddenCommandFormParamsFunctionCall(onClick, formName);
603                 }
604         
605                 if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll())
606                 {
607                     HtmlRendererUtils.appendAutoScrollAssignment(onClick, formName);
608                 }
609             }
610         }
611         
612         if (commandOnClick != null)
613         {
614             onClick.append('}');
615             onClick.append(';');
616             onClick.append("return (cf.apply(this, [])==false)? false : oamSF.apply(this, []); ");
617         }  
618 
619         //The hidden field has only sense if isRenderClearJavascriptOnButton is
620         //set to true. In other case, this hidden field should not be rendered.
621         //if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext()))
622         //{
623             //add hidden field for the case there is no commandLink in the form
624             //String hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo);
625             //addHiddenCommandParameter(facesContext, nestingForm, hiddenFieldName);
626         //}
627 
628         return onClick;
629     }
630 
631     protected void addHiddenCommandParameter(FacesContext facesContext, 
632             UIComponent nestingForm, String hiddenFieldName)
633     {
634         if (nestingForm != null)
635         {
636             HtmlFormRendererBase.addHiddenCommandParameter(facesContext, nestingForm, hiddenFieldName);
637         }
638     }
639 
640     /**
641      * find nesting form<br />
642      * need to be overrideable to deal with dummyForm stuff in tomahawk.
643      */
644     protected FormInfo findNestingForm(UIComponent uiComponent, FacesContext facesContext)
645     {
646         return RendererUtils.findNestingForm(uiComponent, facesContext);
647     }
648 
649     protected boolean isDisabled(FacesContext facesContext, UIComponent uiComponent)
650     {
651         //TODO: overwrite in extended HtmlButtonRenderer and check for enabledOnUserRole
652         if (uiComponent instanceof HtmlCommandButton)
653         {
654             return ((HtmlCommandButton)uiComponent).isDisabled();
655         }
656 
657         return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(
658                 uiComponent, HTML.DISABLED_ATTR, false);
659         
660     }
661 
662     protected boolean isReadonly(FacesContext facesContext, UIComponent uiComponent)
663     {
664         if (uiComponent instanceof HtmlCommandButton)
665         {
666             return ((HtmlCommandButton)uiComponent).isReadonly();
667         }
668         return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(
669                 uiComponent, HTML.READONLY_ATTR, false);
670     }
671 
672     private String getType(UIComponent uiComponent)
673     {
674         if (uiComponent instanceof HtmlCommandButton)
675         {
676             return ((HtmlCommandButton)uiComponent).getType();
677         }
678         return (String)uiComponent.getAttributes().get(org.apache.myfaces.shared.renderkit.JSFAttr.TYPE_ATTR);
679     }
680 
681     private Object getValue(UIComponent uiComponent)
682     {
683         if (uiComponent instanceof ValueHolder)
684         {
685             return ((ValueHolder)uiComponent).getValue();
686         }
687         return uiComponent.getAttributes().get(JSFAttr.VALUE_ATTR);
688     }
689 }