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.effect;
21  
22  import java.io.IOException;
23  
24  import javax.faces.component.UIComponent;
25  import javax.faces.context.FacesContext;
26  import javax.faces.context.ResponseWriter;
27  
28  import org.apache.myfaces.custom.div.Div;
29  import org.apache.myfaces.custom.dojo.DojoConfig;
30  import org.apache.myfaces.custom.dojo.DojoUtils;
31  import org.apache.myfaces.custom.prototype.PrototypeResourceLoader;
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.JSFAttr;
35  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
36  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
37  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRenderer;
38  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
39  
40  /**
41   * Fade field only currently the renderer is implemented and the tag, because we
42   * do not store any extra functionality over a simple div in here
43  
44   * For the fade, we only need a simple renderer and a backend javascript
45   * inclusion so that we can serve it out of the jar
46   *
47   * @JSFRenderer
48   *   renderKitId = "HTML_BASIC" 
49   *   family = "javax.faces.Output"
50   *   type = "org.apache.myfaces.effect.EffectRenderer"
51   *
52   * @author Werner Punz werpu@gmx.at
53   * @version $Revision: 673833 $ $Date: 2008-07-03 16:58:05 -0500 (Thu, 03 Jul 2008) $
54   */
55  public class EffectRenderer extends HtmlRenderer
56  {
57      private static final String DEFAULT_FADE_COLOR = "red";
58      public static final String  RENDERER_TYPE      = "org.apache.myfaces.effect.EffectRenderer";
59  
60      public static final String  TAG_PARAM_FADECOLOR     = "fadeColor";
61  
62      public static final String  TAG_PARAM_FADE          = "fade";
63  
64      public static final String  TAG_PARAM_DURATION      = "duration";
65      
66      public static final String  TAG_PARAM_SQUISH        = "squish";
67  
68      public static final String  TAG_PARAM_SCALE         = "scale";
69  
70      public static final String  TAG_PARAM_SCALE_SIZE    = "scaleSize";
71  
72      public static final String  TAG_PARAM_PUFF          = "puff";
73  
74      public static final String  TAG_PARAM_PULSATE       = "pulsate";
75      
76      /**
77       * Encodes any stand-alone javascript functions that are needed. Uses either
78       * the extension filter, or a user-supplied location for the javascript
79       * files.
80       *
81       * @param context
82       *            FacesContext
83       * @param component
84       *            UIComponent
85       */
86      private void encodeJavascript(FacesContext context, UIComponent component)
87      {
88          // AddResource takes care to add only one reference to the same script
89  
90          // render javascript function for client-side toggle (it won't be used
91          // if user has opted for server-side toggle)
92          String javascriptLocation = (String) component.getAttributes().get(JSFAttr.JAVASCRIPT_LOCATION);
93          AddResource addResource = AddResourceFactory.getInstance(context);
94          Boolean fade = (Boolean) component.getAttributes().get(TAG_PARAM_FADE);
95  
96          try
97          {
98              if (javascriptLocation != null)
99              {
100 
101                 addResource
102                         .addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/prototype.js");
103                 addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/effects.js");
104                 addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/fader.js");
105 
106                 if (fade != null && fade.booleanValue())
107                     DojoUtils.addMainInclude(context, component, javascriptLocation, new DojoConfig());
108            
109             }
110             else
111             {
112 
113                 addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, PrototypeResourceLoader.class,
114                         "prototype.js");
115                 addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, PrototypeResourceLoader.class,
116                         "effects.js");
117                 if (fade != null && fade.booleanValue())
118                     DojoUtils.addMainInclude(context, component, null, new DojoConfig());
119 
120                 if (!DojoUtils.isInlineScriptSet(context, "fader.js"))
121                     addResource.addJavaScriptHere(context, EffectRenderer.class, "fader.js");
122 
123             
124             }
125         }
126         catch (IOException e)
127         {
128          
129             e.printStackTrace();
130         }
131     }
132 
133     public boolean getRendersChildren()
134     {
135         return true;
136     }
137 
138     /**
139      * We only need an encodeBeing method because the fade control, does not
140      * have any childs
141      *
142      * The fading is done via a styleClass tag according to the FAT specs, for
143      * now this is more flexible than embedding yet another tag in another tag
144      * but less flexible for styleClass usage reasons (but you always can use
145      * x:div for handling this issue in a proper manner)
146      *
147      * we have to do a full overload unfortunately because it is altered
148      * severely
149      *
150      */
151     public void encodeBegin(FacesContext context, UIComponent component) throws IOException
152     {
153         if ((context == null) || (component == null))
154         {
155             throw new NullPointerException();
156         }
157 
158         Boolean rendered = (Boolean) component.getAttributes().get("rendered");
159 
160         if ((rendered != null) && (!rendered.booleanValue()))
161             return;
162         encodeJavascript(context, component);
163         super.encodeBegin(context, component);
164 
165         renderEffectsBegin(context, component);
166     }
167 
168     /**
169      * prepares the styleClasses for the fading renderer
170      *
171      * @param component
172      */
173     private String getFadeColor(UIComponent component)
174     {
175 
176         Boolean fade = (Boolean) component.getAttributes().get(TAG_PARAM_FADE);
177 
178         if (fade != null && fade.booleanValue())
179         {
180 
181             String fadeColor = (String) component.getAttributes().get(TAG_PARAM_FADECOLOR);
182             fadeColor = (fadeColor != null) ? fadeColor : DEFAULT_FADE_COLOR;
183             fadeColor = fadeColor.equals("") ? DEFAULT_FADE_COLOR : fadeColor;
184             if(fadeColor.trim().matches("^\\\\[(.*\\,)+\\\\]$")) //pattern [col,col,col] roughly
185                 return fadeColor;
186             else return "\""+fadeColor+"\"";
187             
188         }
189         return null;
190     }
191 
192     public void renderEffectsBegin(FacesContext context, UIComponent component) throws IOException
193     {
194 
195         // dump all the parameters which affect us into we dont set a central
196         // unchecked here to keep the warning level high
197         Boolean squish = (Boolean) component.getAttributes().get(TAG_PARAM_SQUISH);
198         Boolean puff = (Boolean) component.getAttributes().get(TAG_PARAM_PUFF);
199         Boolean scale = (Boolean) component.getAttributes().get(TAG_PARAM_SCALE);
200         Boolean pulsate = (Boolean) component.getAttributes().get(TAG_PARAM_PULSATE);
201         Integer scaleSize = (Integer) component.getAttributes().get(TAG_PARAM_SCALE_SIZE);
202 
203         Div div = (Div) component;
204         ResponseWriter writer = context.getResponseWriter();
205 
206         // if(fade != null && fade.booleanValue())
207         // ScriptController.renderScriptWithDeps(context, component, writer,
208         // ScriptController.FAT_VIEW_ID);
209         if (puff != null && puff.booleanValue())
210         {
211             //writer.writeAttribute(HTML.ONCLICK_ATTR, "javascript:new Effect.Puff(this);", null);
212             writer.startElement(HTML.SCRIPT_ELEM, component);
213             writer.writeAttribute(HTML.TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
214             writer.write("var "+component.getClientId(context).replaceAll("\\:","_")+"_fader = new org_apache_myfaces_effects_fader('"+component.getClientId(context)+"',300);");
215             writer.endElement(HTML.SCRIPT_ELEM);
216         }
217   
218         writer.startElement(HTML.DIV_ELEM, component);
219         HtmlRendererUtils.writeIdIfNecessary(writer, component, context);
220 
221         String styleClass = div.getStyleClass();
222         String style = div.getStyle();
223         if (null != styleClass && null != style)
224         {
225             throw new IllegalStateException("Only one of style or styleClass can be specified");
226         }
227         if (null != styleClass)
228         {
229             writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
230         }
231         if (null != style)
232         {
233             writer.writeAttribute(HTML.STYLE_ATTR, style, null);
234         }
235         // todo check the existing code for already existent javascript code
236         // not needed now, but probably in the long run
237 
238         if (puff != null && puff.booleanValue())
239         {
240             writer.writeAttribute(HTML.ONCLICK_ATTR, "javascript:"+component.getClientId(context).replaceAll("\\:","_")+"_fader.fadeOut();", null);
241             //writer.startElement(HTML.SCRIPT_ELEM, component);
242             //writer.writeAttribute(HTML.TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
243             ///writer.write("var "+component.getClientId(context).replaceAll("\\:","_")+"_fader = new org_apache_myfaces_effects_fader('"+component.getClientId(context)+"',300);");
244             //writer.endElement(HTML.SCRIPT_ELEM);
245         }
246         if (squish != null && squish.booleanValue())
247         {
248             writer.writeAttribute(HTML.ONCLICK_ATTR, "javascript:new Effect.Squish(this);", null);
249         }
250         if (pulsate != null && pulsate.booleanValue())
251         {
252             writer.writeAttribute(HTML.ONCLICK_ATTR, "javascript:new Effect.Pulsate(this);", null);
253         }
254         if (scale != null && scale.booleanValue())
255         {
256             writer.writeAttribute(HTML.ONMOUSEOVER_ATTR, "javascript:new Effect.Scale(this," + scaleSize.toString()
257                     + ");", null);
258             writer.writeAttribute(HTML.ONMOUSEOUT_ATTR, "javascript:new Effect.Scale(this,100);", null);
259         }
260 
261     }
262 
263     /*
264      * (non-Javadoc)
265      *
266      * @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext,
267      *      javax.faces.component.UIComponent)
268      */
269     public void encodeChildren(FacesContext facesContext, UIComponent uiComponent) throws IOException
270     {
271 
272         RendererUtils.renderChildren(facesContext, uiComponent);
273         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
274     }
275 
276     /**
277      * Standard encode end
278      *
279      */
280     public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException
281     {
282         ResponseWriter writer = facesContext.getResponseWriter();
283         writer.endElement(HTML.DIV_ELEM);
284         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
285         super.encodeEnd(facesContext, component);
286         Boolean rendered = (Boolean) component.getAttributes().get("rendered");
287 
288         if ((rendered != null) && (!rendered.booleanValue()))
289             return;
290 
291         Boolean fade = (Boolean) component.getAttributes().get(TAG_PARAM_FADE);
292         Integer duration = (Integer) component.getAttributes().get(TAG_PARAM_DURATION);
293 
294         if (fade != null && fade.booleanValue())
295         {
296             DojoUtils.addRequire(facesContext,component, "dojo.lfx.*");
297             writer.startElement(HTML.SCRIPT_ELEM, component);
298             writer.writeAttribute(HTML.TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
299             writer.writeAttribute(HTML.SCRIPT_LANGUAGE_ATTR, HTML.SCRIPT_LANGUAGE_JAVASCRIPT, null);
300             StringBuffer commandBuffer = new StringBuffer(128);
301             commandBuffer.append("dojo.lfx.html.highlight('");
302             commandBuffer.append(component.getClientId(facesContext));
303             commandBuffer.append("',");
304             commandBuffer.append(getFadeColor(component));
305             commandBuffer.append(",0).play(" + duration.toString() + ");");
306             writer.write(commandBuffer.toString());
307             writer.endElement(HTML.SCRIPT_ELEM);
308 
309         }
310     }
311 
312 }