1 /* Licensed to the Apache Software Foundation (ASF) under one or more
  2  * contributor license agreements.  See the NOTICE file distributed with
  3  * this work for additional information regarding copyright ownership.
  4  * The ASF licenses this file to you under the Apache License, Version 2.0
  5  * (the "License"); you may not use this file except in compliance with
  6  * the License.  You may obtain a copy of the License at
  7  *
  8  *      http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  */
 16 
 17 /**
 18  * An implementation of an xhr request object
 19  * with partial page submit functionality, and jsf
 20  * ppr request and timeout handling capabilities
 21  *
 22  * Author: Ganesh Jung (latest modification by $Author: ganeshpuri $)
 23  * Version: $Revision: 1.4 $ $Date: 2009/05/31 09:16:44 $
 24  */
 25 
 26 /**
 27  * @class
 28  * @name _AjaxRequest
 29  * @memberOf myfaces._impl.xhrCore
 30  * @extends myfaces._impl.xhrCore._BaseRequest
 31  */
 32 myfaces._impl.core._Runtime.extendClass("myfaces._impl.xhrCore._AjaxRequest", myfaces._impl.xhrCore._BaseRequest,
 33 /** myfaces._impl.xhrCore._AjaxRequest.prototype */
 34 {
 35     /**
 36      * Constructor
 37      * <p />
 38      * note there is a load of common properties
 39      * inherited by the base class which define the corner
 40      * parameters and the general internal behavior
 41      * like _onError etc...
 42      * @param {Map} an arguments map which an override any of the given protected
 43      * instance variables, by a simple name value pair combination
 44      */
 45     constructor_: function(arguments) {
 46 
 47         try {
 48             this._callSuper("constructor", arguments);
 49             /*namespace remapping for readability*/
 50             //we fetch in the standard arguments
 51             //and apply them to our protected attributes
 52             this._Lang.applyArgs(this, arguments);
 53 
 54             //if our response handler is not set
 55             if (!this._response) {
 56                 this._response = new myfaces._impl.xhrCore._AjaxResponse(this._onException, this._onWarning);
 57             }
 58 
 59             this._ajaxUtil = new myfaces._impl.xhrCore._AjaxUtils(this._onException, this._onWarning);
 60         } catch (e) {
 61             //_onError
 62             this._onException(this._xhr, this._context, "myfaces._impl.xhrCore._AjaxRequest", "constructor", e);
 63         }
 64     },
 65 
 66     /**
 67      * Sends an Ajax request
 68      */
 69     send : function() {
 70         try {
 71             //we have to encode at send time, otherwise
 72             //we pick up old viewstates
 73             this._initRequestParams();
 74             this._startXHR();
 75             this._startTimeout();
 76         } catch (e) {
 77             //_onError//_onError
 78             this._onException(this._xhr, this._context, "myfaces._impl.xhrCore._AjaxRequest", "send", e);
 79         }
 80     },
 81 
 82 
 83     /**
 84      * gets the ViewState including all now passed in sideconstraints
 85      */
 86     _initRequestParams: function() {
 87         this._requestParameters = this.getViewState();
 88         for (var key in this._passThrough) {
 89             this._requestParameters.append(key, this._passThrough[key]);
 90         }
 91     },
 92 
 93     /**
 94      * starts the asynchronous xhr request
 95      */
 96     _startXHR: function() {
 97         this._preCreateXHR();
 98         this._xhr = myfaces._impl.core._Runtime.getXHRObject();
 99         this._postCreateXHR();
100 
101         var targetURL;
102         if (typeof this._sourceForm.elements["javax.faces.encodedURL"] == 'undefined') {
103             targetURL = this._sourceForm.action;
104         } else {
105             targetURL = this._sourceForm.elements["javax.faces.encodedURL"].value;
106         }
107 
108         this._xhr.open(this._ajaxType, targetURL +
109                 ((this._ajaxType == "GET") ? "?" + this._requestParameters.makeFinal() : "")
110                 , true);
111 
112         var contentType = this._contentType;
113         if (this._encoding) {
114             contentType = contentType + "; charset:" + this._encoding;
115         }
116 
117         this._xhr.setRequestHeader(this._CONTENT_TYPE, this._contentType);
118         this._xhr.setRequestHeader(this._HEAD_FACES_REQ, this._VAL_AJAX);
119 
120         this._xhr.onreadystatechange = this._Lang.hitch(this, this.callback);
121         var _Impl = this._getImpl();
122         _Impl.sendEvent(this._xhr, this._context, _Impl.BEGIN);
123 
124         this._preSend();
125 
126         try {
127             this._xhr.send((this._ajaxType != "GET") ? this._requestParameters.makeFinal() : null);
128         } finally {
129             this._postSend();
130         }
131     },
132 
133 
134 
135     /**
136      * starts the timeout
137      * which is able to terminate the xhr upfront early
138      */
139     _startTimeout: function() {
140         if (this._timeout && this._onTimeout) {
141             var _req = this._xhr;
142             var _context = this._context;
143             if (this._timeoutId) {
144                 window.clearTimeout(this._timeoutId);
145                 this._timeoutId = null;
146             }
147             this._timeoutId = window.setTimeout(
148                 //we unify the api, there must be always a request passed to the external function
149                 //and always a context, no matter what
150                     this._Lang.hitch(this,
151                             function() {
152                                 //the hitch has to be done due to the setTimeout refocusing the scope of this
153                                 //to window
154                                 try {
155                                     _req.onreadystatechange = function() {
156                                     };
157 
158                                     //to avoid malformed whatever, we have
159                                     //the timeout covered already on the _onTimeout function
160                                     _req.abort();
161                                     this._onTimeout(_req, _context);
162                                 } catch (e) {
163                                     alert(e);
164                                 } finally {
165                                 }
166                             })
167                     , this._timeout);
168         }
169     },
170 
171     /**
172      * Callback method to process the Ajax response
173      * triggered by RequestQueue
174      */
175     callback : function() {
176 
177         try {
178             var _Impl = this._getImpl();
179 
180             if (this._xhr.readyState == this._READY_STATE_DONE) {
181                 if (this._timeoutId) {
182                     //normally the timeout should not cause anything anymore
183                     //but just to make sure
184                     window.clearTimeout(this._timeoutId);
185                     this._timeoutId = null;
186                 }
187                 this._onDone(this);
188                 if (this._xhr.status >= this._STATUS_OK_MINOR && this._xhr.status < this._STATUS_OK_MAJOR) {
189                     this._onSuccess();
190                 } else {
191                     this._onError();
192                 }
193             }
194         } catch (e) {
195             this._onException(this._xhr, this._context, "myfaces._impl.xhrCore._AjaxRequest", "callback", e);
196         } finally {
197             //final cleanup to terminate everything
198             this._Lang.clearExceptionProcessed();
199 
200             //this._context.source;
201             if (this._xhr.readyState == this._READY_STATE_DONE) {
202                 this._callSuper("_finalize");
203             }
204 
205         }
206     },
207 
208 
209 
210 
211 
212     /*
213      * various lifecycle callbacks which can be used by differing AjaxRequest impls
214      * (namely level 1.5 (Mozilla XHR) and level 2 (html5 xhr) to run special initialisation code
215      **/
216     _preCreateXHR : function() {
217         //called after the xhr object has been created
218     },
219 
220     _postCreateXHR : function() {
221         //called after the xhr object has been created
222     },
223     _preSend : function() {
224         //called before the xhr object is sent
225     },
226     _postSend : function() {
227         //called after the xhr object is sent for cleanup purposes
228     }
229 
230 });
231 
232