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  
20  package org.apache.myfaces.custom.inputAjax;
21  
22  import java.io.IOException;
23  import java.util.Map;
24  import java.util.HashMap;
25  
26  import javax.faces.component.UIComponent;
27  import javax.faces.context.FacesContext;
28  import javax.faces.context.ResponseWriter;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.myfaces.renderkit.html.util.AddResource;
33  import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
34  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
35  import org.apache.myfaces.custom.ajax.api.AjaxRenderer;
36  import org.apache.myfaces.custom.ajax.util.AjaxRendererUtils;
37  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
38  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
39  import org.apache.myfaces.renderkit.html.ext.HtmlCheckboxRenderer;
40  
41  /**
42   * 
43   * @JSFRenderer
44   *   renderKitId = "HTML_BASIC" 
45   *   family = "javax.faces.SelectBoolean"
46   *   type = "org.apache.myfaces.CheckboxAjax"
47   *
48   * User: treeder
49   * Date: Nov 21, 2005
50   * Time: 9:09:20 AM
51   */
52  public class HtmlSelectBooleanCheckboxAjaxRenderer extends HtmlCheckboxRenderer implements AjaxRenderer
53  {
54      private static final Log log = LogFactory.getLog(HtmlSelectBooleanCheckboxAjaxRenderer.class);
55      private static final String JAVASCRIPT_ENCODED = "org.apache.myfaces.custom.inputAjax.HtmlSelectBooleanCheckboxAjax.JAVASCRIPT_ENCODED";
56  
57  
58      /**
59       * Encodes any stand-alone javascript functions that are needed.
60       * Uses either the extension filter, or a
61       * user-supplied location for the javascript files.
62       *
63       * @param context   FacesContext
64       * @param component UIComponent
65       * @throws java.io.IOException
66       */
67      private void encodeJavascript(FacesContext context, UIComponent component) throws IOException
68      {
69  
70          HtmlSelectBooleanCheckboxAjax selectBooleanCheckbox = (HtmlSelectBooleanCheckboxAjax) component;
71  
72          // Add prototype script to header
73          AddResource addResource = AddResourceFactory.getInstance(context);
74          AjaxRendererUtils.addPrototypeScript(context, component, addResource);
75  
76          // write required javascript
77          ResponseWriter out = context.getResponseWriter();
78          String extraParams = null; //("&checked=\" + el.checked + \"");
79          AjaxRendererUtils.writeAjaxScript(context, out, selectBooleanCheckbox, extraParams);
80  
81          if (!context.getExternalContext().getRequestMap().containsKey(JAVASCRIPT_ENCODED))
82          {
83              // write a special script to swap out images onclick.
84              out.startElement(HTML.SCRIPT_ELEM, null);
85              out.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
86  
87              StringBuffer buff = new StringBuffer();
88              // todo: what if an error occurs? we should swap back to actual value back in server side model in an onComplete function
89              buff.append("function ").append(AjaxRendererUtils.JS_MYFACES_NAMESPACE).append("swapImages(imgEl, hiddenElId, onImg, offImg){\n")
90                      .append("    var hiddenEl = document.getElementById(hiddenElId);\n")
91                      .append("    var currValue = hiddenEl.value;\n")
92                      .append("    if(currValue == 'true') {\n")
93                      .append("        hiddenEl.value = 'false';\n")
94                      .append("        imgEl.src = offImg;\n")
95                      .append("    } else {\n")
96                      .append("        hiddenEl.value = 'true';\n")
97                      .append("        imgEl.src = onImg;\n")
98                      .append("    }\n")
99                      //.append("    if(imgEl.src == offImg) imgEl.src = onImg;\n")
100                     //.append("    if(imgEl.src == onImg) imgEl.src = offImg;\n")
101                     .append("}\n");
102             out.writeText(buff.toString(), null);
103 
104             out.endElement(HTML.SCRIPT_ELEM);
105         }
106 
107         // set request var to make sure this doesn't get written again
108         context.getExternalContext().getRequestMap().put(JAVASCRIPT_ENCODED, Boolean.TRUE);
109     }
110 
111 
112     public void encodeEnd(FacesContext context, UIComponent component) throws IOException
113     {
114         RendererUtils.checkParamValidity(context, component, HtmlSelectBooleanCheckboxAjax.class);
115         if (HtmlRendererUtils.isDisplayValueOnly(component) || isDisabled(context, component))
116         {
117             super.encodeEnd(context, component);
118             return;
119         }
120 
121         String clientId = component.getClientId(context);
122         HtmlSelectBooleanCheckboxAjax selectBooleanCheckbox = (HtmlSelectBooleanCheckboxAjax) component;
123 
124         // allow for user defined onclick's as well
125         String onClick = selectBooleanCheckbox.getOnclick();
126         if (onClick == null)
127         {
128             onClick = "";
129         }
130         onClick = AjaxRendererUtils.JS_MYFACES_NAMESPACE + "ajaxSubmit1('" + clientId + "'); " + onClick;
131         selectBooleanCheckbox.setOnclick(onClick);
132 
133         this.encodeJavascript(context, component);
134 
135         String onImgUrl = selectBooleanCheckbox.getOnImage();
136         String offImgUrl = selectBooleanCheckbox.getOffImage();
137         ResponseWriter out = context.getResponseWriter();
138         if (selectBooleanCheckbox.getOnImage() != null)
139         {
140 
141             Object valOb = selectBooleanCheckbox.getValue();
142             if (valOb != null)
143             {
144                 if (valOb instanceof Boolean)
145                 {
146                     Boolean val = (Boolean) valOb;
147 
148                     // then render an image instead
149                     // and a hidden input to store value
150                     out.startElement(HTML.INPUT_ELEM, null);
151                     out.writeAttribute(HTML.TYPE_ATTR, "hidden", null);
152                     out.writeAttribute(HTML.NAME_ATTR, clientId, null);
153                     out.writeAttribute(HTML.ID_ATTR, clientId, null);
154                     out.writeAttribute(HTML.VALUE_ATTR, val, null);
155                     out.endElement(HTML.INPUT_ELEM);
156 
157                     String imgUrl = val.booleanValue() ? onImgUrl : offImgUrl;
158                     out.startElement(HTML.IMG_ELEM, null);
159                     out.writeAttribute(HTML.SRC_ATTR, imgUrl, null);
160                     // add the swap image function to onClick as well
161                     onClick = AjaxRendererUtils.JS_MYFACES_NAMESPACE + "swapImages(this, '" + clientId + "', '" + onImgUrl + "', '" + offImgUrl + "'); " + onClick;
162                     out.writeAttribute(HTML.ONCLICK_ATTR, onClick, null);
163                     out.endElement(HTML.IMG_ELEM);
164                 }
165                 else
166                 {
167                     log.error("HtmlSelectBooleanAjax.value is not an instance of Boolean: " + valOb);
168                 }
169             }
170         }
171         else
172         {
173             super.encodeEnd(context, component);
174         }
175         AjaxRendererUtils.writeLoadingImage(context, component);
176     }
177 
178     public void encodeAjax(FacesContext context, UIComponent component) throws IOException
179     {
180         log.debug("entering HtmlSelectBooleanCheckboxAjaxRenderer.encodeAjax");
181 // check for request type (portlet support)
182         /*HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
183         */
184         Map extraReturnAttributes = new HashMap();
185         //extraReturnAttributes.put("checked", request.getParameter("checked"));
186         extraReturnAttributes.put("eltype", "checkbox");
187         AjaxRendererUtils.encodeAjax(context, component, null);
188     }
189 }