1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.custom.toggle;
20
21 import java.io.IOException;
22 import java.lang.reflect.Method;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26
27 import javax.faces.application.ResourceDependency;
28 import javax.faces.component.UIComponent;
29 import javax.faces.component.UIViewRoot;
30 import javax.faces.component.behavior.ClientBehavior;
31 import javax.faces.context.FacesContext;
32 import javax.faces.context.ResponseWriter;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
37 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
38 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlGroupRendererBase;
39 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
40 import org.apache.myfaces.shared_tomahawk.renderkit.html.util.ResourceUtils;
41
42
43
44
45
46
47
48
49
50 @ResourceDependency(library="oam.custom.toggle", name="MyFacesToggleLink.js")
51 public class TogglePanelRenderer extends HtmlGroupRendererBase {
52
53 private static Log log = LogFactory.getLog(TogglePanelRenderer.class);
54
55 private static final String LAYOUT_BLOCK_VALUE = "block";
56
57 @Override
58 public void decode(FacesContext context, UIComponent component)
59 {
60 super.decode(context, component);
61
62 HtmlRendererUtils.decodeClientBehaviors(context, component);
63 }
64
65 public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
66 RendererUtils.checkParamValidity(context, component, TogglePanel.class);
67
68
69 TogglePanel togglePanel = (TogglePanel) component;
70
71 ResponseWriter writer = context.getResponseWriter();
72
73 Map<String, List<ClientBehavior>> behaviors = null;
74 behaviors = togglePanel.getClientBehaviors();
75 if (!behaviors.isEmpty())
76 {
77 ResourceUtils.renderDefaultJsfJsInlineIfNecessary(context, writer);
78 }
79
80 boolean toggleMode = togglePanel.isToggled();
81 toggleVisibility(togglePanel.getChildren(), toggleMode);
82
83 String hiddenFieldId = getHiddenFieldId(context, togglePanel);
84
85 writer.startElement(HTML.INPUT_ELEM, component);
86 writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
87 writer.writeAttribute(HTML.ID_ATTR, hiddenFieldId, null);
88 writer.writeAttribute(HTML.NAME_ATTR, hiddenFieldId, null);
89
90 writer.writeAttribute(HTML.VALUE_ATTR, toggleMode ? "1" : "", null);
91
92 writer.endElement(HTML.INPUT_ELEM);
93
94
95 boolean span = false;
96
97
98 String layoutElement = HTML.SPAN_ELEM;
99
100
101 String layout = togglePanel.getLayout();
102 if (layout != null && layout.equals(LAYOUT_BLOCK_VALUE))
103 {
104 layoutElement = HTML.DIV_ELEM;
105 }
106
107 if (behaviors != null && !behaviors.isEmpty())
108 {
109
110 span = true;
111 writer.startElement(layoutElement, component);
112 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(context),null);
113 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.UNIVERSAL_ATTRIBUTES);
114 HtmlRendererUtils.renderBehaviorizedEventHandlers(context, writer, component, behaviors);
115 }
116 else
117 {
118
119 if(component.getId()!=null && !component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
120 {
121 span = true;
122
123 writer.startElement(layoutElement, component);
124
125 HtmlRendererUtils.writeIdIfNecessary(writer, component, context);
126
127 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.COMMON_PASSTROUGH_ATTRIBUTES);
128 }
129 else
130 {
131 span=HtmlRendererUtils.renderHTMLAttributesWithOptionalStartElement(writer,
132 component,
133 layoutElement,
134 HTML.COMMON_PASSTROUGH_ATTRIBUTES);
135 }
136 }
137
138 RendererUtils.renderChildren(context, component);
139 if (span)
140 {
141 writer.endElement(layoutElement);
142 }
143 }
144
145 private void toggleVisibility(List children, boolean toggleMode) {
146 for(Iterator it = children.iterator(); it.hasNext(); ) {
147 UIComponent component = (UIComponent) it.next();
148 setComponentVisibility( component, toggleMode );
149 }
150 }
151
152
153 public static boolean hasStyleAttribute(UIComponent component) {
154 Method[] methods = component.getClass().getMethods();
155
156 for (int i = 0; i < methods.length; i++) {
157 Method method = methods[i];
158 if (method.getName().equals("getStyle")) {
159 return true;
160 }
161 }
162 return false;
163 }
164
165
166 public static void setComponentVisibility(UIComponent component, boolean toggleMode) {
167 FacesContext context = FacesContext.getCurrentInstance();
168
169 if (!hasStyleAttribute(component)) {
170 log.info("style attribute expected, not found for component " + component.getClientId(context));
171 return;
172 }
173
174 try {
175 Class c = component.getClass();
176 Method getStyle = c.getMethod("getStyle", new Class[] {});
177 Method setStyle = c.getMethod("setStyle", new Class[] { String.class });
178
179 String style = (String) getStyle.invoke(component, new Object[] {});
180
181 boolean display = toggleMode != isHiddenWhenToggled(component);
182 if( display ){
183 if (style == null || style.length() == 0) {
184 return;
185 } else {
186 int index = style.indexOf(";display:none;");
187 if (index == -1)
188 return;
189
190 if (index == 0) {
191 style = null;
192 } else {
193 style = style.substring(0, index);
194 }
195 }
196 }else{
197 if (style == null) {
198 style = ";display:none;";
199 } else if (style.indexOf("display:none;") == -1) {
200 style = style.concat(";display:none;");
201 }
202 }
203
204 setStyle.invoke(component, new Object[] { style });
205 } catch (Throwable e) {
206 log.error("unable to set style attribute on component " + component.getClientId(context));
207 }
208 }
209
210 public static boolean isHiddenWhenToggled(UIComponent component){
211 return component instanceof ToggleLink || component instanceof ToggleGroup;
212 }
213
214 private String getHiddenFieldId(FacesContext context, TogglePanel togglePanel){
215 return togglePanel.getClientId(context) + "_hidden";
216 }
217
218 static public String getToggleJavascriptFunctionName(FacesContext context, TogglePanel togglePanel) {
219 return "MyFacesToggleLinkUtils.toggle";
220 }
221
222
223
224
225
226
227
228 }