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.toggle;
20  
21  import java.io.IOException;
22  import java.util.Iterator;
23  
24  import javax.faces.component.UIComponent;
25  import javax.faces.component.UIOutput;
26  import javax.faces.context.FacesContext;
27  import javax.faces.context.ResponseWriter;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.myfaces.component.UserRoleUtils;
32  import org.apache.myfaces.renderkit.html.ext.HtmlLinkRenderer;
33  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
34  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
35  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
36  
37  /**
38   * Renderer for component HtmlAjaxChildComboBox
39   * 
40   * 
41   * @JSFRenderer
42   *   renderKitId = "HTML_BASIC" 
43   *   family = "javax.faces.Output"
44   *   type = "org.apache.myfaces.ToggleLink"
45   * 
46   * @author Sharath Reddy
47   */
48  public class ToggleLinkRenderer extends HtmlLinkRenderer {
49      public static final int DEFAULT_MAX_SUGGESTED_ITEMS = 200;
50  
51      protected void renderOutputLinkStart(FacesContext facesContext,
52              UIOutput output) throws IOException
53      {
54          ResponseWriter writer = facesContext.getResponseWriter();
55      
56          String clientId = output.getClientId(facesContext);
57  
58          //write anchor
59          writer.startElement(HTML.ANCHOR_ELEM, output);
60          writer.writeAttribute(HTML.ID_ATTR, clientId, null);
61          writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
62          writer.writeURIAttribute(HTML.HREF_ATTR, "javascript:void(0);", null);
63          
64          HtmlRendererUtils
65                  .renderHTMLAttributes(
66                          writer,
67                          output,
68                          org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_ONCLICK_WITHOUT_STYLE);
69          HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR,
70                  output.getAttributes().get(HTML.STYLE_ATTR));
71          HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR,
72                  output.getAttributes().get(HTML.STYLE_CLASS_ATTR));
73          
74         HtmlRendererUtils.renderHTMLAttribute(writer, HTML.ONCLICK_ATTR, HTML.ONCLICK_ATTR, 
75                  buildOnclickToggleFunction(facesContext,output));
76         
77          writer.flush();
78      }
79      
80      protected void renderOutputLinkEnd(FacesContext facesContext, UIComponent component)
81          throws IOException
82      {
83          ResponseWriter writer = facesContext.getResponseWriter();
84          // force separate end tag
85          writer.writeText("", null);
86          writer.endElement(HTML.ANCHOR_ELEM);
87      }
88      
89      private String buildOnclickToggleFunction(FacesContext facesContext,
90              UIOutput output) throws IOException
91      {
92          ToggleLink toggleLink = (ToggleLink) output;
93          TogglePanel togglePanel = getParentTogglePanel(facesContext, toggleLink);
94          String[] componentsToToggle = toggleLink.getFor().split(",");
95          String idsToHide = getIdsToHide(facesContext, togglePanel);
96          StringBuffer idsToShow = new StringBuffer();
97          for (int i = 0; i < componentsToToggle.length; i++) {
98              String componentId = componentsToToggle[i].trim();
99              UIComponent componentToShow = toggleLink.findComponent(componentId);
100             if (componentToShow == null) {
101                 Log log = LogFactory.getLog(ToggleLinkRenderer.class);
102                 log.error("Unable to find component with id " + componentId);
103                 continue;
104             }
105             if( idsToShow.length() > 0 )
106                 idsToShow.append( ',' );
107             idsToShow.append( componentToShow.getClientId(facesContext) );
108         }
109         
110         String outputOnclick = toggleLink.getOnclick();
111         StringBuffer onClick = new StringBuffer();
112         if(outputOnclick != null)
113         {
114             onClick.append("var cf = function(){");
115             onClick.append(outputOnclick);
116             onClick.append('}');
117             onClick.append(';');
118             onClick.append("var oamSF = function(){");            
119         }
120 
121         String onClickFocusClientId = toggleLink.getOnClickFocusId() != null ? toggleLink.findComponent(toggleLink.getOnClickFocusId()).getClientId(facesContext) : "";
122         onClick.append(getToggleJavascriptFunctionName(facesContext, toggleLink) + "('"+idsToShow+"','" + idsToHide + "','" + getHiddenFieldId(facesContext, togglePanel) + "','" + onClickFocusClientId + "');");
123                 
124         if (outputOnclick != null)
125         {
126             onClick.append('}');
127             onClick.append(';');
128             onClick.append("return (cf()==false)? false : oamSF();");        
129         }        
130 
131         return onClick.toString();
132     }
133             
134     public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
135         RendererUtils.checkParamValidity(context, component, ToggleLink.class);
136 
137         ToggleLink toggleLink = (ToggleLink) component;
138         if(isDisabled(context, toggleLink))
139             return;
140 
141         super.encodeEnd(context, component);
142     }
143 
144     public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
145         RendererUtils.checkParamValidity(context, component, ToggleLink.class);
146 
147         ToggleLink toggleLink = (ToggleLink) component;
148         if(isDisabled(context, toggleLink))
149             return;
150 
151 
152         super.encodeBegin(context, component);
153     }
154     
155     private String getToggleJavascriptFunctionName(FacesContext context,ToggleLink toggleLink){
156         for(UIComponent component = toggleLink.getParent(); component != null; component = component.getParent())
157             if( component instanceof TogglePanel )
158                 return TogglePanelRenderer.getToggleJavascriptFunctionName( context, (TogglePanel)component );
159 
160         Log log = LogFactory.getLog(ToggleLinkRenderer.class);
161         log.error("The ToggleLink component with id " + toggleLink.getClientId( context )+" isn't enclosed in a togglePanel.");
162         return null;
163     }
164     
165     private String getIdsToHide(FacesContext facesContext, TogglePanel togglePanel) {
166          StringBuffer idsToHide = new StringBuffer();
167          int idsToHideCount = 0;
168          for(Iterator it = togglePanel.getChildren().iterator(); it.hasNext(); ) {
169              UIComponent component = (UIComponent) it.next();
170              if ( TogglePanelRenderer.isHiddenWhenToggled( component ) ) {
171                  if( idsToHideCount > 0 )
172                      idsToHide.append( ',' );
173                  
174                  idsToHide.append( component.getClientId( facesContext ) );
175                  idsToHideCount++;
176              }
177          }
178          
179          return idsToHide.toString();
180     }
181     
182     private TogglePanel getParentTogglePanel(FacesContext facesContext, ToggleLink toggleLink) {
183          for(UIComponent component = toggleLink.getParent(); component != null; component = component.getParent()) {
184              if( component instanceof TogglePanel )
185                  return (TogglePanel) component;
186          }
187          
188          return null;
189     }
190     
191     private String getHiddenFieldId(FacesContext context, TogglePanel togglePanel){
192         return togglePanel.getClientId(context) + "_hidden";
193     }
194     
195     private boolean isDisabled(FacesContext facesContext, ToggleLink link) {
196         TogglePanel panel = getParentTogglePanel(facesContext, link);
197 
198         return panel.isDisabled() || link.isDisabled() || !UserRoleUtils.isEnabledOnUserRole(link);
199     }
200 }