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.autoupdatedatatable;
20  
21  import org.apache.myfaces.renderkit.html.util.AddResource;
22  import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
23  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
24  import org.apache.myfaces.custom.ajax.api.AjaxRenderer;
25  import org.apache.myfaces.custom.prototype.PrototypeResourceLoader;
26  import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
27  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
28  import org.apache.myfaces.renderkit.html.ext.HtmlTableRenderer;
29  
30  import javax.faces.application.ViewHandler;
31  import javax.faces.component.UIComponent;
32  import javax.faces.context.FacesContext;
33  import javax.faces.context.ResponseWriter;
34  import java.io.IOException;
35  
36  /**
37   * 
38   * @JSFRenderer
39   *   renderKitId = "HTML_BASIC" 
40   *   family = "javax.faces.Data"
41   *   type = "org.apache.myfaces.AutoUpdateDataTable"
42   *
43   * @author Jörg Artaker
44   * @author Thomas Huber
45   * @version $Revision: $ $Date: $
46   *          <p/>
47   *          $Log: $
48   */
49  public class AutoUpdateDataTableRenderer extends HtmlTableRenderer implements AjaxRenderer{
50  
51      /**
52       * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
53       */
54      public void encodeBegin(FacesContext context, UIComponent uiComponent) throws IOException
55      {
56          // output div around here so it can work in IE, IE will not allow updating of innerHTML within a table
57          ResponseWriter out = context.getResponseWriter();
58          out.write("\n");
59          out.startElement(HTML.DIV_ELEM, uiComponent);
60          out.writeAttribute(HTML.ID_ATTR, "div" + uiComponent.getClientId(context),null);
61          // todo: output some table attributes to the div such as width and maybe alignment
62  
63          encodeBeginOnly(context, uiComponent);
64      }
65  
66      /**
67       * Encodes any stand-alone javascript functions that are needed.  Uses either the extension filter, or a
68       * user-supplied location for the javascript files.
69       *
70       * @param context FacesContext
71       * @param component UIComponent
72       */
73      private void encodeJavascript(FacesContext context, UIComponent component)
74      {
75          // AddResource takes care to add only one reference to the same script
76          
77          // render javascript function for client-side toggle (it won't be used if user has opted for server-side toggle)
78          String javascriptLocation = (String) component.getAttributes().get(
79                  JSFAttr.JAVASCRIPT_LOCATION);
80  
81          AddResource addResource = AddResourceFactory.getInstance(context);
82          if(javascriptLocation != null)
83          {
84              addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/prototype.js");
85          }
86          else
87          {
88              addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, 
89                      PrototypeResourceLoader.class, "prototype.js");
90          }
91      }
92  
93      /**
94       * @param context FacesContext
95       * @param component UIComponent
96       * @throws java.io.IOException
97       */
98      public void encodeEnd(FacesContext context, UIComponent component) throws IOException
99      {
100         RendererUtils.checkParamValidity(context, component, AutoUpdateDataTable.class);
101         AutoUpdateDataTable autoUpdateDataTable = (AutoUpdateDataTable) component;
102 
103         encodeEndOnly(context, component);
104         ResponseWriter out = context.getResponseWriter();
105         out.endElement(HTML.DIV_ELEM);
106         out.write("\n");
107 
108         this.encodeJavascript(context,component);
109 
110 
111 
112 
113         String viewId = context.getViewRoot().getViewId();
114         ViewHandler viewHandler = context.getApplication().getViewHandler();
115         String actionURL = viewHandler.getActionURL(context, viewId);
116         String clientId = component.getClientId(context);
117 
118         out.startElement(HTML.SCRIPT_ELEM, component);
119         out.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
120 
121         StringBuffer script = new StringBuffer();
122         script.append("function initAutoUpdateDataTable_");
123         script.append(component.getId());
124         script.append("()\n{");
125         script.append("\n");
126         script.append(component.getId()).append("_updater").append(" = new Ajax.PeriodicalUpdater('");
127         script.append("div").append(component.getClientId(context)); //.append(":tbody_element");
128         script.append("','");
129         script.append(context.getExternalContext().encodeActionURL(actionURL+"?affectedAjaxComponent="+clientId));
130         script.append("', {\n frequency: ").append(autoUpdateDataTable.getFrequency());
131         if (context.getApplication().getStateManager().isSavingStateInClient(context)){
132             script.append(" , parameters: '&jsf_tree_64='+encodeURIComponent(document.getElementById('jsf_tree_64').value)+'&jsf_state_64='+encodeURIComponent(document.getElementById('jsf_state_64').value)+'&jsf_viewid='+encodeURIComponent(document.getElementById('jsf_viewid').value)");
133         }
134         String onSuccess = autoUpdateDataTable.getOnSuccess();
135         if(onSuccess != null){
136             script.append(" , onSuccess: ").append(onSuccess);
137         }
138         script.append("    });");
139         script.append("\n}\n");
140         script.append("setTimeout(\"initAutoUpdateDataTable_");
141         script.append(component.getId());
142         script.append("()\", 0);\n");
143 
144         out.writeText(script.toString(),null);
145 
146         out.endElement(HTML.SCRIPT_ELEM);
147     }
148 
149     /**
150      * Pulled this out here so when getting a table update, it won't return the script
151      * @param context
152      * @param component
153      * @throws IOException
154      */
155     private void encodeEndOnly(FacesContext context, UIComponent component)
156             throws IOException
157     {
158         super.encodeEnd(context, component);
159     }
160 
161     /**
162      * Pulled this out here so when getting a table update, it won't do the containing div again
163      * @param context
164      * @param component
165      */
166     private void encodeBeginOnly(FacesContext context, UIComponent component) throws IOException
167     {
168         super.encodeBegin(context, component);
169     }
170 
171     /**
172      * @param facesContext FacesContext
173      * @param component UIComponent
174      */
175     public void decode(FacesContext facesContext, UIComponent component)
176     {
177         super.decode(facesContext, component);
178     }
179 
180     /**
181      * @param context FacesContext
182      * @param component UIComponent
183      * @throws java.io.IOException
184      */
185     public void encodeAjax(FacesContext context, UIComponent component) throws IOException
186     {
187         encodeBeginOnly(context, component);
188         encodeChildren(context, component);
189         encodeEndOnly(context, component);
190         /*if (context.getApplication().getStateManager().isSavingStateInClient(context)){
191             StateManager stateManager = context.getApplication().getStateManager();
192             StateManager.SerializedView serializedView = stateManager.saveSerializedView(context);
193             Object compStates =  serializedView.getState();
194 
195             StringBuffer buf = new StringBuffer();
196 
197             buf.append("jsf_state=");
198             buf.append(StateUtils.encode64(compStates));
199             buf.append("jsf_state_end");
200 
201             context.getResponseWriter().write(buf.toString());
202         }*/
203     }
204 
205 
206 }