5 Replies Latest reply on Jul 6, 2009 9:44 AM by pc00k9

    A4J.AJAX.AddListener resetting after ajax request?

      Headache inducing scenario involving Magnolia cms v4.0.1, jQuery v1.3.2, Seam v2.1.1, RichFaces v3.3.1, jboss 4.2.2, Firefox 3.0.11/IE6.0...

      - Main page is served up from Magnolia
      - Its document-ready uses jQuery.load() to ajax in a form from Seam
      - The seam form is using a4j: taglib for ajax validation & rerendering of form elements

      That all works fine. Phew. :)

      For consistency across the whole site we replaced rich:calendar in the seam fragments with jquery.datepicker thats used on all the other (non-seam/rich) pages. As a minor consequence, each time an a4j rerender fired, the text controls would lose their jquery datepicker bindings - but no big problem we thought - we can tag a listener into A4J.AJAX.AddListener() and hook them into jquery again after each ajax call.

      And thats where the headaches began. :( No matter whether we initially hook up the global ajax listener in the main magnolia page or in the injected seam fragment, they're not surviving >1 ajax rerender call.

      For example, with this code in doc-ready in the main magnolia page ...


      jQuery(document).ready(function() {

      A4J.AJAX.AddListener({
      onafterajax: function(req,evt,data) { alert("onafterajax "+A4J.AJAX._listeners.length);}
      });

      alert("ready "+A4J.AJAX._listeners.length);

      jQuery('.ajaxMe').each(function() {
      var ajaxMe = jQuery(this);
      ajaxMe.load(contextPath + "/" + ajaxMe.attr("link"));
      });

      });

      The initial "ready" alert will popup and report 1 listener. All ok. jquery drags in the seam fragment. All ok. When the seam fragment does its first a4j rerender call to validate a field, theres no "onafterajax" popup - the listener is gone. I added an onbefore listener too, that didnt popup. So with the listener registered in the main magnolia page, its gone after the seam fragment loads.

      Slighty different results if the AddListener + alert is moved into an inline JS block within the seam fragment. The first a4j rerender does end with a popup reporting 1 listener. All ok. But then the listener is gone by the time the next rerender validation occurs.

      I've grepped all the js packs that are being dragged in to the page (tracked them thro firebug).
      a4j/*/a4jscript/*/a4jscriptimg/**.xhtml*.seam/stylesheet/*/script/*/img/a4j/g/3_3_1.GAorg.ajax4jsf.javascript.AjaxScript
      a4j/*/a4jscript/*/a4jscriptimg/**.xhtml*.seam/stylesheet/*/script/*/img/a4j/g/3_3_1.GAorg.ajax4jsf.javascript.PrototypeScript
      a4j/*/a4jscript/*/a4jscriptimg/**.xhtml*.seam/stylesheet/*/script/*/img/a4j/g/3_3_1.GAorg/richfaces/renderkit/html/scripts/events.js
      a4j/*/a4jscript/*/a4jscriptimg/**.xhtml*.seam/stylesheet/*/script/*/img/a4j/g/3_3_1.GAorg/richfaces/renderkit/html/scripts/utils.js
      a4j/*/a4jscript/*/a4jscriptimg/**.xhtml*.seam/stylesheet/*/script/*/img/a4j/g/3_3_1.GAorg/richfaces/renderkit/html/scripts/json/json-dom.js
      a4j/*/a4jscript/*/a4jscriptimg/**.xhtml*.seam/stylesheet/*/script/*/img/a4j/g/3_3_1.GAorg/richfaces/renderkit/html/scripts/scriptaculous/effects.js
      a4j/*/a4jscript/*/a4jscriptimg/**.xhtml*.seam/stylesheet/*/script/*/img/a4j/g/3_3_1.GAorg/richfaces/renderkit/html/scripts/jquery/jquery.js
      a4j/*/a4jscript/*/a4jscriptimg/**.xhtml*.seam/stylesheet/*/script/*/img/a4j/g/3_3_1.GAorg/richfaces/renderkit/html/scripts/JQuerySpinBtn.js
      a4j/*/a4jscript/*/a4jscriptimg/**.xhtml*.seam/stylesheet/*/script/*/img/a4j/g/3_3_1.GAorg/richfaces/renderkit/html/scripts/calendar.js
      script/jquery-ui-1.7.custom.min.js

      There arent any calls to A4J.AJAX.removeListeners() lurking in any of them. Its almost as if the A4J object is cleaned out (or maybe discarded and recreated?) on each rerender?? Is it being overwritten somehow in this weird double ajax aggregation scenario?

      Any wise words would be gratefully received. Even unwise words would be considered ;)


        • 1. Re: A4J.AJAX.AddListener resetting after ajax request?
          nbelaevski

          Hi,

          My guess it's just being recreated when AjaxScript is being loaded. To check: add script containing

          alert('script initialization');
          using a4j:loadScript and see whether it alerts for each AJAX request or not.


          • 2. Re: A4J.AJAX.AddListener resetting after ajax request?

            Ouch. You seem to be correct - the scripts are all re-executed and A4J seems to splat itself. :(

            Hmmm, I've stumbled around it by re-adding the listener in onafter, its a bit of a kludge and its only safe to do that if you're the last listener in the array (otherwise you'll be called again in the current notification cycle while A4J walks its _listeners array!).

            var onAfterAjaxListener = new A4J.AJAX.AjaxListener("onafterajax", function(req,evt,data) {
             A4J.AJAX.removeListener(onAfterAjaxListener);
             A4J.AJAX.AddListener(onAfterAjaxListener);
             alert("onafterajax");
             }
            );
            A4J.AJAX.AddListener(onAfterAjaxListener);
            


            horrible, horrible.


            • 3. Re: A4J.AJAX.AddListener resetting after ajax request?

              Infact, scratch that entirely - its not reliable.
              There seems to be a timing issue.
              Put the alert as the first line in the callback and it usually works.
              Put the popup last, or dont have it at all and the listeners are gone next time around.
              I guess the first line alert is (usually!) delaying the switch until after the new A4J is created. Without the initial alert it seems to be the "old" A4J.

              Oh well, time to give up I think.

              • 4. Re: A4J.AJAX.AddListener resetting after ajax request?
                nbelaevski

                So, does this happen when requests are initiated by RF or not?

                • 5. Re: A4J.AJAX.AddListener resetting after ajax request?

                  yes, your script init popup suggestion was correct, each ajax request seems to cause re-execution of all loadscripts

                  having found that - I was trying to work around it by removing/re-adding, but to no avail