You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ar...@apache.org on 2010/03/08 21:38:19 UTC

svn commit: r920500 - in /myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs: Page.js xhr/RequestQueue.js xhr/XMLRequest.js xhr/XMLRequestEvent.js

Author: arobinson74
Date: Mon Mar  8 20:38:18 2010
New Revision: 920500

URL: http://svn.apache.org/viewvc?rev=920500&view=rev
Log:
Move the JSF2 AJAX 'switch' code to the request queue and undo the hacks placed in Page.js. Added a switch that we can use to eventually select if JSF2 AJAX is used or not on the client

Modified:
    myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js
    myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/RequestQueue.js
    myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/XMLRequest.js
    myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/XMLRequestEvent.js

Modified: myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js?rev=920500&r1=920499&r2=920500&view=diff
==============================================================================
--- myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js (original)
+++ myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/Page.js Mon Mar  8 20:38:18 2010
@@ -18,14 +18,15 @@
  */
 function TrPage()
 {
-  jsf.ajax.addOnError(TrUIUtils.createCallback(this, this._jsfAjaxErrorCallback));
-  jsf.ajax.addOnEvent(TrUIUtils.createCallback(this, this._jsfAjaxCallback));
+  if (typeof jsf != "undefined")
+  {
+    jsf.ajax.addOnEvent(TrUIUtils.createCallback(this, this._jsfAjaxCallback));
+  }
 
   this._loadedLibraries = TrPage._collectLoadedLibraries();
   this._requestQueue = new TrRequestQueue(window);
 }
 
-
 /**
  * Get the shared instance of the page object.
  */
@@ -59,20 +60,9 @@
   headerParams,
   event)
 {
-  var source = "";
-  if (params != null)
-    source = params.source;
-
-  // TODO: move this to the request queue
-  TrPage._delegateToJSFAjax(actionForm, source, event, params);
-
-
-  /** Delegating to jsf.ajax.request(). Do not call the Trinidad PPR request mechanism
-
   this.getRequestQueue().sendFormPost(
     this, this._requestStatusChanged,
-    actionForm, params, headerParams);
-  */
+    actionForm, params, headerParams, event);
 }
 
 TrPage.prototype._requestStatusChanged = function(requestEvent)
@@ -82,9 +72,9 @@
     var statusCode = requestEvent.getResponseStatusCode();
 
     // The server might not return successfully, for example if an
-    // exception is thrown.  When that happens, a non-200 (OK) status
-    // code is returned as part of the HTTP prototcol.
-    if (statusCode == 200)
+    // exception is thrown. When that happens, a status that is below
+    // 200 or 300 or above is returned as part of the HTTP prototcol.
+    if (statusCode >= 200 && statusCode < 300)
     {
       _pprStopBlocking(window);
 
@@ -101,7 +91,14 @@
         // Nokia browser is officially supported.
         if (responseDocument != null)
         {
-          this._handlePprResponse(responseDocument.documentElement);
+          if (requestEvent.isJsfAjaxRequest())
+          {
+            this._handleJsfAjaxResponse(requestEvent);
+          }
+          else
+          {
+            this._handlePprResponse(responseDocument.documentElement);
+          }
         }
       }
       else
@@ -116,7 +113,59 @@
       // wrong - we should do the handling here
       _pprStopBlocking(window);
     }
+  }
+  if (requestEvent.isJsfAjaxRequest())
+  {
+    this._handleJsfAjaxResponse(requestEvent);
+  }
+}
+
+TrPage.prototype._handleJsfAjaxResponse = function(requestEvent)
+{
+  try
+  {
+    var statusCode = requestEvent.getResponseStatusCode();
+    if (statusCode >= 200 && statusCode < 300)
+    {
+      if (this._ajaxOldDomElements)
+      {
+        this._notifyDomReplacementListeners(this._ajaxOldDomElements);
+      }
 
+      if (this._activeNode)
+      {
+        var activeNode = this._activeNode;
+        delete this._activeNode;
+        var index = -1;
+        if (activeNode.id)
+        {
+          for (var i = 0, size = this._ajaxOldDomElement.length; i < size; ++i)
+          {
+            if (TrPage._isDomAncestorOf(activeNode, this._ajaxOldDomElement[i].element))
+            {
+              index = i;
+              break;
+            }
+          }
+          if (index >= 0)
+          {
+            activeNode = document.getElementById(activeNode.id);
+            window._trActiveElement = activeNode;
+            if (activeNode)
+            {
+              activeNode.focus();
+            }
+          }
+        }
+      }
+    }
+    // TODO: do we need to do any additional processing here, for instance,
+    // error processing?
+  }
+  finally
+  {
+    delete this._ajaxOldDomElements;
+    delete this._activeNode;
   }
 }
 
@@ -781,95 +830,19 @@
   }
 }
 
-/**
- * Causes a partial submit to occur on a given component using the jsf.ajax.request call. The
- * specified component will not be validated (yet).
- * @param formId(String) Id of the form to partial submit.
- * @param inputId(String) Id of the element causing the partial submit.
- * @param event(Event) The javascript event object.
- * @param params(Object} additional parameters to send
- */
-TrPage._delegateToJSFAjax = function(formId, inputId, event, params)
-{
-  var doc = window.document;
-  var source = _getElementById(doc, inputId);
-
-  if (!params)
-    params = {};
-
-  // TODO: add execute and render targets??
-  jsf.ajax.request(source, event, params);
-}
-
 TrPage.prototype._jsfAjaxCallback = function(data)
 {
-  // TODO: move this code into the request queue to stop this gross infringement
-  // of encapsulation
-  switch (data.status)
-  {
-    case "begin":
-      this._requestQueue._state = TrRequestQueue.STATE_BUSY;
-      this._requestQueue._broadcastStateChangeEvent(this._requestQueue._state);
-      break;
-    case "success":
-      var oldElems = this._ajaxOldDomElements;
-      try
-      {
-        this._notifyDomReplacementListeners(oldElems);
-      }
-      finally
-      {
-        delete this._ajaxOldDomElements;
-      }
-      if (this._activeNode)
-      {
-        var activeNode = this._activeNode;
-        delete this._activeNode;
-        var index = -1;
-        if (activeNode.id)
-        {
-          for (var i = 0, size = oldElems.length; i < size; ++i)
-          {
-            if (TrPage._isDomAncestorOf(activeNode, oldElems[i].element))
-            {
-              index = i;
-              break;
-            }
-          }
-          if (index >= 0)
-          {
-            activeNode = document.getElementById(activeNode.id);
-            window._trActiveElement = activeNode;
-            if (activeNode)
-            {
-              activeNode.focus();
-            }
-          }
-        }
-      }
-      this._requestQueue._state = TrRequestQueue.STATE_READY;
-      this._requestQueue._broadcastStateChangeEvent(this._requestQueue._state);
-      break;
-    case "complete": default:
-      _pprStopBlocking(window);
-      // Collect the DOM elements that will be replaced to be able to fire the
-      // DOM replacement events
-      this._ajaxOldDomElements = this._getDomToBeUpdated(data.responseCode, data.responseXML);
-      this._activeNode = _getActiveElement();
-      break;
+  if (data.status == "complete")
+  {
+    // Collect the DOM elements that will be replaced to be able to fire the
+    // DOM replacement events.
+    // This information is used in the _handleJsfAjaxResponse function that is called
+    // as a result of the request queue firing the XMLRequestEvent.
+    this._ajaxOldDomElements = this._getDomToBeUpdated(data.responseCode, data.responseXML);
+    this._activeNode = _getActiveElement();
   }
 }
 
-TrPage.prototype._jsfAjaxErrorCallback = function(data)
-{
-  // TODO: move this code into the request queue to stop this gross infringement
-  // of encapsulation
-  this._requestQueue._state = TrRequestQueue.STATE_READY;
-  this._requestQueue._broadcastStateChangeEvent(this._requestQueue._state);
-  delete this._ajaxOldDomElements;
-  delete this._activeNode;
-}
-
 TrPage.prototype._notifyDomReplacementListeners = function(dataArray)
 {
   var listeners = this._domReplaceListeners;

Modified: myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/RequestQueue.js
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/RequestQueue.js?rev=920500&r1=920499&r2=920500&view=diff
==============================================================================
--- myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/RequestQueue.js (original)
+++ myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/RequestQueue.js Mon Mar  8 20:38:18 2010
@@ -31,6 +31,9 @@
 
   // Stash away the DOM window for later reference.
   this._window = domWindow;
+  // TODO: set this via a web.xml configuration parameter as well as checking for presense of the
+  // JSF library
+  this._useJsfBuiltInAjaxForXhr = (typeof jsf != "undefined");
 }
 
 // Class constants
@@ -57,7 +60,8 @@
   actionURL,
   headerParams,
   content,
-  method
+  method,
+  event
   )
 {
   this._type = type;
@@ -66,6 +70,7 @@
   this._headerParams = headerParams;
   this._content = content;
   this._method = method;
+  this._event = event;
 }
 
 TrRequestQueue.prototype._broadcastRequestStatusChanged = function(
@@ -92,11 +97,23 @@
   listener,
   actionURL,
   content,
-  headerParams
+  headerParams,
+  event
   )
 {
   var newRequest = new TrRequestQueue._RequestItem(
-                          type, context, actionURL, headerParams, content, listener);
+                          type, context, actionURL, headerParams, content, listener, event);
+
+  if (this._useJsfBuiltInAjaxForXhr && type == TrRequestQueue._XMLHTTP_TYPE)
+  {
+    // Since JSF 2 already has a queue, we need not queue the request here, instead we should
+    // immediately process the request
+    this._state = TrRequestQueue.STATE_BUSY;
+    this._broadcastStateChangeEvent(TrRequestQueue.STATE_BUSY);
+    this._doXmlHttpRequest(newRequest);
+    return;
+  }
+
   this._requestQueue.push(newRequest);
 
   try
@@ -131,7 +148,8 @@
   method,
   actionForm,
   params,
-  headerParams
+  headerParams,
+  event
   )
 {
   //this retrieves the action url for PPR.  Generally this will be the action property on
@@ -139,7 +157,7 @@
   //expando property encoded as a ResourceUrl.  As such, if the expando is available, use it
   //for PPR
   var pprURL;
-  // In mobile browsers like windows mobile ie, getAttribute funtion throws an exception if 
+  // In mobile browsers like windows mobile ie, getAttribute funtion throws an exception if
   // actionForm doesn't contain the attribute "_trinPPRAction".
   try
   {
@@ -149,7 +167,7 @@
   {
   }
   var action = pprURL?pprURL:actionForm.action;
-  
+
   if (this._isMultipartForm(actionForm))
   {
     // TODO: log a warning if we're dropping any headers?  Or
@@ -158,13 +176,24 @@
   }
   else
   {
-    var content = this._getPostbackContent(actionForm, params);
-
     // IE BUG, see TRINIDAD-704
     if(_agent.isIE)
       this._autoCompleteForm(actionForm);
 
-    this.sendRequest(context, method, action, content, headerParams);
+    if (this._useJsfBuiltInAjaxForXhr)
+    {
+      // JSF 2 AJAX will take the parameters and it will determine the form
+      // content itself, so we should not convert the data to a string or
+      // gather the form values
+      // TODO: log a warning if we're dropping any headers?  Or
+      // come up with a hack to send "headers" via a multipart request?
+      this.sendRequest(context, method, action, params, headerParams, event);
+    }
+    else
+    {
+      var content = this._getPostbackContent(actionForm, params);
+      this.sendRequest(context, method, action, content, headerParams, event);
+    }
   }
 }
 
@@ -349,22 +378,25 @@
 
 /**
 * Performs Asynchronous XML HTTP Request with the Server
-* @param context    any object that is sent back to the callback when the request
+* @param context Any object that is sent back to the callback when the request
 *  is complete. This object can be null.
-* @param method   Javascript method
-* @param actionURL   the url to send the request to
-* @param headerParams  Option HTTP header parameters to attach to the request
-* @param content     the content of the Asynchronous XML HTTP Post
+* @param method Javascript method
+* @param actionURL The url to send the request to
+* @param headerParams Option HTTP header parameters to attach to the request
+* @param content The content of the Asynchronous XML HTTP Post
+* @param event The browser event that triggered the request, if any
 */
 TrRequestQueue.prototype.sendRequest = function(
   context,
   method,
   actionURL,
   content,
-  headerParams
+  headerParams,
+  event
   )
 {
-  this._addRequestToQueue(TrRequestQueue._XMLHTTP_TYPE, context, method, actionURL, content, headerParams);
+  this._addRequestToQueue(TrRequestQueue._XMLHTTP_TYPE, context, method, actionURL, content,
+    headerParams, event);
 }
 
 /**
@@ -411,30 +443,42 @@
 
 TrRequestQueue.prototype._doXmlHttpRequest = function(requestItem)
 {
-  var xmlHttp = new TrXMLRequest();
+  var xmlHttp;
+  if (this._useJsfBuiltInAjaxForXhr)
+  {
+    xmlHttp = new TrXMLJsfAjaxRequest(requestItem._event, requestItem._content);
+  }
+  else
+  {
+    xmlHttp = new TrXMLRequest();
+  }
+
   xmlHttp.__dtsRequestContext = requestItem._context;
   xmlHttp.__dtsRequestMethod = requestItem._method;
   var callback = TrUIUtils.createCallback(this, this._handleRequestCallback);
   xmlHttp.setCallback(callback);
 
-  // xmlhttp request uses the same charset as its parent document's charset.
-  // There is no need to set the charset.
-  xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+  if (!this._useJsfBuiltInAjaxForXhr)
+  {
+    // xmlhttp request uses the same charset as its parent document's charset.
+    // There is no need to set the charset.
+    xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
 
-  var headerParams = requestItem._headerParams;
+    var headerParams = requestItem._headerParams;
 
-  if (headerParams != null)
-  {
-    for (var headerName in headerParams)
+    if (headerParams != null)
     {
-      var currHeader =  headerParams[headerName];
+      for (var headerName in headerParams)
+      {
+        var currHeader =  headerParams[headerName];
 
-      // handle array parameters by joining them together with comma separators
-      // Test if it's an array via the "join" method
-      if (currHeader["join"])
-        currHeader = currHeader.join(',')
+        // handle array parameters by joining them together with comma separators
+        // Test if it's an array via the "join" method
+        if (currHeader["join"])
+          currHeader = currHeader.join(',')
 
-      xmlHttp.setRequestHeader(headerName, currHeader);
+        xmlHttp.setRequestHeader(headerName, currHeader);
+      }
     }
   }
 
@@ -675,7 +719,7 @@
     // the Http connection  has been closed
   }
 
-  if ((statusCode != 200) && (statusCode != 0))
+  if ((status < 200 || status >= 300) && (statusCode != 0))
   {
     TrRequestQueue._alertError();
     TrRequestQueue._logError("Error StatusCode(",

Modified: myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/XMLRequest.js
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/XMLRequest.js?rev=920500&r1=920499&r2=920500&view=diff
==============================================================================
--- myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/XMLRequest.js (original)
+++ myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/XMLRequest.js Mon Mar  8 20:38:18 2010
@@ -6,9 +6,9 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- * 
+ *
  *  http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -34,7 +34,6 @@
   this.xmlhttp = TrXMLRequest._createXmlHttpRequest();
 }
 
-
 /**
 * Request state constants. See getCompletionState()
 **/
@@ -49,7 +48,7 @@
 * Parameters: isSynch - true if request should be synchronous,
 * false otherwise
 **/
-TrXMLRequest.prototype.setSynchronous = 
+TrXMLRequest.prototype.setSynchronous =
 function (isSynch)
 {
   this.isSynchronous = isSynch;
@@ -62,7 +61,7 @@
 * The callback should have the following siganture:
 * <void> function (<TrXMLRequest>request)
 **/
-TrXMLRequest.prototype.setCallback = 
+TrXMLRequest.prototype.setCallback =
 function (_callback)
 {
   this.callback = _callback;
@@ -92,7 +91,7 @@
 * Note: this method will block if the the request is asynchronous and
 * has not yet been completed
 **/
-TrXMLRequest.prototype.getResponseXML = 
+TrXMLRequest.prototype.getResponseXML =
 function()
 {
   return this.xmlhttp.responseXML;
@@ -103,7 +102,7 @@
 * Note: this method will block if the the request is asynchronous and
 * has not yet been completed
 **/
-TrXMLRequest.prototype.getResponseText = 
+TrXMLRequest.prototype.getResponseText =
 function()
 {
   return this.xmlhttp.responseText;
@@ -111,7 +110,7 @@
 
 /**
 * Sends an XML HTTP request
-* Parameters: 
+* Parameters:
 * url - destination URL
 * content - XML document or string that should be included in the request's body
 **/
@@ -125,7 +124,7 @@
     cb.obj = this;
     xmlhttp.onreadystatechange  = cb;
   }
-  
+
   var method = content ? "POST" : "GET";
   xmlhttp.open(method, url, !this.isSynchronous);
   for (var name in this.headers)
@@ -144,20 +143,20 @@
 }
 
 
-TrXMLRequest.prototype.getResponseHeader = 
+TrXMLRequest.prototype.getResponseHeader =
 function(name)
 {
 
   return this.xmlhttp.getResponseHeader(name);
 }
 
-TrXMLRequest.prototype.getAllResponseHeaders = 
+TrXMLRequest.prototype.getAllResponseHeaders =
 function()
 {
   return this.xmlhttp.getAllResponseHeaders();
 }
 
-TrXMLRequest.prototype.setRequestHeader = 
+TrXMLRequest.prototype.setRequestHeader =
 function(name, value)
 {
   this.headers[name] = value;
@@ -206,4 +205,117 @@
   delete this.xmlhttp;
 }
 
+/**
+ * Wrapper for the JSF AJAX callback data that provides the same
+ * interface as TrXMLRequest to maintain a compatible API to ease
+ * the support of both the legacy code as well as code to integrate
+ * with JSF 2 AJAX
+ */
+function TrXMLJsfAjaxRequest(
+  event,
+  params)
+{
+  this.isSynchronous = false;
+  this.callback = null;
+  this._event = event;
+  this._params = params || new Object();
+  this._status = 0;
+  this._state = TrXMLRequest.UNINITIALIZED;
+}
+TrXMLJsfAjaxRequest.prototype.setCallback = function(value)
+{
+  this.callback = value;
+}
+TrXMLJsfAjaxRequest.prototype.getCompletionState = function()
+{
+  return this._state;
+}
+TrXMLJsfAjaxRequest.prototype.getStatus = function()
+{
+  return this._status;
+}
+TrXMLJsfAjaxRequest.prototype.getResponseXML = function()
+{
+  return this._responseXML;
+}
+TrXMLJsfAjaxRequest.prototype.getResponseText = function()
+{
+  return this._responseText;
+}
+TrXMLJsfAjaxRequest.prototype.cleanup = function()
+{
+  this.callback = null;
+}
+TrXMLJsfAjaxRequest.prototype._ajaxCallback = function(
+  data
+  )
+{
+  switch (data.status)
+  {
+    case "begin":
+      this._state = TrXMLRequest.LOADING;
+      break;
+    case "complete":
+      this._state = TrXMLRequest.LOADED;
+      break;
+    case "success":
+    default:
+      this._state = TrXMLRequest.COMPLETED;
+      break;
+  }
+
+  if (data.status != "begin")
+  {
+    this._status = data.responseCode;
+    this._responseXML = data.responseXML;
+    this._responseText = data.responseText;
+  }
 
+  if (this.callback)
+  {
+    this.callback(this);
+  }
+}
+TrXMLJsfAjaxRequest.prototype.__onerror = function(
+  data
+  )
+{
+  this._state = TrXMLRequest.COMPLETED;
+  this._status = data.responseCode;
+  this._responseXML = data.responseXML;
+  this._responseText = data.responseText;
+  if (this.callback)
+  {
+    this.callback(this);
+  }
+}
+TrXMLJsfAjaxRequest.prototype.send = function()
+{
+  var source = this._params.source ?
+    _getElementById(window.document, this._params.source) : null;
+
+  var ajaxCallback = TrUIUtils.createCallback(this, this._ajaxCallback);
+
+  jsf.ajax.request(
+    source,
+    this._event,
+    {
+      "onevent": ajaxCallback,
+      "onerror": ajaxCallback,
+      "params": this._params
+    });
+
+  // No need for the event anymore, release the resource
+  delete this._event;
+}
+// No-op functions:
+TrXMLJsfAjaxRequest.prototype.setSynchronous =
+TrXMLJsfAjaxRequest.prototype.setRequestHeader = function() {}
+TrXMLJsfAjaxRequest.prototype.getAllResponseHeaders = function()
+{
+  return new Object();
+};
+TrXMLJsfAjaxRequest.prototype.getResponseHeader = function()
+{
+  return null;
+};
\ No newline at end of file

Modified: myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/XMLRequestEvent.js
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/XMLRequestEvent.js?rev=920500&r1=920499&r2=920500&view=diff
==============================================================================
--- myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/XMLRequestEvent.js (original)
+++ myfaces/trinidad/branches/jsf2_ajax/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/xhr/XMLRequestEvent.js Mon Mar  8 20:38:18 2010
@@ -6,9 +6,9 @@
  *  to you under the Apache License, Version 2.0 (the
  *  "License"); you may not use this file except in compliance
  *  with the License.  You may obtain a copy of the License at
- * 
+ *
  *  http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  *  Unless required by applicable law or agreed to in writing,
  *  software distributed under the License is distributed on an
  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -20,7 +20,7 @@
 /**
  * AJAX Request Event class. This object is passed back to the listeners
  * of a AJAX Service Request. It support ITrXMLRequestEvent pseudo-interface
- * with the following methods: getStatus, getResponseXML, getResponseText, 
+ * with the following methods: getStatus, getResponseXML, getResponseText,
  * isPprResponse, getResponseContentType
  */
 function TrXMLRequestEvent(
@@ -56,7 +56,7 @@
 * NOTE: this method is valid only for TrXMLRequestEvent.STATUS_COMPLETE
 **/
 TrXMLRequestEvent.prototype._isResponseValidXML = function()
-{         
+{
   // Note: Mozilla applies default XSLT to XML parse error
   var responseDocument = this._request.getResponseXML();
   if (!responseDocument)
@@ -81,7 +81,7 @@
 * NOTE: this method is valid only for TrXMLRequestEvent.STATUS_COMPLETE
 **/
 TrXMLRequestEvent.prototype.getResponseText = function()
-{  
+{
   return this._request.getResponseText();
 }
 
@@ -147,4 +147,12 @@
 TrXMLRequestEvent.prototype.getResponseContentType = function()
 {
   this.getResponseHeader("Content-Type");
-}
\ No newline at end of file
+}
+
+/**
+ * Returns if the request was made by the built in JSF AJAX APIs
+ */
+TrXMLRequestEvent.prototype.isJsfAjaxRequest = function()
+{
+  return (this._request instanceof TrXMLJsfAjaxRequest);
+};
\ No newline at end of file