package org.jboss.seam.ui.renderkit; import static org.jboss.seam.ui.util.HTML.SCRIPT_ELEM; import static org.jboss.seam.ui.util.HTML.SCRIPT_LANGUAGE_ATTR; import static org.jboss.seam.ui.util.HTML.SCRIPT_LANGUAGE_JAVASCRIPT; import static org.jboss.seam.ui.util.HTML.SCRIPT_TYPE_ATTR; import static org.jboss.seam.ui.util.HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT; import java.io.IOException; import javax.faces.component.UIComponent; import javax.faces.component.UIParameter; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import org.jboss.seam.log.LogProvider; import org.jboss.seam.ui.util.cdk.RendererBase; /** * @author Pete Muir * */ public abstract class CommandButtonParameterRendererBase extends RendererBase { protected abstract LogProvider getLog(); protected abstract String getParameterName(UIComponent component); @Override protected void doEncodeEnd(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException { UIComponent actionComponent = component.getParent(); UIComponent form = getUtils().getForm(actionComponent); UIParameter parameter = (UIParameter) component; if (getUtils().isCommandButton(actionComponent)) { String formId = form.getClientId(context); writer.startElement(SCRIPT_ELEM, component); writer.writeAttribute(SCRIPT_LANGUAGE_ATTR, SCRIPT_LANGUAGE_JAVASCRIPT, SCRIPT_LANGUAGE_ATTR); writer.writeAttribute(SCRIPT_TYPE_ATTR, SCRIPT_TYPE_TEXT_JAVASCRIPT, SCRIPT_TYPE_ATTR); if (actionComponent.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) { getLog().warn("Must set an id for the command buttons with s:conversationPropagation"); } String functionBody = "{" + "if (document.getElementById)" + "{" + "var form = document.getElementById('" + formId + "');" + "var input = document.createElement('input');" + "if (document.all)" + "{ " + // what follows should work with NN6 but doesn't in M14" "input.type = 'hidden';" + "input.name = '" + getParameterName(component) + "';" + "input.value = '" + parameter.getValue() + "';" + "}" + "else if (document.getElementById) " + "{" + // so here is theNN6 workaround "input.setAttribute('type', 'hidden');" + "input.setAttribute('name', '" + getParameterName(component) + "');" + "input.setAttribute('value', '" + parameter.getValue() + "');" + "}" + "form.appendChild(input);" + "return true;" + "}" + "}"; String functionName = "cp_" + actionComponent.getId(); String functionCode = "var " + functionName + " = " + "new Function(\"event\", \"" + functionBody + "\");"; writer.write(functionCode); // We are either written before the HTML element (e.g. a:commandButton) // In this case we can simply prepend to the existing onClick String existingOnClick = (String) actionComponent.getAttributes().get("onclick"); actionComponent.getAttributes().put("onclick", functionName + "();" + existingOnClick); // But we also might be written after (e.g. JSF RI h:commandButton // In this case we can use event capture String functionRegister = "if (document.getElementById('" + actionComponent.getClientId(context) + "'))" + "{" + "document.getElementById('" + actionComponent.getClientId(context) + "').onclick = new Function(\"event\", \"" + functionBody + "\");" + "}"; writer.write(functionRegister); writer.endElement("script"); } } }