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/11/17 01:16:50 UTC

svn commit: r1202947 [2/5] - in /myfaces/shared/trunk_4.0.x: ./ core/ core/src/main/java/org/apache/myfaces/shared/application/ core/src/main/java/org/apache/myfaces/shared/component/ core/src/main/java/org/apache/myfaces/shared/config/ core/src/main/j...

Added: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlJavaScriptUtils.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlJavaScriptUtils.java?rev=1202947&view=auto
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlJavaScriptUtils.java (added)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlJavaScriptUtils.java Thu Nov 17 00:16:48 2011
@@ -0,0 +1,756 @@
+/*
+ * 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.shared.renderkit.html;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.faces.component.UINamingContainer;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.myfaces.shared.config.MyfacesConfig;
+import org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils.ScriptContext;
+import org.apache.myfaces.shared.renderkit.html.util.JavascriptUtils;
+import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
+
+public final class HtmlJavaScriptUtils
+{
+    private static final Logger log = Logger.getLogger(HtmlJavaScriptUtils.class
+            .getName());
+
+    private static final String AUTO_SCROLL_PARAM = "autoScroll";
+    private static final String AUTO_SCROLL_FUNCTION = "getScrolling";
+
+    private static final String SET_HIDDEN_INPUT_FN_NAME = "oamSetHiddenInput";
+    private static final String SET_HIDDEN_INPUT_FN_NAME_JSF2 = "myfaces.oam.setHiddenInput";
+
+    private static final String FIRST_SUBMIT_SCRIPT_ON_PAGE = "org.apache.MyFaces.FIRST_SUBMIT_SCRIPT_ON_PAGE";
+    private static final String CLEAR_HIDDEN_INPUT_FN_NAME = "oamClearHiddenInput";
+    
+
+    @SuppressWarnings("unchecked")
+    public static void renderFormSubmitScript(FacesContext facesContext)
+            throws IOException
+    {
+
+        Map map = facesContext.getExternalContext().getRequestMap();
+        Boolean firstScript = (Boolean) map.get(FIRST_SUBMIT_SCRIPT_ON_PAGE);
+
+        if (firstScript == null || firstScript.equals(Boolean.TRUE))
+        {
+            map.put(FIRST_SUBMIT_SCRIPT_ON_PAGE, Boolean.FALSE);
+            renderFormSubmitScriptIfNecessary(facesContext);
+
+            //we have to render the config just in case
+            renderConfigOptionsIfNecessary(facesContext);
+        }
+    }
+    
+    /**
+     * @param facesContext
+     * @throws IOException
+     */
+    private static void renderFormSubmitScriptIfNecessary(
+            FacesContext facesContext) throws IOException
+    {
+        final ExternalContext externalContext = facesContext
+                .getExternalContext();
+        final MyfacesConfig currentInstance = MyfacesConfig
+                .getCurrentInstance(externalContext);
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        if (currentInstance.isRenderFormSubmitScriptInline())
+        {
+            writer.startElement(HTML.SCRIPT_ELEM, null);
+            writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
+
+            boolean autoScroll = currentInstance.isAutoScroll();
+
+            ScriptContext context = new ScriptContext(
+                    currentInstance.isPrettyHtml());
+            context.prettyLine();
+            context.increaseIndent();
+
+            prepareScript(facesContext, context, autoScroll);
+
+            writer.writeText(context.toString(), null);
+
+            writer.endElement(HTML.SCRIPT_ELEM);
+        }
+        else
+        {
+            ResourceUtils
+                    .renderMyfacesJSInlineIfNecessary(facesContext, writer);
+        }
+    }
+    
+    private static void renderConfigOptionsIfNecessary(FacesContext facesContext)
+            throws IOException
+    {
+        ResponseWriter writer = facesContext.getResponseWriter();
+        MyfacesConfig config = MyfacesConfig.getCurrentInstance(facesContext
+                .getExternalContext());
+        ScriptContext script = new ScriptContext(config.isPrettyHtml());
+        boolean autoScroll = config.isAutoScroll();
+        boolean autoSave = JavascriptUtils.isSaveFormSubmitLinkIE(facesContext
+                .getExternalContext());
+
+        if (autoScroll || autoSave)
+        {
+            script.prettyLine();
+            script.increaseIndent();
+            script.append("(!window.myfaces) ? window.myfaces = {} : null;");
+            script.append("(!myfaces.core) ? myfaces.core = {} : null;");
+            script.append("(!myfaces.core.config) ? myfaces.core.config = {} : null;");
+        }
+
+        if (autoScroll)
+        {
+            script.append("myfaces.core.config.autoScroll = true;");
+        }
+        if (autoSave)
+        {
+            script.append("myfaces.core.config.ieAutoSave = true;");
+        }
+        if (autoScroll || autoSave)
+        {
+            writer.startElement(HTML.SCRIPT_ELEM, null);
+            writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
+            writer.writeText(script.toString(), null);
+            writer.endElement(HTML.SCRIPT_ELEM);
+        }
+    }
+    /**
+     * @param facesContext
+     * @param context
+     * @param autoScroll
+     */
+    private static void prepareScript(FacesContext facesContext,
+            ScriptContext context, boolean autoScroll)
+    {
+
+        final char separatorChar = UINamingContainer
+                .getSeparatorChar(facesContext);
+        context.prettyLine();
+
+        //render a function to create a hidden input, if it doesn't exist
+        context.append("function ");
+        context.append(SET_HIDDEN_INPUT_FN_NAME).append(
+                "(formname, name, value)");
+        context.append("{");
+        context.append("var form = document.forms[formname];");
+        context.prettyLine();
+        context.append("if (typeof form == 'undefined')");
+        context.append("{");
+        context.append("form = document.getElementById(formname);");
+        context.append("}");
+        context.prettyLine();
+        context.append("if(typeof form.elements[name]!='undefined' && "+
+                "(form.elements[name].nodeName=='INPUT' || form.elements[name].nodeName=='input'))");
+        context.append("{");
+        context.append("form.elements[name].value=value;");
+        context.append("}");
+        context.append("else");
+        context.append("{");
+        context.append("var newInput = document.createElement('input');");
+        context.prettyLine();
+        context.append("newInput.setAttribute('type','hidden');");
+        context.prettyLine();
+        context.append("newInput.setAttribute('id',name);"); // IE hack; See MYFACES-1805
+        context.prettyLine();
+        context.append("newInput.setAttribute('name',name);");
+        context.prettyLine();
+        context.append("newInput.setAttribute('value',value);");
+        context.prettyLine();
+        context.append("form.appendChild(newInput);");
+        context.append("}");
+
+        context.append("}");
+
+        context.prettyLine();
+
+        context.prettyLine();
+
+        //render a function to clear a hidden input, if it exists        
+        context.append("function ");
+        context.append(CLEAR_HIDDEN_INPUT_FN_NAME).append(
+                "(formname, name, value)");
+        context.append("{");
+        context.append("var form = document.forms[formname];");
+        context.prettyLine();
+        context.append("if (typeof form == 'undefined')");
+        context.append("{");
+        context.append("form = document.getElementById(formname);");
+        context.append("}");
+        context.prettyLine();
+        context.append("var hInput = form.elements[name];");
+        context.prettyLine();
+        context.append("if(typeof hInput !='undefined')");
+        context.append("{");
+        //context.append("form.elements[name].value=null;");
+        context.append("form.removeChild(hInput);");
+        context.append("}");
+
+        context.append("}");
+
+        context.prettyLine();
+
+        context.append("function ");
+        context.append(HtmlRendererUtils.SUBMIT_FORM_FN_NAME).append(
+                "(formName, linkId, target, params)");
+        context.append("{");
+
+        //call the script to clear the form (clearFormHiddenParams_<formName>) method - 
+        //optionally, only necessary for IE5.5.
+        //todo: if IE5.5. is ever desupported, we can get rid of this and instead rely on 
+        //the last part of this script to
+        //clear the parameters
+        appendClearHiddenCommandFormParamsFunctionCall(
+                context, null);
+
+        if (autoScroll)
+        {
+            appendAutoScrollAssignment(facesContext, context, null);
+        }
+
+        context.prettyLine();
+
+        context.append("var form = document.forms[formName];");
+        context.prettyLine();
+        context.append("if (typeof form == 'undefined')");
+        context.append("{");
+        context.append("form = document.getElementById(formName);");
+        context.append("}");
+        context.prettyLine();
+
+        if (JavascriptUtils.isSaveFormSubmitLinkIE(FacesContext
+                .getCurrentInstance().getExternalContext()))
+        {
+            context.append("var agentString = navigator.userAgent.toLowerCase();");
+            context.prettyLine();
+            //context.append("var isIE = false;");
+            context.prettyLine();
+            context.append("if (agentString.indexOf('msie') != -1)");
+
+            context.append("{");
+            context.append("if (!(agentString.indexOf('ppc') != -1 &&"+
+                    " agentString.indexOf('windows ce') != -1 && version >= 4.0))");
+            context.append("{");
+            context.append("window.external.AutoCompleteSaveForm(form);");
+            //        context.append("isIE = false;");
+            context.append("}");
+            //        context.append("else");
+            //        context.append("{");
+            //        context.append("isIE = true;");
+            //        context.prettyLine();
+            //        context.append("}");
+
+            context.append("}");
+
+            context.prettyLine();
+        }
+        //set the target (and save it). This should be done always, 
+        //and the default value of target is always valid.
+        context.append("var oldTarget = form.target;");
+        context.prettyLine();
+        context.append("if(target != null)");
+        context.append("{");
+        context.prettyLine();
+        context.append("form.target=target;");
+        context.append("}");
+
+        //set the submit parameters
+
+        context.append("if((typeof params!='undefined') && params != null)");
+        context.append("{");
+        context.prettyLine();
+        context.append("for(var i=0, param; (param = params[i]); i++)");
+        context.append("{");
+        context.append(SET_HIDDEN_INPUT_FN_NAME).append(
+                "(formName,param[0], param[1]);");
+        context.append("}");
+        context.append("}");
+
+        context.prettyLine();
+
+        context.append(SET_HIDDEN_INPUT_FN_NAME);
+        context.append("(formName,formName +'" + separatorChar + "'+'"
+                + HtmlRendererUtils.HIDDEN_COMMANDLINK_FIELD_NAME
+                + "',linkId);");
+
+        context.prettyLine();
+        context.prettyLine();
+
+        //do the actual submit calls
+
+        context.append("if(form.onsubmit)");
+        context.append("{");
+        context.append("var result=form.onsubmit();");
+        context.prettyLine();
+        context.append("if((typeof result=='undefined')||result)");
+        context.append("{");
+        context.append("try");
+        context.append("{");
+        context.append("form.submit();");
+        context.append("}");
+        context.append("catch(e){}");
+        context.append("}");
+        context.append("}");
+        context.append("else ");
+        context.append("{");
+        context.append("try");
+        context.append("{");
+        context.append("form.submit();");
+        context.append("}");
+        context.append("catch(e){}");
+        context.append("}");
+
+        //reset the target
+        context.prettyLine();
+        //Restore the old target, no more questions asked
+        context.append("form.target=oldTarget;");
+        context.prettyLine();
+
+        //clear the individual parameters - to make sure that even if the clear-function isn't called,
+        // the back button/resubmit functionality will still work in all browsers except IE 5.5.
+
+        context.append("if((typeof params!='undefined') && params != null)");
+        context.append("{");
+        context.prettyLine();
+        context.append("for(var i=0, param; (param = params[i]); i++)");
+        context.append("{");
+        context.append(CLEAR_HIDDEN_INPUT_FN_NAME).append(
+                "(formName,param[0], param[1]);");
+        context.append("}");
+        context.append("}");
+
+        context.prettyLine();
+
+        context.append(CLEAR_HIDDEN_INPUT_FN_NAME);
+        context.append("(formName,formName +'" + separatorChar + "'+'"
+                + HtmlRendererUtils.HIDDEN_COMMANDLINK_FIELD_NAME
+                + "',linkId);");
+
+        //return false, so that browser does not handle the click
+        context.append("return false;");
+        context.append("}");
+
+        context.prettyLineDecreaseIndent();
+    }
+    
+    public static void appendAutoScrollAssignment(StringBuffer onClickValue,
+            String formName)
+    {
+        appendAutoScrollAssignment(FacesContext.getCurrentInstance(),
+                new ScriptContext(onClickValue, false), formName);
+    }
+
+    /**
+     * Adds the hidden form input value assignment that is necessary for the autoscroll
+     * feature to an html link or button onclick attribute.
+     */
+    public static void appendAutoScrollAssignment(FacesContext context,
+            StringBuffer onClickValue, String formName)
+    {
+        appendAutoScrollAssignment(context, new ScriptContext(onClickValue,
+                false), formName);
+    }
+    
+    private static void appendAutoScrollAssignment(FacesContext context,
+            ScriptContext scriptContext, String formName)
+    {
+        String formNameStr = formName == null ? "formName" : (new StringBuffer(
+                "'").append(formName).append("'").toString());
+        String paramName = new StringBuffer().append("'")
+                .append(AUTO_SCROLL_PARAM).append("'").toString();
+        String value = new StringBuffer().append(AUTO_SCROLL_FUNCTION)
+                .append("()").toString();
+
+        scriptContext.prettyLine();
+        scriptContext.append("if(typeof window." + AUTO_SCROLL_FUNCTION
+                + "!='undefined')");
+        scriptContext.append("{");
+        if (MyfacesConfig.getCurrentInstance(context.getExternalContext())
+                .isRenderFormSubmitScriptInline())
+        {
+            scriptContext.append(SET_HIDDEN_INPUT_FN_NAME);
+        }
+        else
+        {
+            scriptContext.append(SET_HIDDEN_INPUT_FN_NAME_JSF2);
+        }
+        scriptContext.append("(").append(formNameStr).append(",")
+                .append(paramName).append(",").append(value).append(");");
+        scriptContext.append("}");
+
+    }
+    
+    public static String getAutoScrollFunction(FacesContext facesContext)
+    {
+        ScriptContext script = new ScriptContext(MyfacesConfig
+                .getCurrentInstance(facesContext.getExternalContext())
+                .isPrettyHtml());
+
+        script.prettyLineIncreaseIndent();
+
+        script.append("function ");
+        script.append(AUTO_SCROLL_FUNCTION);
+        script.append("()");
+        script.append("{");
+        script.append("var x = 0; var y = 0;");
+        script.append("if (self.pageXOffset || self.pageYOffset)");
+        script.append("{");
+        script.append("x = self.pageXOffset;");
+        script.prettyLine();
+        script.append("y = self.pageYOffset;");
+        script.append("}");
+        script.append(" else if ((document.documentElement && document.documentElement.scrollLeft)||"+
+                "(document.documentElement && document.documentElement.scrollTop))");
+        script.append("{");
+        script.append("x = document.documentElement.scrollLeft;");
+        script.prettyLine();
+        script.append("y = document.documentElement.scrollTop;");
+        script.append("}");
+        script.append(" else if (document.body) ");
+        script.append("{");
+        script.append("x = document.body.scrollLeft;");
+        script.prettyLine();
+        script.append("y = document.body.scrollTop;");
+        script.append("}");
+        script.append("return x + \",\" + y;");
+        script.append("}");
+
+        ExternalContext externalContext = facesContext.getExternalContext();
+        String oldViewId = JavascriptUtils.getOldViewId(externalContext);
+        if (oldViewId != null
+                && oldViewId.equals(facesContext.getViewRoot().getViewId()))
+        {
+            //ok, we stayed on the same page, so let's scroll it to the former place
+            String scrolling = (String) externalContext
+                    .getRequestParameterMap().get(AUTO_SCROLL_PARAM);
+            if (scrolling != null && scrolling.length() > 0)
+            {
+                int x = 0;
+                int y = 0;
+                int comma = scrolling.indexOf(',');
+                if (comma == -1)
+                {
+                    log.warning("Illegal autoscroll request parameter: "
+                            + scrolling);
+                }
+                else
+                {
+                    try
+                    {
+                        //we convert to int against XSS vulnerability
+                        x = Integer.parseInt(scrolling.substring(0, comma));
+                    }
+                    catch (NumberFormatException e)
+                    {
+                        log.warning("Error getting x offset for autoscroll feature. Bad param value: "
+                                + scrolling);
+                        x = 0; //ignore false numbers
+                    }
+
+                    try
+                    {
+                        //we convert to int against XSS vulnerability
+                        y = Integer.parseInt(scrolling.substring(comma + 1));
+                    }
+                    catch (NumberFormatException e)
+                    {
+                        log.warning("Error getting y offset for autoscroll feature. Bad param value: "
+                                + scrolling);
+                        y = 0; //ignore false numbers
+                    }
+                }
+                script.append("window.scrollTo(").append(x).append(",")
+                        .append(y).append(");\n");
+            }
+        }
+
+        return script.toString();
+    }
+    
+    /**
+     * Renders the hidden form input that is necessary for the autoscroll feature.
+     */
+    public static void renderAutoScrollHiddenInput(FacesContext facesContext,
+            ResponseWriter writer) throws IOException
+    {
+        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+        writer.startElement(HTML.INPUT_ELEM, null);
+        writer.writeAttribute(HTML.TYPE_ATTR, "hidden", null);
+        writer.writeAttribute(HTML.NAME_ATTR, AUTO_SCROLL_PARAM, null);
+        writer.endElement(HTML.INPUT_ELEM);
+        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+    }
+
+    /**
+     * Renders the autoscroll javascript function.
+     */
+    public static void renderAutoScrollFunction(FacesContext facesContext,
+            ResponseWriter writer) throws IOException
+    {
+        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+        writer.startElement(HTML.SCRIPT_ELEM, null);
+        writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR,
+                HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
+        writer.writeText(getAutoScrollFunction(facesContext), null);
+        writer.endElement(HTML.SCRIPT_ELEM);
+        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+    }
+    
+    public static void appendClearHiddenCommandFormParamsFunctionCall(
+            StringBuffer buf, String formName)
+    {
+        appendClearHiddenCommandFormParamsFunctionCall(new ScriptContext(buf,
+                false), formName);
+    }
+    
+    private static void appendClearHiddenCommandFormParamsFunctionCall(
+            ScriptContext context, String formName)
+    {
+        String functionName = HtmlRendererUtils
+                .getClearHiddenCommandFormParamsFunctionName(formName);
+        if (formName == null)
+        {
+            context.prettyLine();
+            context.append("var clearFn = ");
+            context.append(functionName);
+            context.append(";");
+            context.prettyLine();
+            context.append("if(typeof window[clearFn] =='function')");
+            context.append("{");
+            context.append("window[clearFn](formName);");
+            context.append("}");
+        }
+        else
+        {
+            context.prettyLine();
+            context.append("if(typeof window.");
+            context.append(functionName);
+            context.append("=='function')");
+            context.append("{");
+            context.append(functionName).append("('").append(formName)
+                    .append("');");
+            context.append("}");
+        }
+    }
+    
+    /**
+     * Prefixes the given String with "clear_" and removes special characters
+     *
+     * @param formName
+     * @return String
+     */
+    public static String getClearHiddenCommandFormParamsFunctionName(
+            String formName)
+    {
+        final char separatorChar = UINamingContainer
+                .getSeparatorChar(FacesContext.getCurrentInstance());
+        if (formName == null)
+        {
+            return "'" + HtmlRendererUtils.CLEAR_HIDDEN_FIELD_FN_NAME
+                    + "_'+formName.replace(/-/g, '\\$" + separatorChar
+                    + "').replace(/" + separatorChar + "/g,'_')";
+        }
+
+        return JavascriptUtils
+                .getValidJavascriptNameAsInRI(HtmlRendererUtils.CLEAR_HIDDEN_FIELD_FN_NAME + "_"
+                        + formName.replace(separatorChar, '_'));
+    }
+
+    public static String getClearHiddenCommandFormParamsFunctionNameMyfacesLegacy(
+            String formName)
+    {
+        return "clear_"
+                + JavascriptUtils.getValidJavascriptName(formName, false);
+    }
+    
+    /**
+     * Render the javascript function that is called on a click on a commandLink
+     * to clear the hidden inputs. This is necessary because on a browser back,
+     * each hidden input still has it's old value (browser cache!) and therefore
+     * a new submit would cause the according action once more!
+     *
+     * @param writer
+     * @param formName
+     * @param dummyFormParams
+     * @param formTarget
+     * @throws IOException
+     */
+    public static void renderClearHiddenCommandFormParamsFunction(
+            ResponseWriter writer, String formName, Set dummyFormParams,
+            String formTarget) throws IOException
+    {
+        //render the clear hidden inputs javascript function
+        String functionName = getClearHiddenCommandFormParamsFunctionName(formName);
+        writer.startElement(HTML.SCRIPT_ELEM, null);
+        writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
+
+        // Using writeComment instead of write with <!-- tag
+        StringBuffer script = new StringBuffer();
+        script.append("function ");
+        script.append(functionName);
+        script.append("() {");
+        if (dummyFormParams != null)
+        {
+            script.append("\n  var f = document.forms['");
+            script.append(formName);
+            script.append("'];");
+            int i = 0;
+            for (Iterator it = dummyFormParams.iterator(); it.hasNext();)
+            {
+                String elemVarName = "elem" + i;
+                script.append("\n  var ").append(elemVarName).append(" = ");
+                script.append("f.elements['").append((String) it.next())
+                        .append("'];");
+                script.append("\n  if(typeof ").append(elemVarName)
+                        .append(" !='undefined' && ");
+                script.append(elemVarName).append(".nodeName=='INPUT'){");
+                script.append("\n   if (").append(elemVarName)
+                        .append(".value != '') {");
+                script.append("\n    " + elemVarName + ".value='';");
+                script.append("\n   }");
+                script.append("\n  }");
+                i++;
+            }
+        }
+        // clear form target
+        script.append("\n  f.target=");
+        if (formTarget == null || formTarget.length() == 0)
+        {
+            //Normally one would think that setting target to null has the
+            //desired effect, but once again IE is different...
+            //Setting target to null causes IE to open a new window!
+            script.append("'';");
+        }
+        else
+        {
+            script.append("'");
+            script.append(formTarget);
+            script.append("';");
+        }
+        script.append("\n}");
+
+        //Just to be sure we call this clear method on each load.
+        //Otherwise in the case, that someone submits a form by pressing Enter
+        //within a text input, the hidden inputs won't be cleared!
+        script.append("\n");
+        script.append(functionName);
+        script.append("();");
+
+        writer.writeText(script.toString(), null);
+        writer.endElement(HTML.SCRIPT_ELEM);
+    }
+    
+    /**
+     * This function correctly escapes the given JavaScript code
+     * for the use in the jsf.util.chain() JavaScript function.
+     * It also handles double-escaping correclty.
+     *
+     * @param javaScript
+     * @return
+     */
+    public static String escapeJavaScriptForChain(String javaScript)
+    {
+        // first replace \' with \\'
+        //String escaped = StringUtils.replace(javaScript, "\\'", "\\\\'");
+
+        // then replace ' with \'
+        // (this will replace every \' in the original to \\\')
+        //escaped = StringUtils.replace(escaped, '\'', "\\'");
+
+        //return escaped;
+
+        StringBuffer out = null;
+        for (int pos = 0; pos < javaScript.length(); pos++)
+        {
+            char c = javaScript.charAt(pos);
+
+            if (c == '\\' || c == '\'')
+            {
+                if (out == null)
+                {
+                    out = new StringBuffer(javaScript.length() + 8);
+                    if (pos > 0)
+                    {
+                        out.append(javaScript, 0, pos);
+                    }
+                }
+                out.append('\\');
+            }
+            if (out != null)
+            {
+                out.append(c);
+            }
+        }
+
+        if (out == null)
+        {
+            return javaScript;
+        }
+        else
+        {
+            return out.toString();
+        }
+    }
+    
+    public static void renderViewStateJavascript(FacesContext facesContext,
+            String hiddenId, String serializedState) throws IOException
+    {
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        writer.startElement(HTML.SCRIPT_ELEM, null);
+        writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
+
+        final ExternalContext externalContext = facesContext
+                .getExternalContext();
+        final MyfacesConfig currentInstance = MyfacesConfig
+                .getCurrentInstance(externalContext);
+
+        ScriptContext context = new ScriptContext(
+                currentInstance.isPrettyHtml());
+        context.prettyLine();
+        context.increaseIndent();
+
+        context.append("function setViewState() {\n");
+        context.append("\tvar state = '");
+        context.append(serializedState);
+        context.append("';\n");
+        context.append("\tfor (var i = 0; i < document.forms.length; i++) {\n");
+        context.append("\t\tdocument.forms[i]['" + hiddenId
+                + "'].value = state;\n");
+        context.append("\t}\n");
+        context.append("}\n");
+        context.append("setViewState();\n");
+
+        context.decreaseIndent();
+
+        writer.writeText(context.toString(), null);
+
+        writer.endElement(HTML.SCRIPT_ELEM);
+    }
+}

Propchange: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlJavaScriptUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java?rev=1202947&r1=1202946&r2=1202947&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java Thu Nov 17 00:16:48 2011
@@ -64,7 +64,8 @@ public abstract class HtmlLinkRendererBa
 
     //private static final Log log = LogFactory.getLog(HtmlLinkRenderer.class);
     
-    public static final String END_LINK_OUTCOME_AS_SPAN = "org.apache.myfaces.shared.HtmlLinkRendererBase.END_LINK_OUTCOME_AS_SPAN";
+    public static final String END_LINK_OUTCOME_AS_SPAN = 
+        "org.apache.myfaces.shared.HtmlLinkRendererBase.END_LINK_OUTCOME_AS_SPAN";
 
     public boolean getRendersChildren()
     {
@@ -86,7 +87,8 @@ public abstract class HtmlLinkRendererBa
                 String reqValue = (String) facesContext.getExternalContext().getRequestParameterMap().get(
                         HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo));
                 if (reqValue != null && reqValue.equals(clientId)
-                    || HtmlRendererUtils.isPartialOrBehaviorSubmit(facesContext, clientId)) {
+                    || HtmlRendererUtils.isPartialOrBehaviorSubmit(facesContext, clientId))
+                {
                     component.queueEvent(new ActionEvent(component));
 
                     RendererUtils.initPartialValidationAndModelUpdate(component, facesContext);
@@ -230,7 +232,8 @@ public abstract class HtmlLinkRendererBa
         if (HtmlRendererUtils.isDisabled(component) || formInfo == null)
         {
             writer.startElement(HTML.SPAN_ELEM, component);
-            if (component instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
+            if (component instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(
+                    facesContext.getExternalContext()))
             {
                 behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
                 if (!behaviors.isEmpty())
@@ -242,7 +245,8 @@ public abstract class HtmlLinkRendererBa
                     HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
                 }
                 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, component, behaviors);
-                HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(facesContext, writer, component, behaviors);
+                HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
+                        facesContext, writer, component, behaviors);
                 if (isCommonPropertiesOptimizationEnabled(facesContext))
                 {
                     CommonPropertyUtils.renderAnchorPassthroughPropertiesWithoutEvents(writer, 
@@ -250,7 +254,8 @@ public abstract class HtmlLinkRendererBa
                 }
                 else
                 {
-                    HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
+                    HtmlRendererUtils.renderHTMLAttributes(writer, component, 
+                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
                 }
             }
             else
@@ -275,7 +280,8 @@ public abstract class HtmlLinkRendererBa
                 if (component instanceof ClientBehaviorHolder)
                 {
                     behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
-                    renderBehaviorizedJavaScriptAnchorStart(facesContext, writer, component, clientId, behaviors, formInfo);
+                    renderBehaviorizedJavaScriptAnchorStart(
+                            facesContext, writer, component, clientId, behaviors, formInfo);
                     if (!behaviors.isEmpty())
                     {
                         HtmlRendererUtils.writeIdAndName(writer, component, facesContext);
@@ -284,8 +290,10 @@ public abstract class HtmlLinkRendererBa
                     {
                         HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
                     }
-                    HtmlRendererUtils.renderBehaviorizedEventHandlersWithoutOnclick(facesContext, writer, component, behaviors);
-                    HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(facesContext, writer, component, behaviors);
+                    HtmlRendererUtils.renderBehaviorizedEventHandlersWithoutOnclick(
+                            facesContext, writer, component, behaviors);
+                    HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
+                            facesContext, writer, component, behaviors);
                     if (isCommonPropertiesOptimizationEnabled(facesContext))
                     {
                         CommonPropertyUtils.renderAnchorPassthroughPropertiesWithoutStyleAndEvents(writer, 
@@ -293,7 +301,8 @@ public abstract class HtmlLinkRendererBa
                     }
                     else
                     {
-                        HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_STYLE_AND_EVENTS);
+                        HtmlRendererUtils.renderHTMLAttributes(writer, component, 
+                                HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_STYLE_AND_EVENTS);
                     }
                 }
                 else
@@ -307,7 +316,8 @@ public abstract class HtmlLinkRendererBa
                     }
                     else
                     {
-                        HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_ONCLICK_WITHOUT_STYLE);
+                        HtmlRendererUtils.renderHTMLAttributes(writer, component, 
+                                HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_ONCLICK_WITHOUT_STYLE);
                     }
                 }
             }
@@ -322,7 +332,8 @@ public abstract class HtmlLinkRendererBa
                 }
                 else
                 {
-                    HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_STYLE);
+                    HtmlRendererUtils.renderHTMLAttributes(writer, component, 
+                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_STYLE);
                 }
             }
 
@@ -377,14 +388,16 @@ public abstract class HtmlLinkRendererBa
             onClick.append("var oamSF = function(){");
         }
 
-        if (RendererUtils.isAdfOrTrinidadForm(formInfo.getForm())) {
+        if (RendererUtils.isAdfOrTrinidadForm(formInfo.getForm()))
+        {
             onClick.append("submitForm('");
             onClick.append(formInfo.getForm().getClientId(facesContext));
             onClick.append("',1,{source:'");
             onClick.append(component.getClientId(facesContext));
             onClick.append("'});return false;");
         }
-        else {
+        else
+        {
             HtmlRendererUtils.renderFormSubmitScript(facesContext);
 
             StringBuffer params = addChildParameters(facesContext, component, nestingForm);
@@ -406,7 +419,8 @@ public abstract class HtmlLinkRendererBa
                     append(clientId).append("'");
             }
 
-            if (params.length() > 2 || target != null) {
+            if (params.length() > 2 || target != null)
+            {
                 onClick.append(",").
                     append(target == null ? "null" : ("'" + target + "'")).append(",").
                     append(params);
@@ -415,7 +429,8 @@ public abstract class HtmlLinkRendererBa
 
             //Not necessary since we are using oamSetHiddenInput to create input hidden fields
             //render hidden field - todo: in here for backwards compatibility
-            if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isRenderHiddenFieldsForLinkParams())
+            if (MyfacesConfig.getCurrentInstance(
+                    facesContext.getExternalContext()).isRenderHiddenFieldsForLinkParams())
             {
                 String hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo);
                 addHiddenCommandParameter(facesContext, nestingForm, hiddenFieldName);
@@ -477,7 +492,8 @@ public abstract class HtmlLinkRendererBa
             }
             
             //render a javascript that chain the related code
-            Collection<ClientBehaviorContext.Parameter> paramList = HtmlRendererUtils.getClientBehaviorContextParameters(
+            Collection<ClientBehaviorContext.Parameter> paramList = 
+                HtmlRendererUtils.getClientBehaviorContextParameters(
                     HtmlRendererUtils.mapAttachedParamsToStringValues(facesContext, component));
             
             onclick = HtmlRendererUtils.buildBehaviorChain(facesContext, component,
@@ -493,9 +509,12 @@ public abstract class HtmlLinkRendererBa
     private boolean hasSubmittingBehavior(Map<String, List<ClientBehavior>> clientBehaviors, String eventName)
     {
         List<ClientBehavior> eventBehaviors = clientBehaviors.get(eventName);
-        if (eventBehaviors != null && !eventBehaviors.isEmpty()) {
-            for (ClientBehavior behavior : eventBehaviors) {
-                if (behavior.getHints().contains(ClientBehaviorHint.SUBMITTING)) {
+        if (eventBehaviors != null && !eventBehaviors.isEmpty())
+        {
+            for (ClientBehavior behavior : eventBehaviors)
+            {
+                if (behavior.getHints().contains(ClientBehaviorHint.SUBMITTING))
+                {
                     return true;
                 }
             }
@@ -511,21 +530,24 @@ public abstract class HtmlLinkRendererBa
 
         StringBuffer onClick = new StringBuffer();
 
-        if (RendererUtils.isAdfOrTrinidadForm(formInfo.getForm())) {
+        if (RendererUtils.isAdfOrTrinidadForm(formInfo.getForm()))
+        {
             onClick.append("submitForm('");
             onClick.append(formInfo.getForm().getClientId(facesContext));
             onClick.append("',1,{source:'");
             onClick.append(component.getClientId(facesContext));
             onClick.append("'});return false;");
         }
-        else {
+        else
+        {
             HtmlRendererUtils.renderFormSubmitScript(facesContext);
 
             StringBuffer params = addChildParameters(facesContext, component, nestingForm);
 
             String target = getTarget(component);
 
-            if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isRenderFormSubmitScriptInline())
+            if (MyfacesConfig.getCurrentInstance(
+                    facesContext.getExternalContext()).isRenderFormSubmitScriptInline())
             {
                 onClick.append("return ").
                     append(HtmlRendererUtils.SUBMIT_FORM_FN_NAME).append("('").
@@ -540,7 +562,8 @@ public abstract class HtmlLinkRendererBa
                     append(clientId).append("'");
             }
 
-            if (params.length() > 2 || target != null) {
+            if (params.length() > 2 || target != null)
+            {
                 onClick.append(",").
                     append(target == null ? "null" : ("'" + target + "'")).append(",").
                     append(params);
@@ -556,19 +579,23 @@ public abstract class HtmlLinkRendererBa
         return onClick.toString();
     }
 
-    private String getTarget(UIComponent component) {
+    private String getTarget(UIComponent component)
+    {
         // for performance reason: double check for the target attribute
         String target;
-        if (component instanceof HtmlCommandLink) {
+        if (component instanceof HtmlCommandLink)
+        {
             target = ((HtmlCommandLink) component).getTarget();
         }
-        else {
+        else
+        {
             target = (String) component.getAttributes().get(HTML.TARGET_ATTR);
         }
         return target;
     }
 
-    private StringBuffer addChildParameters(FacesContext context, UIComponent component, UIComponent nestingForm) {
+    private StringBuffer addChildParameters(FacesContext context, UIComponent component, UIComponent nestingForm)
+    {
         //add child parameters
         StringBuffer params = new StringBuffer();
         params.append("[");
@@ -650,7 +677,8 @@ public abstract class HtmlLinkRendererBa
         return _ComponentUtils.findNestingForm(uiComponent, facesContext);
     }
 
-    protected void addHiddenCommandParameter(FacesContext facesContext, UIComponent nestingForm, String hiddenFieldName)
+    protected void addHiddenCommandParameter(
+            FacesContext facesContext, UIComponent nestingForm, String hiddenFieldName)
     {
         if (nestingForm != null)
         {
@@ -683,9 +711,12 @@ public abstract class HtmlLinkRendererBa
         }
         else
         {
-            if (strictXhtmlLinks) {
+            if (strictXhtmlLinks)
+            {
                 hrefBuf.append("&amp;");
-            } else {
+            }
+            else
+            {
                 hrefBuf.append('&');
             }
         }
@@ -738,7 +769,8 @@ public abstract class HtmlLinkRendererBa
         if (HtmlRendererUtils.isDisabled(output))
         {
             writer.startElement(HTML.SPAN_ELEM, output);
-            if (output instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
+            if (output instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(
+                    facesContext.getExternalContext()))
             {
                 behaviors = ((ClientBehaviorHolder) output).getClientBehaviors();
                 if (!behaviors.isEmpty())
@@ -750,7 +782,8 @@ public abstract class HtmlLinkRendererBa
                     HtmlRendererUtils.writeIdIfNecessary(writer, output, facesContext);
                 }
                 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, output, behaviors);
-                HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(facesContext, writer, output, behaviors);
+                HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
+                        facesContext, writer, output, behaviors);
                 if (isCommonPropertiesOptimizationEnabled(facesContext))
                 {
                     CommonPropertyUtils.renderAnchorPassthroughPropertiesWithoutEvents(writer, 
@@ -758,7 +791,8 @@ public abstract class HtmlLinkRendererBa
                 }
                 else
                 {
-                    HtmlRendererUtils.renderHTMLAttributes(writer, output, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
+                    HtmlRendererUtils.renderHTMLAttributes(writer, output, 
+                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
                 }
             }
             else
@@ -821,7 +855,8 @@ public abstract class HtmlLinkRendererBa
             //write anchor
             writer.startElement(HTML.ANCHOR_ELEM, output);
             writer.writeURIAttribute(HTML.HREF_ATTR, href, null);
-            if (output instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
+            if (output instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(
+                    facesContext.getExternalContext()))
             {
                 behaviors = ((ClientBehaviorHolder) output).getClientBehaviors();
                 if (!behaviors.isEmpty())
@@ -833,7 +868,8 @@ public abstract class HtmlLinkRendererBa
                     HtmlRendererUtils.writeIdAndNameIfNecessary(writer, output, facesContext);
                 }
                 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, output, behaviors);
-                HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(facesContext, writer, output, behaviors);
+                HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
+                        facesContext, writer, output, behaviors);
                 if (isCommonPropertiesOptimizationEnabled(facesContext))
                 {
                     CommonPropertyUtils.renderAnchorPassthroughPropertiesWithoutEvents(writer, 
@@ -841,7 +877,8 @@ public abstract class HtmlLinkRendererBa
                 }
                 else
                 {
-                    HtmlRendererUtils.renderHTMLAttributes(writer, output, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
+                    HtmlRendererUtils.renderHTMLAttributes(writer, output, 
+                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
                 }
             }
             else
@@ -874,7 +911,8 @@ public abstract class HtmlLinkRendererBa
         {
             output.getAttributes().put(END_LINK_OUTCOME_AS_SPAN, Boolean.TRUE);
             writer.startElement(HTML.SPAN_ELEM, output);
-            if (output instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
+            if (output instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(
+                    facesContext.getExternalContext()))
             {
                 behaviors = ((ClientBehaviorHolder) output).getClientBehaviors();
                 if (!behaviors.isEmpty())
@@ -886,7 +924,8 @@ public abstract class HtmlLinkRendererBa
                     HtmlRendererUtils.writeIdIfNecessary(writer, output, facesContext);
                 }
                 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, output, behaviors);
-                HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(facesContext, writer, output, behaviors);
+                HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
+                        facesContext, writer, output, behaviors);
                 if (isCommonPropertiesOptimizationEnabled(facesContext))
                 {
                     CommonPropertyUtils.renderAnchorPassthroughPropertiesWithoutEvents(writer, 
@@ -894,7 +933,8 @@ public abstract class HtmlLinkRendererBa
                 }
                 else
                 {
-                    HtmlRendererUtils.renderHTMLAttributes(writer, output, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
+                    HtmlRendererUtils.renderHTMLAttributes(writer, output, 
+                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
                 }
             }
             else
@@ -923,7 +963,8 @@ public abstract class HtmlLinkRendererBa
             //write anchor
             writer.startElement(HTML.ANCHOR_ELEM, output);
             writer.writeURIAttribute(HTML.HREF_ATTR, targetHref, null);
-            if (output instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
+            if (output instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(
+                    facesContext.getExternalContext()))
             {
                 behaviors = ((ClientBehaviorHolder) output).getClientBehaviors();
                 if (!behaviors.isEmpty())
@@ -935,7 +976,8 @@ public abstract class HtmlLinkRendererBa
                     HtmlRendererUtils.writeIdAndNameIfNecessary(writer, output, facesContext);
                 }
                 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, output, behaviors);
-                HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(facesContext, writer, output, behaviors);
+                HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
+                        facesContext, writer, output, behaviors);
                 if (isCommonPropertiesOptimizationEnabled(facesContext))
                 {
                     CommonPropertyUtils.renderAnchorPassthroughPropertiesWithoutEvents(writer, 
@@ -943,7 +985,8 @@ public abstract class HtmlLinkRendererBa
                 }
                 else
                 {
-                    HtmlRendererUtils.renderHTMLAttributes(writer, output, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
+                    HtmlRendererUtils.renderHTMLAttributes(writer, output, 
+                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
                 }
             }
             else
@@ -956,7 +999,8 @@ public abstract class HtmlLinkRendererBa
                 }
                 else
                 {
-                    HtmlRendererUtils.renderHTMLAttributes(writer, output, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES);
+                    HtmlRendererUtils.renderHTMLAttributes(writer, output, 
+                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES);
                 }
             }
 
@@ -978,7 +1022,8 @@ public abstract class HtmlLinkRendererBa
         onClick.append(jsForm);
         onClick.append(".elements['").append(name).append("']");
         //UIParameter is no ValueHolder, so no conversion possible
-        String strParamValue = value != null ? org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder.encode(value.toString(), false, false) : "";
+        String strParamValue = value != null ? org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder.encode(
+                value.toString(), false, false) : "";
         onClick.append(".value='").append(strParamValue).append("';");
 
         addHiddenCommandParameter(FacesContext.getCurrentInstance(), nestingForm, name);
@@ -989,17 +1034,25 @@ public abstract class HtmlLinkRendererBa
                                            StringBuffer hrefBuf,
                                            boolean firstParameter,
                                            String charEncoding,
-                                           boolean strictXhtmlLinks) throws UnsupportedEncodingException {
-        if (name == null) {
+                                           boolean strictXhtmlLinks) throws UnsupportedEncodingException
+    {
+        if (name == null)
+        {
             throw new IllegalArgumentException("Unnamed parameter value not allowed within command link.");
         }
 
-        if (firstParameter) {
+        if (firstParameter)
+        {
             hrefBuf.append('?');
-        } else {
-            if (strictXhtmlLinks) {
+        }
+        else
+        {
+            if (strictXhtmlLinks)
+            {
                 hrefBuf.append("&amp;");
-            } else {
+            }
+            else
+            {
                 hrefBuf.append('&');
             }
         }
@@ -1018,7 +1071,8 @@ public abstract class HtmlLinkRendererBa
     {
         ResponseWriter writer = facesContext.getResponseWriter();
         
-        if (HtmlRendererUtils.isDisabled(component) || component.getAttributes().remove(END_LINK_OUTCOME_AS_SPAN) != null)
+        if (HtmlRendererUtils.isDisabled(component) || component.getAttributes().remove(
+                END_LINK_OUTCOME_AS_SPAN) != null)
         {
             writer.endElement(HTML.SPAN_ELEM);
         }

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlListboxRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlListboxRendererBase.java?rev=1202947&r1=1202946&r2=1202947&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlListboxRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlListboxRendererBase.java Thu Nov 17 00:16:48 2011
@@ -100,7 +100,8 @@ public class HtmlListboxRendererBase
         }
         else
         {
-            return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(uiComponent, org.apache.myfaces.shared.renderkit.html.HTML.DISABLED_ATTR, false);
+            return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(uiComponent, 
+                    org.apache.myfaces.shared.renderkit.html.HTML.DISABLED_ATTR, false);
         }
     }
 
@@ -128,7 +129,8 @@ public class HtmlListboxRendererBase
         }
     }
 
-    public Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object submittedValue) throws ConverterException
+    public Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object submittedValue)
+         throws ConverterException
     {
         org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext, uiComponent, null);
 

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMenuRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMenuRendererBase.java?rev=1202947&r1=1202946&r2=1202947&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMenuRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMenuRendererBase.java Thu Nov 17 00:16:48 2011
@@ -18,9 +18,9 @@
  */
 package org.apache.myfaces.shared.renderkit.html;
 
-import org.apache.myfaces.shared.renderkit.RendererUtils;
-import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
-import org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
 
 import javax.faces.component.UIComponent;
 import javax.faces.component.UISelectMany;
@@ -32,9 +32,9 @@ import javax.faces.component.html.HtmlSe
 import javax.faces.context.FacesContext;
 import javax.faces.convert.Converter;
 import javax.faces.convert.ConverterException;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
+
+import org.apache.myfaces.shared.renderkit.RendererUtils;
+import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
 
 /**
  * X-CHECKED: tlddoc of h:selectManyListbox
@@ -97,7 +97,8 @@ public class HtmlMenuRendererBase
         }
         else
         {
-            return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(uiComponent, org.apache.myfaces.shared.renderkit.html.HTML.DISABLED_ATTR, false);
+            return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(uiComponent, 
+                    org.apache.myfaces.shared.renderkit.html.HTML.DISABLED_ATTR, false);
         }
     }
 
@@ -124,7 +125,8 @@ public class HtmlMenuRendererBase
         }
     }
 
-    public Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object submittedValue) throws ConverterException
+    public Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object submittedValue)
+         throws ConverterException
     {
         org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext, uiComponent, null);
 

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMessageRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMessageRendererBase.java?rev=1202947&r1=1202946&r2=1202947&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMessageRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMessageRendererBase.java Thu Nov 17 00:16:48 2011
@@ -66,7 +66,8 @@ public abstract class HtmlMessageRendere
         renderMessage(facesContext, message, false);
     }
 
-    protected void renderMessage(FacesContext facesContext, UIComponent message, boolean alwaysRenderSpan) throws IOException
+    protected void renderMessage(FacesContext facesContext, UIComponent message, 
+            boolean alwaysRenderSpan) throws IOException
     {
         renderMessage(facesContext, message, alwaysRenderSpan, false);
     }
@@ -76,7 +77,8 @@ public abstract class HtmlMessageRendere
      * @param message
      * @param alwaysRenderSpan if true will render a span even if there is no message
      */
-    protected void renderMessage(FacesContext facesContext, UIComponent message, boolean alwaysRenderSpan, boolean renderDivWhenNoMessagesAndIdSet) throws IOException
+    protected void renderMessage(FacesContext facesContext, UIComponent message, 
+            boolean alwaysRenderSpan, boolean renderDivWhenNoMessagesAndIdSet) throws IOException
     {
         String forAttr = getFor(message);
         if (forAttr == null)
@@ -88,7 +90,11 @@ public abstract class HtmlMessageRendere
         UIComponent forComponent = message.findComponent(forAttr);
         if (forComponent == null)
         {
-            log.severe("Could not render Message. Unable to find component '" + forAttr + "' (calling findComponent on component '" + message.getClientId(facesContext) + "'). If the provided id was correct, wrap the message and its component into an h:panelGroup or h:panelGrid.");
+            log.severe("Could not render Message. Unable to find component '" 
+                    + forAttr + "' (calling findComponent on component '" 
+                    + message.getClientId(facesContext) 
+                    + "'). If the provided id was correct, wrap the message and its " 
+                    + "component into an h:panelGroup or h:panelGrid.");
             return;
         }
 
@@ -107,7 +113,8 @@ public abstract class HtmlMessageRendere
                 HtmlRendererUtils.renderHTMLAttribute(writer, message, JSFAttr.STYLE_CLASS_ATTR, HTML.CLASS_ATTR);
                 writer.endElement(HTML.SPAN_ELEM);
             }
-            else if (renderDivWhenNoMessagesAndIdSet && message.getId() != null && !message.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
+            else if (renderDivWhenNoMessagesAndIdSet && message.getId() != null && 
+                    !message.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
             {
                 // show span anyways in case there's a client side update, ie: ajax
                 ResponseWriter writer = facesContext.getResponseWriter();
@@ -164,15 +171,38 @@ public abstract class HtmlMessageRendere
     }
 
     protected void renderSingleFacesMessage(FacesContext facesContext,
+            UIComponent message,
+            FacesMessage facesMessage,
+            String messageClientId,
+            boolean renderId,
+            boolean renderStyleAndStyleClass)
+    throws IOException
+    {
+        Map<String, List<ClientBehavior>> behaviors = null;
+        if (message instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(
+                facesContext.getExternalContext()))
+        {
+            behaviors = ((ClientBehaviorHolder) message).getClientBehaviors();
+        }
+        boolean wrapSpan = (message.getId() != null && !message.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) 
+            || (behaviors != null && !behaviors.isEmpty());
+
+        renderSingleFacesMessage(facesContext, message, facesMessage, messageClientId, 
+                renderId, renderStyleAndStyleClass, wrapSpan);
+    }
+    
+    protected void renderSingleFacesMessage(FacesContext facesContext,
                                             UIComponent message,
                                             FacesMessage facesMessage,
                                             String messageClientId,
                                             boolean renderId,
-                                            boolean renderStyleAndStyleClass)
+                                            boolean renderStyleAndStyleClass,
+                                            boolean wrapSpan)
             throws IOException
     {
         // determine style and style class
-        String[] styleAndClass = HtmlMessageRendererBase.getStyleAndStyleClass(message, facesMessage.getSeverity());
+        String[] styleAndClass = HtmlMessageRendererBase.getStyleAndStyleClass(
+                message, facesMessage.getSeverity());
         String style = styleAndClass[0];
         String styleClass = styleAndClass[1];
 
@@ -192,13 +222,13 @@ public abstract class HtmlMessageRendere
         boolean span = false;
 
         Map<String, List<ClientBehavior>> behaviors = null;
-        if (message instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
+        if (message instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed
+                (facesContext.getExternalContext()))
         {
             behaviors = ((ClientBehaviorHolder) message).getClientBehaviors();
         }
         
-        if ( (message.getId() != null && !message.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) 
-                || (behaviors != null && !behaviors.isEmpty()) )
+        if ( wrapSpan )
         {
             span = true;
 
@@ -213,28 +243,35 @@ public abstract class HtmlMessageRendere
             {
                 HtmlRendererUtils.writeIdIfNecessary(writer, message, facesContext);
             }
-            if (message instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))
+            if (message instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(
+                    facesContext.getExternalContext()))
             {
                 behaviors = ((ClientBehaviorHolder) message).getClientBehaviors();
                 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, message, behaviors);
-                HtmlRendererUtils.renderHTMLAttributes(writer, message, HTML.UNIVERSAL_ATTRIBUTES_WITHOUT_STYLE_AND_TITLE);
+                HtmlRendererUtils.renderHTMLAttributes(writer, message, 
+                        HTML.UNIVERSAL_ATTRIBUTES_WITHOUT_STYLE_AND_TITLE);
             }
             else
             {
-                HtmlRendererUtils.renderHTMLAttributes(writer, message, HTML.MESSAGE_PASSTHROUGH_ATTRIBUTES_WITHOUT_TITLE_STYLE_AND_STYLE_CLASS);
+                HtmlRendererUtils.renderHTMLAttributes(writer, message, 
+                        HTML.MESSAGE_PASSTHROUGH_ATTRIBUTES_WITHOUT_TITLE_STYLE_AND_STYLE_CLASS);
             }
         }
         else
         {
             span = HtmlRendererUtils.renderHTMLAttributesWithOptionalStartElement(
-                    writer, message, HTML.SPAN_ELEM, HTML.MESSAGE_PASSTHROUGH_ATTRIBUTES_WITHOUT_TITLE_STYLE_AND_STYLE_CLASS);
+                    writer, message, HTML.SPAN_ELEM, 
+                    HTML.MESSAGE_PASSTHROUGH_ATTRIBUTES_WITHOUT_TITLE_STYLE_AND_STYLE_CLASS);
         }
 
-        span |= HtmlRendererUtils.renderHTMLAttributeWithOptionalStartElement(writer, message, HTML.SPAN_ELEM, HTML.TITLE_ATTR, title, span);
+        span |= HtmlRendererUtils.renderHTMLAttributeWithOptionalStartElement(
+                writer, message, HTML.SPAN_ELEM, HTML.TITLE_ATTR, title, span);
         if (renderStyleAndStyleClass)
         {
-            span |= HtmlRendererUtils.renderHTMLAttributeWithOptionalStartElement(writer, message, HTML.SPAN_ELEM, HTML.STYLE_ATTR, style, span);
-            span |= HtmlRendererUtils.renderHTMLAttributeWithOptionalStartElement(writer, message, HTML.SPAN_ELEM, HTML.STYLE_CLASS_ATTR, styleClass, span);
+            span |= HtmlRendererUtils.renderHTMLAttributeWithOptionalStartElement(
+                    writer, message, HTML.SPAN_ELEM, HTML.STYLE_ATTR, style, span);
+            span |= HtmlRendererUtils.renderHTMLAttributeWithOptionalStartElement(
+                    writer, message, HTML.SPAN_ELEM, HTML.STYLE_CLASS_ATTR, styleClass, span);
         }
 
 
@@ -370,7 +407,8 @@ public abstract class HtmlMessageRendere
             return ((HtmlMessage) component).isTooltip();
         }
 
-        return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(component, org.apache.myfaces.shared.renderkit.JSFAttr.TOOLTIP_ATTR, false);
+        return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(component, 
+                org.apache.myfaces.shared.renderkit.JSFAttr.TOOLTIP_ATTR, false);
         
     }
 
@@ -381,7 +419,8 @@ public abstract class HtmlMessageRendere
             return ((UIMessage) component).isShowSummary();
         }
 
-        return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(component, org.apache.myfaces.shared.renderkit.JSFAttr.SHOW_SUMMARY_ATTR, false);
+        return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(component, 
+                org.apache.myfaces.shared.renderkit.JSFAttr.SHOW_SUMMARY_ATTR, false);
         
     }
 
@@ -392,7 +431,8 @@ public abstract class HtmlMessageRendere
             return ((UIMessage) component).isShowDetail();
         }
 
-        return RendererUtils.getBooleanAttribute(component, org.apache.myfaces.shared.renderkit.JSFAttr.SHOW_DETAIL_ATTR, false);
+        return RendererUtils.getBooleanAttribute(component, 
+                org.apache.myfaces.shared.renderkit.JSFAttr.SHOW_DETAIL_ATTR, false);
         
     }
     
@@ -403,7 +443,8 @@ public abstract class HtmlMessageRendere
             return ((UIMessage) component).isRedisplay();
         }
 
-        return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(component, org.apache.myfaces.shared.renderkit.JSFAttr.REDISPLAY_ATTR, true);
+        return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(component, 
+                org.apache.myfaces.shared.renderkit.JSFAttr.REDISPLAY_ATTR, true);
         
     }
 

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMessagesRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMessagesRendererBase.java?rev=1202947&r1=1202946&r2=1202947&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMessagesRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlMessagesRendererBase.java Thu Nov 17 00:16:48 2011
@@ -186,7 +186,7 @@ public abstract class HtmlMessagesRender
             renderSingleFacesMessage(facesContext,
                     messages,
                     facesMessage,
-                    messagesIterator.getClientId(),false,false);
+                    messagesIterator.getClientId(),false,false,false);
             writer.endElement(HTML.LI_ELEM);
         }
 
@@ -239,7 +239,7 @@ public abstract class HtmlMessagesRender
             renderSingleFacesMessage(facesContext,
                     messages,
                     facesMessage,
-                    messagesIterator.getClientId(),false,false);
+                    messagesIterator.getClientId(),false,false,false);
 
             writer.endElement(HTML.TD_ELEM);
             writer.endElement(HTML.TR_ELEM);

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlOutcomeTargetButtonRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlOutcomeTargetButtonRendererBase.java?rev=1202947&r1=1202946&r2=1202947&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlOutcomeTargetButtonRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlOutcomeTargetButtonRendererBase.java Thu Nov 17 00:16:48 2011
@@ -147,7 +147,8 @@ public class HtmlOutcomeTargetButtonRend
                 }
                 else
                 {
-                    CommonPropertyUtils.renderEventPropertiesWithoutOnclick(writer, commonPropertiesMarked, uiComponent);
+                    CommonPropertyUtils.renderEventPropertiesWithoutOnclick(
+                            writer, commonPropertiesMarked, uiComponent);
                     CommonPropertyUtils.renderFocusBlurEventProperties(writer, commonPropertiesMarked, uiComponent);
                 }
             }

Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRadioRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRadioRendererBase.java?rev=1202947&r1=1202946&r2=1202947&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRadioRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRadioRendererBase.java Thu Nov 17 00:16:48 2011
@@ -115,7 +115,7 @@ public class HtmlRadioRendererBase
         List selectItemList = org.apache.myfaces.shared.renderkit.RendererUtils.getSelectItemList(selectOne, facesContext);
         converter = HtmlRendererUtils.findUIOutputConverterFailSafe(facesContext, selectOne);
         
-        Object currentValue = org.apache.myfaces.shared.renderkit.RendererUtils.getStringValue(facesContext, selectOne);
+        Object currentValue = org.apache.myfaces.shared.renderkit.RendererUtils.getStringFromSubmittedValueOrLocalValueReturnNull(facesContext, selectOne);
 
         int itemNum = 0;
 
@@ -218,7 +218,11 @@ public class HtmlRadioRendererBase
         else 
         {
             String itemStrValue = org.apache.myfaces.shared.renderkit.RendererUtils.getConvertedStringValue(facesContext, selectOne, converter, selectItem.getValue());
-            boolean itemChecked = itemStrValue.equals(currentValue);
+            boolean itemChecked = (itemStrValue == null) ? 
+                    itemStrValue == currentValue : 
+                    "".equals(itemStrValue) ? 
+                            (currentValue == null || itemStrValue.equals(currentValue)) : 
+                            itemStrValue.equals(currentValue);
             
             // IF the hideNoSelectionOption attribute of the component is true
             // AND this selectItem is the "no selection option"
@@ -312,6 +316,10 @@ public class HtmlRadioRendererBase
         {
             writer.writeAttribute(HTML.VALUE_ATTR, value, null);
         }
+        else
+        {
+            writer.writeAttribute(HTML.VALUE_ATTR, "", null);
+        }
         
         Map<String, List<ClientBehavior>> behaviors = null;
         if (uiComponent instanceof ClientBehaviorHolder && JavascriptUtils.isJavascriptAllowed(facesContext.getExternalContext()))