OpenFaces icon indicating copy to clipboard operation
OpenFaces copied to clipboard

Trouble rerendering <o:dropDownField> using Ajax in Firefox

Open openfaces opened this issue 10 years ago • 0 comments

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.

openfaces avatar Mar 11 '14 16:03 openfaces