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.submitOnEvent;
20  
21  import org.apache.myfaces.custom.dialog.ModalDialog;
22  import org.apache.myfaces.custom.dojo.DojoUtils;
23  import org.apache.myfaces.renderkit.html.util.AddResource;
24  import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
25  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
26  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRenderer;
27  
28  import javax.faces.component.ActionSource;
29  import javax.faces.component.EditableValueHolder;
30  import javax.faces.component.UICommand;
31  import javax.faces.component.UIComponent;
32  import javax.faces.component.UIInput;
33  import javax.faces.component.UISelectBoolean;
34  import javax.faces.component.UISelectMany;
35  import javax.faces.component.UISelectOne;
36  import javax.faces.context.FacesContext;
37  import javax.faces.context.ResponseWriter;
38  import java.io.IOException;
39  import java.util.Arrays;
40  import java.util.Set;
41  import java.util.TreeSet;
42  
43  /**
44   * Attach an event handler to an input element or use a global event handler to
45   * submit a form by "clicking" on a link or button
46   *
47   * 
48   * @JSFRenderer
49   *   renderKitId = "HTML_BASIC" 
50   *   family = "org.apache.myfaces.SubmitOnEvent"
51   *   type = "org.apache.myfaces.SubmitOnEvent"
52   * 
53   * @version $Id: SubmitOnEventRenderer.java 673833 2008-07-03 21:58:05Z skitching $
54   */
55  public class SubmitOnEventRenderer extends HtmlRenderer
56  {
57      private final static Set ON_CHANGE_FAMILY = new TreeSet(Arrays.asList(new String[]
58      {
59          UISelectBoolean.COMPONENT_FAMILY,
60          UISelectMany.COMPONENT_FAMILY,
61          UISelectOne.COMPONENT_FAMILY
62      }));
63  
64      public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException
65      {
66          SubmitOnEvent submitOnEvent = (SubmitOnEvent) uiComponent;
67  
68          UIComponent forComponent = null;
69  
70          UIComponent triggerComponent = null;
71          UIComponent parent = uiComponent.getParent();
72          if (parent != null)
73          {
74              if (UIInput.COMPONENT_FAMILY.equals(parent.getFamily())
75                  || parent instanceof UIInput
76                  || parent instanceof ModalDialog
77                  || parent instanceof EditableValueHolder)
78              {
79                  triggerComponent = parent;
80              }
81              else if (UICommand.COMPONENT_FAMILY.equals(parent.getFamily())
82                  || parent instanceof UICommand
83                  || parent instanceof ActionSource)
84              {
85                  forComponent = parent;
86              }
87          }
88  
89          if (triggerComponent != null && !triggerComponent.isRendered())
90          {
91              // the component we are attaced to is not being rendered, so we can quit now ...
92              return;
93          }
94  
95          if (forComponent == null)
96          {
97              String forComponentId = submitOnEvent.getFor();
98              if (forComponentId == null)
99              {
100                 throw new IllegalArgumentException("SubmitOnEvent: attribute 'for' missing");
101             }
102 
103             forComponent = uiComponent.findComponent(forComponentId);
104             if (forComponent == null)
105             {
106                 throw new IllegalArgumentException("SubmitOnEvent: can't find 'for'-component '" + forComponentId + "'");
107             }
108         }
109 
110         AddResourceFactory.getInstance(facesContext).addJavaScriptAtPosition(
111                 facesContext, AddResource.HEADER_BEGIN, SubmitOnEventRenderer.class,
112                 "submitOnEvent.js");
113 
114         // If the dojo library will be loaded, use it to attach to the onLoad handler.
115         // Do NOT use dojo if no other component requires it, this avoids loading of this
116         // heavy-weight javascript-library for just the simple submitOnEvent use-case.
117         // We do this for better integration with dojo widget (e.g. our ModalDialog)
118         // where using the timeout stuff is not appropriate.
119         boolean useDojoForInit = DojoUtils.isDojoInitialized(facesContext);
120 
121         StringBuffer js = new StringBuffer(80);
122 
123         if (useDojoForInit)
124         {
125             js.append("dojo.addOnLoad(function() {");
126         }
127         else
128         {
129             js.append("setTimeout(\"");
130         }
131         js.append("orgApacheMyfacesSubmitOnEventRegister('");
132         if (submitOnEvent.getEvent() != null)
133         {
134             js.append(submitOnEvent.getEvent().toLowerCase());
135         }
136         else
137         {
138             if (triggerComponent != null
139                 && triggerComponent.getFamily() != null
140                 && ON_CHANGE_FAMILY.contains(triggerComponent.getFamily()))
141             {
142                 js.append("change");
143             }
144             else
145             {
146                 js.append("keypress");
147             }
148         }
149         js.append("','");
150         if (submitOnEvent.getCallback() != null)
151         {
152             js.append(submitOnEvent.getCallback());
153         }
154         js.append("','");
155         if (triggerComponent != null)
156         {
157             if (triggerComponent instanceof ModalDialog)
158             {
159                 js.append(((ModalDialog) triggerComponent).getDialogVar());
160             }
161             else
162             {
163                 js.append(triggerComponent.getClientId(facesContext));
164             }
165         }
166         js.append("','");
167         js.append(forComponent.getClientId(facesContext));
168         js.append("');");
169         // js.append("');");
170         if (useDojoForInit)
171         {
172             js.append("});");
173         }
174         else
175         {
176             js.append("\", 100)");
177         }
178 
179         // AddResourceFactory.getInstance(facesContext).addInlineScriptAtPosition(facesContext, AddResource.BODY_END, js.toString());
180 
181         ResponseWriter out = facesContext.getResponseWriter();
182         out.startElement(HTML.SCRIPT_ELEM, uiComponent);
183         out.writeAttribute(HTML.SCRIPT_LANGUAGE_ATTR, HTML.SCRIPT_LANGUAGE_JAVASCRIPT, null);
184         out.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
185         out.writeText(js.toString(), null);
186         out.endElement(HTML.SCRIPT_ELEM);
187     }
188 }