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.custom.jslistener;
20  
21  import java.io.IOException;
22  
23  import javax.faces.application.Application;
24  import javax.faces.application.ResourceDependency;
25  import javax.faces.component.UIComponent;
26  import javax.faces.component.UINamingContainer;
27  import javax.faces.context.FacesContext;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
32  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRenderer;
33  
34  /**
35   * @JSFRenderer
36   *   renderKitId = "HTML_BASIC" 
37   *   family = "javax.faces.Output"
38   *   type = "org.apache.myfaces.JsValueChangeListener"
39   * 
40   * @author Martin Marinschek (latest modification by $Author: skitching $)
41   * @version $Revision: 673833 $ $Date: 2008-07-03 16:58:05 -0500 (jue, 03 jul 2008) $
42   */
43  @ResourceDependency(library="oam.custom.jslistener",name="JSListener.js")
44  public class JsValueChangeListenerRenderer
45          extends HtmlRenderer
46  {
47      private static Log log = LogFactory.getLog(JsValueChangeListenerRenderer.class);
48  
49      public void encodeEnd(FacesContext facesContext, UIComponent component)
50              throws IOException
51      {
52          RendererUtils.checkParamValidity(facesContext, component, JsValueChangeListener.class);
53  
54          UIComponent parent = component.getParent();
55  
56          JsValueChangeListener jsValueChangeListener = (JsValueChangeListener) component;
57  
58  
59          String aFor = jsValueChangeListener.getFor();
60          String expressionValue = jsValueChangeListener.getExpressionValue();
61          String property = jsValueChangeListener.getProperty();
62  
63          //AddResourceFactory.getInstance(facesContext).addJavaScriptAtPosition(
64          //        facesContext, AddResource.HEADER_BEGIN, JsValueChangeListenerRenderer.class,
65          //        "JSListener.js");
66  
67          if(aFor!=null)
68          {
69              UIComponent forComponent = component.findComponent(aFor);
70  
71              String forComponentId = null;
72  
73              if (forComponent == null)
74              {
75                  if (log.isInfoEnabled())
76                  {
77                      log.info("Unable to find component '" + aFor + "' (calling findComponent on component '" + component.getClientId(getFacesContext()) + "') - will try to render component id based on the parent-id (on same level)");
78                  }
79                  if (aFor.length() > 0 && aFor.charAt(0) == UINamingContainer.SEPARATOR_CHAR)
80                  {
81                      //absolute id path
82                      forComponentId = aFor.substring(1);
83                  }
84                  else
85                  {
86                      //relative id path, we assume a component on the same level as the label component
87                      String labelClientId = component.getClientId(getFacesContext());
88                      int colon = labelClientId.lastIndexOf(UINamingContainer.SEPARATOR_CHAR);
89                      if (colon == -1)
90                      {
91                          forComponentId = aFor;
92                      }
93                      else
94                      {
95                          forComponentId = labelClientId.substring(0, colon + 1) + aFor;
96                      }
97                  }
98              }
99              else
100             {
101                 forComponentId = forComponent.getClientId(getFacesContext());
102             }
103 
104             expressionValue = expressionValue.replaceAll("\\'","\\\\'");
105             expressionValue = expressionValue.replaceAll("\"","\\\"");
106 
107 
108             String methodCall = "orgApacheMyfacesJsListenerSetExpressionProperty('"+
109                     parent.getClientId(getFacesContext())+"','"+
110                     forComponentId+"',"+
111                     (property==null?"null":"'"+property+"'")+
112                     ",'"+expressionValue+"');";
113 
114 
115             callMethod(facesContext, jsValueChangeListener, "onchange",methodCall);
116 
117             if (jsValueChangeListener.getBodyTagEvent() != null)
118             {
119                 callMethod(facesContext, jsValueChangeListener, jsValueChangeListener.getBodyTagEvent(), methodCall);
120             }
121 
122         }
123     }
124 
125     private void callMethod(FacesContext context, JsValueChangeListener jsValueChangeListener, String propName, String value)
126     {
127         UIComponent parent = jsValueChangeListener.getParent();
128 
129         Object oldValue = parent.getAttributes().get(propName);
130         
131         if(oldValue != null)
132         {
133             String oldValueStr = oldValue.toString().trim();
134 
135             // render the jsValueChangeListener script only for each parent component 
136             if(oldValueStr.indexOf(parent.getClientId(FacesContext.getCurrentInstance())) < 0
137                     && oldValueStr.length() > 0)
138             {
139                 oldValueStr = "";
140             }
141 
142             if(oldValueStr.length()>0 && !oldValueStr.endsWith(";"))
143                 oldValueStr +=";";
144 
145             value = oldValueStr + value;
146 
147         }
148 
149         if (!propName.equals("onchange") && value != null)
150         {
151             //TODO: this should be refactored to register a javascript-event-wrapper the java-script way
152             //in the current version of AddResource, this would not work anymore
153             /*AddResourceFactory.getInstance(context).
154                     addJavaScriptToBodyTag(context,jsValueChangeListener.getBodyTagEvent(), value);*/
155         }
156         else if(value != null)
157         {
158             parent.getAttributes().put(propName, value);
159         }
160         else
161         {
162             try
163             {
164                 parent.getAttributes().remove(propName);
165             }
166             catch(Exception ex)
167             {
168                 log.error("the value could not be removed : ",ex);
169             }
170         }
171     }
172 
173 
174     protected Application getApplication()
175     {
176         return getFacesContext().getApplication();
177     }
178 
179     protected FacesContext getFacesContext()
180     {
181         return FacesContext.getCurrentInstance();
182     }
183 
184 }