2011-10-26 46 views
3

我正在使用JSF w/Seam的Web应用程序。我希望能够在每个Ajax响应之后调用JavaScript函数。我正在寻找一种方法来做到这一点,而无需在每个页面上的每个commandLink/commandButton上放置oncomplete属性。如何在每个a4j AJAX响应后调用JavaScript函数?

我认为有一种方法来设置一个servlet过滤器(拦截器?我得到的术语困惑),以注入JS调用到每个响应。我将研究这一点。与此同时,如果有人有任何其他建议,我全都听过。

编辑:我认为jQuery ajaxSuccess方法可能是去这里的方式,但我不知道如何实际使用它。我无法获得任何注册。我基本上想添加代码来获取来自任何源的任何和所有ajax请求,以在成功时调用我的JavaScript方法。任何人都可以告诉我这样做的正确方法吗?我尝试了很多方法来做到这一点,包括将jQuery("*").ajaxSuccess(function(){myFunction();});添加到我的模板xhtml文件的底部。

回答

4

改写答案:see original answer in revision history

您可以覆盖XMLHttpRequest的默认send方法,其中一个劫持readystatechange处理程序:

(function() 
{ 
    var xhrSend = XMLHttpRequest.prototype.send; 
    XMLHttpRequest.prototype.send = function () 
    { 
     var handler = this.onreadystatechange; 
     this.onreadystatechange = function() 
     { 
      if (handler) { 
       if (handler.handleEvent) handler.handleEvent.apply(xhr, arguments); 
       else handler.apply(xhr, arguments); 
      } 
      if (this.readyState == 4) 
      { 
       // your oncomplete function here 
       this.onreadystatechange = handler; 
      } 
     }; 
     xhrSend.apply(this, arguments); 
    }; 
})(); 

编辑:以上函数不使用jQuery的要求工作,所以可能它可能不会与其他库也是如此。下面的修订版解决了setTimeout黑客延迟覆盖处理程序的代码的问题。当然,使用jQuery,您可以使用全局处理程序,但对于具有类似行为的其他库,这将会很有用。

(function() { 
    function globalHandler() { 
     if (this.readyState == 4) { 
      // your oncomplete code here 
     } 
    } 
    var xhrSend = XMLHttpRequest.prototype.send; 
    XMLHttpRequest.prototype.send = function() { 
     var xhr = this; 
     if (xhr.addEventListener) { 
      xhr.removeEventListener("readystatechange", globalHandler); 
      xhr.addEventListener("readystatechange", globalHandler, false); 
     } 
     else { 
      function readyStateChange() { 
       if (handler) { 
        if (handler.handleEvent) 
         handler.handleEvent.apply(xhr, arguments); 
        else 
         handler.apply(xhr, arguments); 
       } 
       globalHandler.apply(xhr, arguments); 
       setReadyStateChange(); 
      } 
      function setReadyStateChange() { 
       setTimeout(function() { 
        if (xhr.onreadystatechange != readyStateChange) { 
         handler = xhr.onreadystatechange; 
         xhr.onreadystatechange = readyStateChange; 
        } 
       }, 1); 
      } 
      var handler; 
      setReadyStateChange(); 
     } 
     xhrSend.apply(xhr, arguments); 
    }; 
})(); 

http://jsfiddle.net/gilly3/FuacA/5/
我在IE7-9进行了测试,Chrome浏览器的最新版本和FF

+0

我也尝试过。仍然没有效果。问题是我的ajax请求不是通过jQuery完成的吗? – iandisme

+0

@iandisme - YES !!绝对!那是你的问题。 '.ajaxSuccess'是一个* jQuery事件*。如果您在jQuery之外制作常规的XMLHttpRequest,jQuery无法了解它。 – gilly3

+0

@iandisme - 查看我的非jQuery解决方案的更新答案。 – gilly3

1

我认为这是你在找什么:Using Global Ajax Handlers In jQuery

+0

也不能得到这个工作。 jQuery(“*”)。bind(“ajaxSuccess”,function(){myFunction();});而其他一些东西根本不起作用。 – iandisme

+0

和为什么不工作? –

+0

链接不起作用(至少今天[2013年7月10日]该网站不可用)。 – matt

3

由于您使用RichFaces的,你可以简单地使用:

<a:status id="globalStatus" onstart="onRequestStart()" onstop="onRequestEnd()" /> 
+0

这不适合我。通过文档,有一个“for”属性指向我需要指定的a4j输出区域。简单地将此添加到我的模板文档中的主窗体中并不能解决问题。 +1虽然介绍我的标签。 – iandisme

+0

只是我的记忆:我认为这对我有用,因为我们定义了一个全局的ajax队列。如果你有这样的队列,那么这应该工作。否则,您可以在for属性中定义队列名称,或者也可以在ajax按钮的id中定义队列名称。我会为此查看Richfaces的现场演示。 –

+0

我使用全局ajax队列,以避免着名的并发呼叫对话问题,因为你没有定义一个但我不知道你不使用对话或解决它不同? –

2

使用A4J:状态应该工作,但它必须是一个H内部:表单标签:

<h:form id="randomForm" styleClass="edit"> 
     <a:status id="stateStatus" 
     onstart="Richfaces.showModalPanel('waitBx'),document.getElementById('randomForm:search').disabled=true;" 
     onstop="Richfaces.hideModalPanel('waitBx'),document.getElementById('randomForm:search').disabled=false;" 
     styleClass="message" > 
</a:status> 

...... way more code 
</form> 

每次ajax调用后,弹出一个等待图片并禁用搜索按钮。

有趣的是,至少在我们的代码中,这不适用于任何嵌套的a4j:区域。

+0

+1表示重要的表单标记 –

相关问题