6 Replies Latest reply: Feb 10, 2011 10:23 AM by yagish sharma RSS

a4j:jsFunction in IE6/7 breaks when html:form's prependId="f

yagish sharma Newbie

In RichFaces3.2.2SR1, a4j:jsFunction generates an HTML script, which breaks in IE6/7, but works in FireFox. The issue is the way the jsFunction is rendered.

Here is a sample of how the script is rendered in Ajax4JSF and in RichFaces when html:form's prependId attribute is false.

<a4j:jsFunction name="func1" and id="func1" action="doSomething()"/>

Notice that the name and id fields are kept same.

In Ajax4JSF, this will render as -
script id="func1" type="text/javascript"
function func1(){.........};
/script

In RichFaces, this renders as -
script id="func1" type="text/javascript">
func1 = function(){.........};
/script

Having the id of script tag and the func1 prototype name as same creates the problem. IE6/7 while parsing the script tag gives an error - "Object does not supports this property".

In RichFaces the renderer for jsFunction is AjaxFunctionRendererBase. This renderer's getFunction() method has changed from Ajax4JSF and generates this inappropriate javascript code.

A sample to try in IE6/7 - (Uses Facelets, can get rid of them)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j">




<a4j:log popup="false" level="ALL" style="width: 800px; height: 300px;"></a4j:log>

<f:view>
<rich:panel header="Simple Echo">
<h:inputText size="50" value="#{bean.text}" >
<a4j:support event="onkeyup" reRender="rep"/>
</h:inputText>
<h:outputText value="#{bean.text}" id="rep"/>

<a4j:jsFunction id="startSession" name="startSession" action="#{bean.startSession}" oncomplete="alert('I am done');"/>

</rich:panel>

</f:view>




  • 1. Re: a4j:jsFunction in IE6/7 breaks when html:form's prependI
    Nick Belaevski Master

    Hi,

    With the new style of rendering you can easily assign function to complex variable, e.g.:

    <h:form prependId="false">
     <rich:panel header="Simple Echo">
     <h:inputText size="50" value="#{bean.text}">
     <a4j:support event="onkeyup" reRender="rep" />
     </h:inputText>
     <h:outputText value="#{bean.text}" id="rep" />
    
     <script>
     var funcs = new Array();
     </script>
    
     <a4j:jsFunction id="startSession" name="funcs[0]"
     action="#{bean.startSession}" oncomplete="alert('I am done');" />
    
     <script>
     funcs[0]();
     </script>
    
     </rich:panel>
     </h:form>


  • 2. Re: a4j:jsFunction in IE6/7 breaks when html:form's prependI
    yagish sharma Newbie

    Thanks nbelaevski.
    Your suggestion is similar to using different values for "id" and the "name" attributes. I have tried that and it does work. Also, changing the prependId attribute of html:form works, since it prepends the "id" with the form name, making it different from name attribute. (This does breaks the existing javascript though :( )

    My constraint is, I am porting our application from using Ajax4JSF to RichFaces3.2.2. So making this change in each JSF file, would require me to change every Javascript as well.

    I was trying to create a different renderer for the jsFunction component for RichFaces, but unfortunately its not easily configurable (or I dont know the correct way as yet). Another approach I am trying is to create a custom component and renderer and use that instead of a4j:jsFunction. This also is a big change, and not the best way of resolving this issue.

    I am trying to figure out a solution with the minimal impact. Would appreciate any help.

    Thanks
    Yagish Sharma

  • 4. Re: a4j:jsFunction in IE6/7 breaks when html:form's prependI
    yagish sharma Newbie

    Here is a workaround to fix this issue.

    Create a new class extending the FunctionRenderer in RichFaces, and over-ride the getFunction method -

    public class NewAjaxFunctionRenderer extends FunctionRenderer{
     /*
     * (non-Javadoc)
     *
     * @see org.ajax4jsf.framework.renderer.RendererBase#getComponentClass()
     */
    
     public static final String RENDERER_TYPE = "org.cas.AjaxFunctionRenderer";
     protected Class getComponentClass() {
     return HtmlAjaxFunction.class;
     }
    
     public String getFunction(FacesContext context, UIAjaxFunction component) {
     StringBuffer script = new StringBuffer();
     JSFunctionDefinition func = new JSFunctionDefinition();
     func.setName(component.getName());
     // Create AJAX Submit function.
     JSFunction ajaxFunction = AjaxRendererUtils.buildAjaxFunction(
     component, context,AjaxRendererUtils.AJAX_FUNCTION_NAME);
     Map options = AjaxRendererUtils.buildEventOptions(context, component);
     Map parameters = (Map) options.get("parameters");
     if (null == parameters) {
     parameters = new HashMap();
     options.put("parameters", parameters);
     }
     ajaxFunction.addParameter(JSReference.NULL);
     ajaxFunction.addParameter(options);
     // Fill parameters.
     for (Iterator it = component.getChildren().iterator(); it.hasNext();) {
     UIComponent child = (UIComponent) it.next();
     if (child instanceof UIParameter) {
     UIParameter parameter = ((UIParameter) child);
     String name = parameter.getName();
     func.addParameter(name);
     // Put parameter name to AJAX.Submit parameter, with default value.
     JSReference reference = new JSReference(name);
     if (null != parameter.getValue()) {
     reference = new JSReference(name + "||"
     + ScriptUtils.toScript(parameters.get(name)));
    
     }
     // Replace parameter value to reference.
     parameters.put(name, reference);
     }
     }
     func.addToBody(ajaxFunction.toScript());
     func.appendScript(script);
     return script.toString();
     }
    }


    In faces-config.xml add the new renderer for a4j:jsFunction -

    <renderer>
     <component-family>org.ajax4jsf.components.AjaxFunction</component-family>
     <renderer-type>
     org.ajax4jsf.components.AjaxFunctionRenderer
     </renderer-type>
     <renderer-class>
     org.test.NewAjaxFunctionRenderer
     </renderer-class>
     </renderer>


  • 5. Re: a4j:jsFunction in IE6/7 breaks when html:form's prependI
    Ophir Tahor Newbie

    Hi,

     

    I have the same issue in our system. We are using version 3.3.0 of richfaces and it seems that the NewAjaxFunctionRenderer that I added wasn't invoked.

    I did  the same things that mentioned here: Createed a new Class and added the renderer to face-config.xml file.

     

    Can someone help me to understand what should be done in order to make it invoked.

     

     

    Thanks for any help.

  • 6. a4j:jsFunction in IE6/7 breaks when html:form's prependId="f
    yagish sharma Newbie

    Hi,

      You will have to check in the faces-config in the richfaces jar, and see whats the component-family and renderer-type for AjaxFunctionRenderer is defined. Then you can over-write that with your custom renderer-class in your faces-config.xml. Hope this helps.

     

    yagish