OpenFaces
OpenFaces copied to clipboard
Trouble rerendering <o:dropDownField> using Ajax in Firefox
Nicholas Oxhøj I have run into a bug with <o:dropDownField> when being inside a component/region rerendered by RichFaces Ajax.
When such a page is viewed in newer Firefox browsers, the rerendered dropdown, doesn't get initialized correctly, e.g. the button doesn't show and you cannot open the dropdown with the keyboard either.
This bug is caused by some bugs in the two fixes that was made for my old related bug report: http://requests.openfaces.org/browse/OF-66
The first bug is in O$.removeRelocatedPopupIfExists:
O$.removeRelocatedPopupIfExists = function(popupId) {
var dapp = O$.getDefaultAbsolutePositionParent();
var potentialPopups = dapp.childNodes;
for (var i = 0, count = potentialPopups.length; i < count; i++) {
var potentialPopup = potentialPopups[i];
if (potentialPopup.id == popupId) {
dapp.removeChild(potentialPopup);
}
}
};
(https://github.com/openfaces/OpenFaces/blob/12462a399f63b9efaa3907737fd0fe416a08cb94/openFaces/source/META-INF/resources/openfaces/util/util.js#L3764)
The problem is that potentialPopups is a "live" list, such that when you remove child nodes, they also disappear from potentialPopups, which is then shortened. But you have cached the length in the "count" variable, so that when you try to access the "count'th" element, "potentialPopup" will be undefined, "potentialPopup.id" will throw an error, and the rest of O$.DropDown._init() will never be executed...
To fix this, you could stop caching the length:
for (var i = 0; i < potentialPopups.length; i++) {
Or if you for some reason was worried about calling "potentialPopups.length" more than once, you could just run through it in the opposite direction:
for (var i = potentialPopups.length - 1 ; i >= 0; i--) {
But the above bug shouldn't be relevant in a new Firefox browser, since you only intend to relocate popups in Firefox 2 (and some cases of IE).But this happens because of the second bug introduced in the fix for OF-66.
The test in O$.DropDown._initPopup() looks like
if ((O$.isExplorer() && O$.isQuirksMode() && dropDown._popup.parentNode != container) ||
(O$.isMozillaFF2() && O$.isStrictMode())) {
(https://github.com/openfaces/OpenFaces/blob/cdde1153922583ce13003ce0eb5c175fd00c4554/openFaces/source/META-INF/resources/openfaces/input/dropdown.js#L465)
But O$.isMozillaFF2() now looks like
O$.isMozillaFF2 = function() {
return O$.isMozillaFF() && O$.userAgentContains("Firefox/2");
};
https://github.com/openfaces/OpenFaces/blob/12462a399f63b9efaa3907737fd0fe416a08cb94/openFaces/source/META-INF/resources/openfaces/util/util.js#L938
and since my Firefox is now version 23, the user agent string conatins "Firefox/23.0" and therefore O$.isMozillaFF2() returns true. So you should probably at least do something like
navigator.userAgent.search(/Firefox\/2(\D|$)/i)
when matching for specific versions.