views:

811

answers:

2

Hi all,

I have a JSF 1.2 application (Sun RI, Facelets, Richfaces) that was used only on IE6 browsers. Now, we must also support Firefox (yeah !).

In one of my pages, I have a form that contains a button that will re-render the whole form. After the re-rendering, some links (<h:commandLink/>) are added in this form.

The JSF code looks like this:

<h:form id="foobar">
    ...
    <a4j:commandButton ... reRender="foobar"/>
    ...
    <h:commandLink .../>
</h:form>

My problem is related to the HTML code generated by the command link component, which is as following:

<a href="#" onclick="if(typeof jsfcljs == 'function'){jsfcljs(document.forms['foobar'],'...','');}return false">bla bla</a>

(for information, jsfcljs is the Javascript function generated by the component <h:commandLink/>)

The problem is that document.forms["foobar"] is working well when the page is initially rendered, but once the form is re-rendered after the Ajax call, this code does not work anymore on Firefox (but works on IE6).

This results on a Javascript error when I click on one link in the form after the Ajax call.

Note that if I call document.getElementById("foobar"); after the Ajax call, Firefox founds my form...

If you consider the following Javascript function:

function test() {
    var e = document.forms;
    var tmp = "";
    for (i = 0; i < e.length; i++) {
     tmp = tmp + e[i].id + " ; ";
    }
    alert(tmp);
}

when I run it before and after the Ajax call, I get the following results:

someForm ; anotherForm ; foobar ; // Before Ajax call on FF 
someForm ; anotherForm ; // After Ajax call on FF. PROBLEM HERE!

someForm ; anotherForm ; foobar ; // Before Ajax call on IE6 
someForm ; anotherForm ; foobar ; // After Ajax call on IE6

Here are my thoughts about the reason of the problem:

When the Ajax response is received on the client side, a4j is removing the reRender-ed elements (in particular my foobar form) from the DOM tree objects, which results in removing it from document.forms array. Then, it adds again the foobar form with its new content. But Firefox does not update the document.forms array, while IE6 does. That's why document.forms["foobar"] returns undefined after the Ajax call.

My solution to solve this problem is to change the reRender attribute in order to re-render only sub-parts of the form, and not the form itself. This way, my links work.

However, I wanted to know if there is another way to solve this issue, without modifying the reRender attribute. Any idea?


Edit

The Javascript code when a command link is clicked is the following:

function dpf(f) {
    var adp = f.adp;
    if (adp != null) {
        for (var i = 0; i < adp.length; i++) {
            f.removeChild(adp[i]);
        }
    }
};

function apf(f, pvp) {
    var adp = new Array();
    f.adp = adp;
    var ps = pvp.split(',');
    for (var i = 0, ii = 0; i < ps.length; i++, ii++) {
        var p = document.createElement("input");
        p.type = "hidden";
        p.name = ps[i];
        p.value = ps[i + 1];
        f.appendChild(p);
        adp[ii] = p;
        i += 1;
    }
};

function jsfcljs(f, pvp, t) {
    apf(f, pvp);
    var ft = f.target;
    if (t) {
        f.target = t;
    }
    f.submit();
    f.target = ft;
    dpf(f);
};

In the <h:commandLink> onclick attribute, we call the jsfcljs(document.forms['foobar'], 'someId', '') which is evaluated in jsfcljs(undefined, 'someId', ''). Then, when f is called, I get a Javacript error that says that f is undefined.

+1  A: 

The problem is actually an HTML one from what I see.

Your form should be defined with a name and not simply an id attribute:

Different browsers treat name and id equivalencies differently. If this does not solve your problem comment and I will produce a test case that does not require a server-side to demonstrate whatever effect you're seeing.

Another way around the problem code is to rewrite the inline onclick event calls on the client-side in order to reference the form by id with the document.getElementById("foobar") call instead of document.forms["foobar"]

J5
Thanks for the idea of using the `name` in addition to the `id` attribute. I will check that soon!Regarding your proposition to modify the inline `onclick` function, it is not conceivable, as this JS code is *generated* by the JSF core. However, as stated by **BalusC**, this code has maybe evolved since the latest release of JSF 1.2...
romaintaz
The functions can be modified by other javascript code embedded in the page. If it turns out that is necessary, I can likely provide code that accomplishes this task.
J5
A: 

I recall this as one of the bugs of Sun Mojarra 1.2 (which has already been around for 4 years). Upgrading the libs should solve this problem. The currently latest Sun Mojarra 1.2 is 1.2_14 which was released just three weeks ago. Just replace the two JSF libs in /WEB-INF/lib with them.

BalusC