You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/06/17 03:40:29 UTC

svn commit: r955444 - in /myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle: AbstractToggleGroup.java AbstractTogglePanel.java ToggleGroupRenderer.java ToggleLinkRenderer.java TogglePanelRenderer.java

Author: lu4242
Date: Thu Jun 17 01:40:29 2010
New Revision: 955444

URL: http://svn.apache.org/viewvc?rev=955444&view=rev
Log:
TOMAHAWK-1474 Behavior support for components that contains event aware properties in jsf 2.0 module

Added:
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/AbstractToggleGroup.java
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/AbstractTogglePanel.java
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/ToggleGroupRenderer.java
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/ToggleLinkRenderer.java
Modified:
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/TogglePanelRenderer.java

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/AbstractToggleGroup.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/AbstractToggleGroup.java?rev=955444&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/AbstractToggleGroup.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/AbstractToggleGroup.java Thu Jun 17 01:40:29 2010
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.custom.toggle;
+
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.component.html.HtmlPanelGroup;
+
+import org.apache.myfaces.component.EventAware;
+import org.apache.myfaces.component.UniversalProperties;
+
+/**
+ * Container class allows user to toggle between view/edit mode.
+ * 
+ * Extends PanelGroup. Allows user to have several toggleLink in a group. 
+ * When the togglePanel is toggled, the toggleGroup will be hidden.
+ * 
+ * @JSFComponent
+ *   name = "t:toggleGroup"
+ *   class = "org.apache.myfaces.custom.toggle.ToggleGroup"
+ *   tagClass = "org.apache.myfaces.custom.toggle.ToggleGroupTag"
+ *   
+ * @author Sharath
+ * 
+ */
+public abstract class AbstractToggleGroup extends HtmlPanelGroup
+    implements EventAware, UniversalProperties, ClientBehaviorHolder
+{
+    public static final String COMPONENT_TYPE = "org.apache.myfaces.ToggleGroup";
+    public static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.ToggleGroup";
+
+    public AbstractToggleGroup()
+    {
+        super();
+        setRendererType(AbstractToggleGroup.DEFAULT_RENDERER_TYPE);
+    }
+    
+    /**
+     * HTML: Flag to define the toggle status.
+     * 
+     * @JSFProperty
+     */
+     public abstract boolean isToggled();
+    
+     public abstract void setToggled(boolean toggleMode);
+    
+}

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/AbstractTogglePanel.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/AbstractTogglePanel.java?rev=955444&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/AbstractTogglePanel.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/AbstractTogglePanel.java Thu Jun 17 01:40:29 2010
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.custom.toggle;
+
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.component.html.HtmlPanelGroup;
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.component.EventAware;
+import org.apache.myfaces.component.UniversalProperties;
+
+/**
+ * Container class allows user to toggle between view/edit mode.
+ * 
+ * Extends PanelGroup. Allows user to toggle between 'view' mode and 'edit' mode. 
+ * In the togglePanel, include a toggleLink. When the toggleLink is clicked, 
+ * the rest of the group is shown, and the link is hidden.
+ * 
+ * @JSFComponent
+ *   name = "t:togglePanel"
+ *   class = "org.apache.myfaces.custom.toggle.TogglePanel"
+ *   tagClass = "org.apache.myfaces.custom.toggle.TogglePanelTag"
+ *   
+ * @author Sharath
+ * 
+ */
+public abstract class AbstractTogglePanel extends HtmlPanelGroup
+    implements EventAware, UniversalProperties, ClientBehaviorHolder
+{
+    public static final String COMPONENT_TYPE = "org.apache.myfaces.TogglePanel";
+    public static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.TogglePanel";
+
+    public static final boolean DEFAULT_TOGGLED = false;
+
+    public static final boolean DEFAULT_DISABLED = false;
+
+    /**
+     * You can set toggled to true to force the toggleGroup to always be in toggle 
+     * mode. Default is false.
+     * 
+     * @JSFProperty
+     *   defaultValue="false"
+     * @return
+     */
+    public abstract boolean isToggled();
+    
+    public abstract void setToggled(boolean toggleMode);
+    
+    /**
+     * @JSFProperty
+     *   defaultValue="false"
+     * @return
+     */
+    public abstract boolean isDisabled();
+    
+    public void processDecodes(FacesContext context)
+    {
+        super.processDecodes(context);
+
+        String hiddenFieldId = this.getClientId(context) + "_hidden";
+        String toggleMode = (String) context.getExternalContext().getRequestParameterMap().get(hiddenFieldId);
+
+        if (toggleMode != null && toggleMode.trim().equals("1")) {
+            this.setToggled(true);
+        }
+    }
+
+    public void processUpdates(FacesContext context)
+    {
+        super.processUpdates(context);
+        this.setToggled(false);
+    }
+}

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/ToggleGroupRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/ToggleGroupRenderer.java?rev=955444&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/ToggleGroupRenderer.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/ToggleGroupRenderer.java Thu Jun 17 01:40:29 2010
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.toggle;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlGroupRendererBase;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.util.ResourceUtils;
+
+/**
+ * 
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC" 
+ *   family = "javax.faces.Panel"
+ *   type = "org.apache.myfaces.ToggleGroup"
+ * 
+ */
+public class ToggleGroupRenderer extends HtmlGroupRendererBase {
+
+    @Override
+    public void decode(FacesContext context, UIComponent component)
+    {
+        super.decode(context, component);
+        
+        HtmlRendererUtils.decodeClientBehaviors(context, component);
+    }
+
+    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
+        ToggleGroup toggleGroup = (ToggleGroup) component;
+        ResponseWriter writer = context.getResponseWriter();
+
+        Map<String, List<ClientBehavior>> behaviors = null;
+        behaviors = toggleGroup.getClientBehaviors();
+        if (!behaviors.isEmpty())
+        {
+            ResourceUtils.renderDefaultJsfJsInlineIfNecessary(context, writer);
+        }
+        
+        writer.startElement( org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SPAN_ELEM, component );
+        writer.writeAttribute(HTML.ID_ATTR, component.getClientId(context), null);
+
+        if (behaviors != null && !behaviors.isEmpty())
+        {
+            HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.UNIVERSAL_ATTRIBUTES);
+            HtmlRendererUtils.renderBehaviorizedEventHandlers(context, writer, component, behaviors);
+        }
+        else
+        {
+            HtmlRendererUtils.renderHTMLAttributes( writer, component, HTML.COMMON_PASSTROUGH_ATTRIBUTES );
+        }
+
+        RendererUtils.renderChildren( context, component );
+
+        writer.endElement( HTML.SPAN_ELEM );
+    }
+}

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/ToggleLinkRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/ToggleLinkRenderer.java?rev=955444&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/ToggleLinkRenderer.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/ToggleLinkRenderer.java Thu Jun 17 01:40:29 2010
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.toggle;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIOutput;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.component.UserRoleUtils;
+import org.apache.myfaces.renderkit.html.ext.HtmlLinkRenderer;
+import org.apache.myfaces.shared_tomahawk.renderkit.ClientBehaviorEvents;
+import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
+
+/**
+ * Renderer for component HtmlAjaxChildComboBox
+ * 
+ * 
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC" 
+ *   family = "javax.faces.Output"
+ *   type = "org.apache.myfaces.ToggleLink"
+ * 
+ * @author Sharath Reddy
+ */
+public class ToggleLinkRenderer extends HtmlLinkRenderer {
+    public static final int DEFAULT_MAX_SUGGESTED_ITEMS = 200;
+
+    protected void renderOutputLinkStart(FacesContext facesContext,
+            UIOutput output) throws IOException
+    {
+        ResponseWriter writer = facesContext.getResponseWriter();
+    
+        String clientId = output.getClientId(facesContext);
+        
+        ToggleLink toggleLink = (ToggleLink) output;
+
+        //write anchor
+        writer.startElement(HTML.ANCHOR_ELEM, output);
+        writer.writeAttribute(HTML.ID_ATTR, clientId, null);
+        writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
+        writer.writeURIAttribute(HTML.HREF_ATTR, "javascript:void(0);", null);
+
+        Map<String, List<ClientBehavior>> behaviors = toggleLink.getClientBehaviors();        
+        if (behaviors != null && !behaviors.isEmpty())
+        {
+            HtmlRendererUtils.renderBehaviorizedEventHandlersWithoutOnclick(facesContext, writer, output, behaviors);
+            HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(facesContext, writer, output, behaviors);
+            HtmlRendererUtils
+                    .renderHTMLAttributes(
+                            writer,
+                            output,
+                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_STYLE_AND_EVENTS);
+            HtmlRendererUtils.renderBehaviorizedAttribute(facesContext, writer, HTML.ONCLICK_ATTR, output,
+                    ClientBehaviorEvents.CLICK, null, behaviors, HTML.ONCLICK_ATTR, null, buildOnclickToggleFunction(facesContext,output));
+        }
+        else
+        {
+            HtmlRendererUtils
+                    .renderHTMLAttributes(
+                            writer,
+                            output,
+                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_ONCLICK_WITHOUT_STYLE);
+            HtmlRendererUtils.renderHTMLAttribute(writer, HTML.ONCLICK_ATTR, HTML.ONCLICK_ATTR, 
+                    buildOnclickToggleFunction(facesContext,output));
+        }
+
+        HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR,
+                output.getAttributes().get(HTML.STYLE_ATTR));
+        HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR,
+                output.getAttributes().get(HTML.STYLE_CLASS_ATTR));
+        
+        writer.flush();
+    }
+    
+    protected void renderOutputLinkEnd(FacesContext facesContext, UIComponent component)
+        throws IOException
+    {
+        ResponseWriter writer = facesContext.getResponseWriter();
+        // force separate end tag
+        writer.writeText("", null);
+        writer.endElement(HTML.ANCHOR_ELEM);
+    }
+    
+    private String buildOnclickToggleFunction(FacesContext facesContext,
+            UIOutput output) throws IOException
+    {
+        ToggleLink toggleLink = (ToggleLink) output;
+        TogglePanel togglePanel = getParentTogglePanel(facesContext, toggleLink);
+        String[] componentsToToggle = toggleLink.getFor().split(",");
+        String idsToHide = getIdsToHide(facesContext, togglePanel);
+        StringBuffer idsToShow = new StringBuffer();
+        for (int i = 0; i < componentsToToggle.length; i++) {
+            String componentId = componentsToToggle[i].trim();
+            UIComponent componentToShow = toggleLink.findComponent(componentId);
+            if (componentToShow == null) {
+                Log log = LogFactory.getLog(ToggleLinkRenderer.class);
+                log.error("Unable to find component with id " + componentId);
+                continue;
+            }
+            if( idsToShow.length() > 0 )
+                idsToShow.append( ',' );
+            idsToShow.append( componentToShow.getClientId(facesContext) );
+        }
+        
+        String outputOnclick = toggleLink.getOnclick();
+        StringBuffer onClick = new StringBuffer();
+        if(outputOnclick != null)
+        {
+            onClick.append("var cf = function(){");
+            onClick.append(outputOnclick);
+            onClick.append('}');
+            onClick.append(';');
+            onClick.append("var oamSF = function(){");            
+        }
+
+        String onClickFocusClientId = toggleLink.getOnClickFocusId() != null ? toggleLink.findComponent(toggleLink.getOnClickFocusId()).getClientId(facesContext) : "";
+        onClick.append(getToggleJavascriptFunctionName(facesContext, toggleLink) + "('"+idsToShow+"','" + idsToHide + "','" + getHiddenFieldId(facesContext, togglePanel) + "','" + onClickFocusClientId + "');");
+                
+        if (outputOnclick != null)
+        {
+            onClick.append('}');
+            onClick.append(';');
+            onClick.append("return (cf()==false)? false : oamSF();");        
+        }        
+
+        return onClick.toString();
+    }
+            
+    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
+        RendererUtils.checkParamValidity(context, component, ToggleLink.class);
+
+        ToggleLink toggleLink = (ToggleLink) component;
+        if(isDisabled(context, toggleLink))
+            return;
+
+        super.encodeEnd(context, component);
+    }
+
+    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
+        RendererUtils.checkParamValidity(context, component, ToggleLink.class);
+
+        ToggleLink toggleLink = (ToggleLink) component;
+        if(isDisabled(context, toggleLink))
+            return;
+
+
+        super.encodeBegin(context, component);
+    }
+    
+    private String getToggleJavascriptFunctionName(FacesContext context,ToggleLink toggleLink){
+        for(UIComponent component = toggleLink.getParent(); component != null; component = component.getParent())
+            if( component instanceof TogglePanel )
+                return TogglePanelRenderer.getToggleJavascriptFunctionName( context, (TogglePanel)component );
+
+        Log log = LogFactory.getLog(ToggleLinkRenderer.class);
+        log.error("The ToggleLink component with id " + toggleLink.getClientId( context )+" isn't enclosed in a togglePanel.");
+        return null;
+    }
+    
+    private String getIdsToHide(FacesContext facesContext, TogglePanel togglePanel) {
+         StringBuffer idsToHide = new StringBuffer();
+         int idsToHideCount = 0;
+         for(Iterator it = togglePanel.getChildren().iterator(); it.hasNext(); ) {
+             UIComponent component = (UIComponent) it.next();
+             if ( TogglePanelRenderer.isHiddenWhenToggled( component ) ) {
+                 if( idsToHideCount > 0 )
+                     idsToHide.append( ',' );
+                 
+                 idsToHide.append( component.getClientId( facesContext ) );
+                 idsToHideCount++;
+             }
+         }
+         
+         return idsToHide.toString();
+    }
+    
+    private TogglePanel getParentTogglePanel(FacesContext facesContext, ToggleLink toggleLink) {
+         for(UIComponent component = toggleLink.getParent(); component != null; component = component.getParent()) {
+             if( component instanceof TogglePanel )
+                 return (TogglePanel) component;
+         }
+         
+         return null;
+    }
+    
+    private String getHiddenFieldId(FacesContext context, TogglePanel togglePanel){
+        return togglePanel.getClientId(context) + "_hidden";
+    }
+    
+    private boolean isDisabled(FacesContext facesContext, ToggleLink link) {
+        TogglePanel panel = getParentTogglePanel(facesContext, link);
+
+        return panel.isDisabled() || link.isDisabled() || !UserRoleUtils.isEnabledOnUserRole(link);
+    }
+}

Modified: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/TogglePanelRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/TogglePanelRenderer.java?rev=955444&r1=955443&r2=955444&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/TogglePanelRenderer.java (original)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/toggle/TogglePanelRenderer.java Thu Jun 17 01:40:29 2010
@@ -22,9 +22,12 @@ import java.io.IOException;
 import java.lang.reflect.Method;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import javax.faces.application.ResourceDependency;
 import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
+import javax.faces.component.behavior.ClientBehavior;
 import javax.faces.context.FacesContext;
 import javax.faces.context.ResponseWriter;
 
@@ -33,6 +36,8 @@ import org.apache.commons.logging.LogFac
 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlGroupRendererBase;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.util.ResourceUtils;
 
 /**
  * 
@@ -47,16 +52,33 @@ public class TogglePanelRenderer extends
 
     private static Log log = LogFactory.getLog(TogglePanelRenderer.class);
 
+    private static final String LAYOUT_BLOCK_VALUE = "block";
+
+    @Override
+    public void decode(FacesContext context, UIComponent component)
+    {
+        super.decode(context, component);
+        
+        HtmlRendererUtils.decodeClientBehaviors(context, component);
+    }
+
     public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
         RendererUtils.checkParamValidity(context, component, TogglePanel.class);
         //addToggleLinkJavascript(context);
         
         TogglePanel togglePanel = (TogglePanel) component;
-        boolean toggleMode = togglePanel.isToggled();
-        toggleVisibility(togglePanel.getChildren(), toggleMode);
-        
         // render the hidden input field
         ResponseWriter writer = context.getResponseWriter();
+        
+        Map<String, List<ClientBehavior>> behaviors = null;
+        behaviors = togglePanel.getClientBehaviors();
+        if (!behaviors.isEmpty())
+        {
+            ResourceUtils.renderDefaultJsfJsInlineIfNecessary(context, writer);
+        }
+        
+        boolean toggleMode = togglePanel.isToggled();
+        toggleVisibility(togglePanel.getChildren(), toggleMode);
 
         String hiddenFieldId = getHiddenFieldId(context, togglePanel);
 
@@ -69,7 +91,55 @@ public class TogglePanelRenderer extends
 
         writer.endElement(HTML.INPUT_ELEM);
 
-        super.encodeEnd(context, togglePanel);
+        //super.encodeEnd(context, togglePanel);
+        boolean span = false;
+
+        // will be SPAN or DIV, depending on the layout attribute value
+        String layoutElement = HTML.SPAN_ELEM;
+
+        // if layout is 'block', render DIV instead SPAN
+        String layout = togglePanel.getLayout();
+        if (layout != null && layout.equals(LAYOUT_BLOCK_VALUE))
+        {
+            layoutElement = HTML.DIV_ELEM;
+        }
+
+        if (behaviors != null && !behaviors.isEmpty())
+        {
+            //Render element and id to make javascript work
+            span = true;
+            writer.startElement(layoutElement, component);
+            writer.writeAttribute(HTML.ID_ATTR, component.getClientId(context),null);
+            HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.UNIVERSAL_ATTRIBUTES);
+            HtmlRendererUtils.renderBehaviorizedEventHandlers(context, writer, component, behaviors);
+        }
+        else
+        {
+            //No behaviors, do it as usual
+            if(component.getId()!=null && !component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
+            {
+                span = true;
+
+                writer.startElement(layoutElement, component);
+
+                HtmlRendererUtils.writeIdIfNecessary(writer, component, context);
+
+                HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.COMMON_PASSTROUGH_ATTRIBUTES);
+            }
+            else
+            {
+                span=HtmlRendererUtils.renderHTMLAttributesWithOptionalStartElement(writer,
+                                                                                 component,
+                                                                                 layoutElement,
+                                                                                 HTML.COMMON_PASSTROUGH_ATTRIBUTES);
+            }
+        }
+
+        RendererUtils.renderChildren(context, component);
+        if (span)
+        {
+            writer.endElement(layoutElement);
+        }
     }
 
     private void toggleVisibility(List children, boolean toggleMode) {