I am currently working on a JSF 1.2 application (Sun RI, Facelets, Richfaces) that was previously designed only for IE6 browsers. However, we now need to extend our support to include Firefox as well.
On one of the pages, there is a form with a button that triggers a re-render of the entire form. Subsequently, after this re-rendering process, some links (<h:commandLink/>
) are dynamically added to the form.
The JSF code snippet in question is:
<h:form id="foobar">
...
<a4j:commandButton ... reRender="foobar"/>
...
<h:commandLink .../>
</h:form>
One issue I encountered relates to the HTML code generated by the command link component, specifically:
<a href="#" onclick="if(typeof jsfcljs == 'function'){jsfcljs(document.forms['foobar'],'...','');}return false">bla bla</a>
(just to clarify, jsfcljs
is a Javascript function created by the <h:commandLink/>
component)
The problem arises because document.forms["foobar"]
functions correctly when the page is initially loaded, but becomes dysfunctional after the form is re-rendered following an Ajax call, particularly on Firefox (while it still works on IE6).
This results in a JavaScript error when attempting to click on any link within the form post-Ajax call.
It's worth noting that if I use
document.getElementById("foobar");
instead, Firefox successfully locates my form even after the Ajax call.
To provide more context, let's consider the following custom 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 running this function before and after the Ajax call, the following outcomes are observed:
someForm ; anotherForm ; foobar ; // Before Ajax call on FF
someForm ; anotherForm ; // After Ajax call on FF. ISSUE HERE!
someForm ; anotherForm ; foobar ; // Before Ajax call on IE6
someForm ; anotherForm ; foobar ; // After Ajax call on IE6
My analysis of the problem suggests that upon receipt of the Ajax response, a4j removes the reRender-ed elements (including my foobar
form) from the DOM tree objects. Consequently, this removal from the document.forms
array update is not propagated in Firefox as opposed to IE6 which does update the array. As a result, document.forms["foobar"]
returns undefined
post-Ajax call on Firefox.
As a workaround solution, I recommend adjusting the reRender
attribute to target specific subsections of the form rather than the entire form itself. This adjustment ensures the proper functionality of the links.
However, I'm curious to explore other potential resolutions for this issue without requiring modifications to the reRender
attribute. Any suggestions?
Edit
The Javascript snippet triggered when a command link is clicked is as follows:
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);
};
Within the <h:commandLink>
onclick handler, the invocation is made to
jsfcljs(document.forms['foobar'], 'someId', '')
causing evaluation to jsfcljs(undefined, 'someId', '')
. This sequence leads to a JavaScript error stating that f is undefined
upon execution of f
.