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 2011/03/18 17:59:55 UTC

svn commit: r1082972 - in /myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces: custom/radio/ custom/radio/AbstractHtmlRadio.java renderkit/html/ext/HtmlRadioRenderer.java

Author: lu4242
Date: Fri Mar 18 16:59:55 2011
New Revision: 1082972

URL: http://svn.apache.org/viewvc?rev=1082972&view=rev
Log:
TOMAHAWK-1551 f:ajax doesn't work in t:selectOneRadio layout="spread"

Added:
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/radio/
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/radio/AbstractHtmlRadio.java
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/radio/AbstractHtmlRadio.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/radio/AbstractHtmlRadio.java?rev=1082972&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/radio/AbstractHtmlRadio.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/radio/AbstractHtmlRadio.java Fri Mar 18 16:59:55 2011
@@ -0,0 +1,92 @@
+/*
+ * 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.radio;
+
+import javax.faces.component.UIComponentBase;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
+import org.apache.myfaces.component.UserRoleAware;
+
+/**
+ * This tag is used in conjunction with the extended selectOneRadio 
+ * tag when the "spread" layout is selected. It specifies the 
+ * position within the document that the radio button corresponding 
+ * to a specific SelectItem should be rendered. All HTML pass-through 
+ * attributes for this input are taken from the associated 
+ * selectOneRadio. 
+ * 
+ * Unless otherwise specified, all attributes accept static values or EL expressions.
+ * 
+ * @JSFComponent
+ *   name = "t:radio"
+ *   class = "org.apache.myfaces.custom.radio.HtmlRadio"
+ *   tagClass = "org.apache.myfaces.custom.radio.HtmlRadioTag"
+ * @since 1.1.7
+ * @author Thomas Spiegl (latest modification by $Author: lu4242 $)
+ * @version $Revision: 691856 $ $Date: 2008-09-03 21:40:30 -0500 (mié, 03 sep 2008) $
+ */
+public abstract class AbstractHtmlRadio
+    extends UIComponentBase implements UserRoleAware
+{
+    //private static final Log log = LogFactory.getLog(HtmlRadio.class);
+
+    public static final String FOR_ATTR = "for".intern();
+    public static final String INDEX_ATTR = "index".intern();
+
+
+    public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlRadio";
+    public static final String COMPONENT_FAMILY = "org.apache.myfaces.Radio";
+    private static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.Radio";
+
+    /**
+     * The id of the referenced extended selectOneRadio component. 
+     * This value is resolved to the particular component using 
+     * the standard UIComponent.findComponent() searching algorithm.
+     * 
+     * @JSFProperty
+     *   required="true"
+     */
+    public abstract String getFor();
+    
+    /**
+     * The index of the corresponding SelectItem, where 0 represents the first SelectItem.
+     * 
+     * @JSFProperty
+     *   defaultValue = "Integer.MIN_VALUE"
+     *   required="true"
+     */
+    public abstract int getIndex();
+    
+    /**
+     * If this property is set to true, the id generated for the input html markup
+     * will be the logical id composed from the clientId of the associated 
+     * selectOneRadio and the index of this component (for example 'myComp:2').
+     * 
+     * <p>
+     * NOTE: This is provided only for backward compatibility with tomahawk 1.2.
+     * Activate this behavior will make client behaviors added to 
+     * t:selectOneRadio like f:ajax or others fail, because the logical id 
+     * has no counterpart in the component tree.
+     * </p>
+     * 
+     * @return
+     */
+    @JSFProperty(defaultValue="false")
+    public abstract boolean isRenderLogicalId();
+}

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java?rev=1082972&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java Fri Mar 18 16:59:55 2011
@@ -0,0 +1,325 @@
+/*
+ * 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.renderkit.html.ext;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.component.UINamingContainer;
+import javax.faces.component.UISelectOne;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.convert.Converter;
+import javax.faces.model.SelectItem;
+
+import org.apache.myfaces.component.UserRoleUtils;
+import org.apache.myfaces.custom.radio.HtmlRadio;
+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.HtmlRadioRendererBase;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.util.JavascriptUtils;
+
+
+/**
+ * 
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC"
+ *   family = "org.apache.myfaces.Radio"
+ *   type = "org.apache.myfaces.Radio"
+ *    
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC"
+ *   family = "javax.faces.SelectOne"
+ *   type = "org.apache.myfaces.Radio"
+ * 
+ * @author Manfred Geiler (latest modification by $Author: lu4242 $)
+ * @author Thomas Spiegl
+ * @version $Revision: 685654 $ $Date: 2008-08-13 14:57:50 -0500 (mié, 13 ago 2008) $
+ */
+public class HtmlRadioRenderer
+        extends HtmlRadioRendererBase
+{
+    //private static final Log log = LogFactory.getLog(HtmlRadioRenderer.class);
+
+    private static final String LAYOUT_SPREAD = "spread";
+
+    public void encodeEnd(FacesContext context, UIComponent component) throws IOException
+    {
+        if (context == null) throw new NullPointerException("context");
+        if (component == null) throw new NullPointerException("component");
+
+        if (component instanceof HtmlRadio)
+        {
+            renderRadio(context, (HtmlRadio)component);
+        }
+        else if (HtmlRendererUtils.isDisplayValueOnly(component))
+        {
+            HtmlRendererUtils.renderDisplayValueOnlyForSelects(context, component);
+        }
+        else if (component instanceof UISelectOne)
+        {
+            String layout = getLayout(component);
+            if (layout != null && layout.equals(LAYOUT_SPREAD))
+            {
+                return; //radio inputs are rendered by spread radio components
+            }
+            else
+            {
+                super.encodeEnd(context, component);
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException("Unsupported component class " + component.getClass().getName());
+        }
+    }
+
+    protected void renderRadio(FacesContext facesContext, HtmlRadio radio) throws IOException
+    {
+        String forAttr = radio.getFor();
+        if (forAttr == null)
+        {
+            throw new IllegalStateException("mandatory attribute 'for'");
+        }
+        int index = radio.getIndex();
+        if (index < 0)
+        {
+            throw new IllegalStateException("positive index must be given");
+        }
+
+        UIComponent uiComponent = radio.findComponent(forAttr);
+        if (uiComponent == null)
+        {
+            throw new IllegalStateException("Could not find component '" + forAttr + "' (calling findComponent on component '" + radio.getClientId(facesContext) + "')");
+        }
+        if (!(uiComponent instanceof UISelectOne))
+        {
+            throw new IllegalStateException("UISelectOne expected");
+        }
+
+        UISelectOne uiSelectOne = (UISelectOne)uiComponent;
+        Converter converter;
+        List selectItemList = RendererUtils.getSelectItemList(uiSelectOne);
+        if (index >= selectItemList.size())
+        {
+            throw new IndexOutOfBoundsException("index " + index + " >= " + selectItemList.size());
+        }
+
+        try
+        {
+            converter = RendererUtils.findUIOutputConverter(facesContext, uiSelectOne);
+        }
+        catch (FacesException e)
+        {
+            converter = null;
+        }
+
+        Object currentValue = RendererUtils.getObjectValue(uiSelectOne);
+        currentValue
+            = RendererUtils.getConvertedStringValue(facesContext, uiSelectOne,
+                                                    converter, currentValue);
+        SelectItem selectItem = (SelectItem)selectItemList.get(index);
+        String itemStrValue
+            = RendererUtils.getConvertedStringValue(facesContext, uiSelectOne,
+                                                    converter,
+                                                    selectItem.getValue());
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        //writer.startElement(HTML.LABEL_ELEM, uiSelectOne);
+        
+        //renderRadio(facesContext,
+        //            uiSelectOne,
+        //            itemStrValue,
+        //            selectItem.getLabel(),
+        //            selectItem.isDisabled(),
+        //            itemStrValue.equals(currentValue), false);
+        //writer.endElement(HTML.LABEL_ELEM);
+
+        //Render the radio component
+        String itemId = renderRadio(
+                facesContext,
+                uiSelectOne,
+                radio,
+                itemStrValue,
+                selectItem.isDisabled(),
+                itemStrValue.equals(currentValue),
+                false,
+                index);
+        
+        //Render the
+        // label element after the input
+        boolean componentDisabled = isDisabled(facesContext, uiSelectOne);
+        boolean itemDisabled = selectItem.isDisabled();
+        boolean disabled = (componentDisabled || itemDisabled);
+
+        HtmlRendererUtils.renderLabel(writer, uiSelectOne, itemId, selectItem, disabled);
+    }
+    
+    protected String renderRadio(
+            FacesContext facesContext,
+            UISelectOne uiComponent, HtmlRadio radio, 
+            String value, boolean disabled,
+            boolean checked, boolean renderId, Integer itemNum)
+            throws IOException
+    {
+        String clientId = uiComponent.getClientId(facesContext);
+
+        String itemId = radio.isRenderLogicalId() ? 
+                clientId + UINamingContainer.getSeparatorChar(facesContext) + itemNum :
+                radio.getClientId(facesContext);
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        writer.startElement(HTML.INPUT_ELEM, uiComponent);
+        
+        // Force id rendering because it is necessary for the label
+        // and for @this work correctly
+        writer.writeAttribute(HTML.ID_ATTR, itemId, null);
+        
+        writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_RADIO, null);
+        writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
+        
+        
+        if (disabled)
+        {
+            writer.writeAttribute(HTML.DISABLED_ATTR, HTML.DISABLED_ATTR, null);
+        }
+
+        if (checked)
+        {
+            writer.writeAttribute(HTML.CHECKED_ATTR, HTML.CHECKED_ATTR, null);
+        }
+
+        if (value != null)
+        {
+            writer.writeAttribute(HTML.VALUE_ATTR, value, null);
+        }
+        
+        Map<String, List<ClientBehavior>> behaviors = null;
+        if (uiComponent instanceof ClientBehaviorHolder
+                && JavascriptUtils.isJavascriptAllowed(facesContext
+                        .getExternalContext()))
+        {
+            behaviors = ((ClientBehaviorHolder) uiComponent)
+                    .getClientBehaviors();
+
+            HtmlRendererUtils.renderBehaviorizedOnchangeEventHandler(facesContext, writer, uiComponent, itemId, behaviors);
+            HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext,writer, uiComponent, itemId, behaviors);
+            HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchange(facesContext, writer, uiComponent, itemId, behaviors);
+            HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.INPUT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED_AND_STYLE_AND_EVENTS);
+        }
+        else
+        {
+            HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.INPUT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED_AND_STYLE);
+        }
+        
+        if (isDisabled(facesContext, uiComponent))
+        {
+            writer.writeAttribute(
+                    org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.DISABLED_ATTR,
+                    Boolean.TRUE, null);
+        }
+
+        writer.endElement(HTML.INPUT_ELEM);
+
+        return itemId;
+    }
+
+    protected boolean isDisabled(FacesContext facesContext, UIComponent uiComponent)
+    {
+        if (!UserRoleUtils.isEnabledOnUserRole(uiComponent))
+        {
+            return true;
+        }
+        else
+        {
+            return super.isDisabled(facesContext, uiComponent);
+        }
+    }
+
+
+    public void decode(FacesContext facesContext, UIComponent uiComponent)
+    {
+        if (uiComponent instanceof HtmlRadio)
+        {
+            HtmlRadio radio = (HtmlRadio) uiComponent;
+            String forAttr = radio.getFor();
+            if (forAttr == null)
+            {
+                throw new IllegalStateException("mandatory attribute 'for'");
+            }
+            int index = radio.getIndex();
+            if (index < 0)
+            {
+                throw new IllegalStateException("positive index must be given");
+            }
+
+            UIComponent uiSelectOne = radio.findComponent(forAttr);
+            if (uiSelectOne == null)
+            {
+                throw new IllegalStateException("Could not find component '" + forAttr + "' (calling findComponent on component '" + radio.getClientId(facesContext) + "')");
+            }
+            if (!(uiSelectOne instanceof UISelectOne))
+            {
+                throw new IllegalStateException("UISelectOne expected");
+            }
+
+            if (uiSelectOne instanceof ClientBehaviorHolder) {
+                ClientBehaviorHolder clientBehaviorHolder = (ClientBehaviorHolder) uiSelectOne;
+
+                Map<String, List<ClientBehavior>> clientBehaviors =
+                        clientBehaviorHolder.getClientBehaviors();
+
+                if (clientBehaviors != null && !clientBehaviors.isEmpty()) {
+                    Map<String, String> paramMap = facesContext.getExternalContext().
+                            getRequestParameterMap();
+
+                    String behaviorEventName = paramMap.get("javax.faces.behavior.event");
+
+                    if (behaviorEventName != null) {
+                        List<ClientBehavior> clientBehaviorList = clientBehaviors.get(behaviorEventName);
+
+                        if (clientBehaviorList != null && !clientBehaviorList.isEmpty()) {
+                            String clientId = paramMap.get("javax.faces.source");
+
+                            if (radio.getClientId().equals(clientId)) {
+                                for (ClientBehavior clientBehavior : clientBehaviorList) {
+                                    clientBehavior.decode(facesContext, radio);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+            super.decode(facesContext, uiComponent);
+        }
+    }
+
+}