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 /**
 19  * @class
 20  * @name Xhr1
 21  * @memberOf myfaces._impl.xhrCore.engine
 22  * @extends myfaces._impl.xhrCore.engine.BaseRequest
 23  * @description
 24  *
 25  * wrapper for an xhr level1 object with all its differences
 26  * it emulates the xhr level2 api which is way simpler than the level1 api
 27  */
 28 
 29 _MF_CLS(_PFX_XHR + "engine.Xhr1", myfaces._impl.xhrCore.engine.BaseRequest, /** @lends myfaces._impl.xhrCore.engine.Xhr1.prototype */ {
 30 
 31     _xhrObject: null,
 32     _timeoutTimer: null,
 33 
 34     constructor_: function(params) {
 35         //the constructor is empty due to the original xhr object not having anything
 36 
 37         this._callSuper("constructor_", params);
 38         this._initDefaultFinalizableFields();
 39 
 40         this._XHRConst = myfaces._impl.xhrCore.engine.XhrConst;
 41         this._Lang.applyArgs(this, params);
 42     },
 43 
 44     // void open(DOMString method, DOMString url, boolean async);
 45     open: function(method, url, async) {
 46 
 47         var xhr = this._xhrObject;
 48         xhr.onreadystatechange = this._Lang.hitch(this, this.onreadystatechange);
 49         this.method = method || this.method;
 50         this.url = url || this.url;
 51         this.async = ('undefined' != typeof async) ? async : this.async;
 52         xhr.open(this.method, this.url, this.async);
 53     },
 54 
 55     send: function(formData) {
 56 
 57         var myevt = {};
 58 
 59         this._addProgressAttributes(myevt, 20, 100);
 60         this.onloadstart(myevt);
 61         this.onprogress(myevt);
 62         this._startTimeout();
 63         this._xhrObject.send(formData);
 64     },
 65 
 66     setRequestHeader: function(key, value) {
 67         this._xhrObject.setRequestHeader(key, value);
 68     },
 69 
 70     abort: function() {
 71 
 72         this._xhrObject.abort();
 73         this.onabort({});
 74     },
 75 
 76     _addProgressAttributes: function(evt, percent, total) {
 77         //http://www.w3.org/TR/progress-events/#progressevent
 78         evt.lengthComputable = true;
 79         evt.loaded = percent;
 80         evt.total = total;
 81 
 82     },
 83 
 84     onreadystatechange: function(evt) {
 85         var myevt = evt || {};
 86         //we have to simulate the attributes as well
 87         var xhr = this._xhrObject;
 88         var XHRConst = this._XHRConst;
 89         try {
 90         this.readyState = xhr.readyState;
 91         this.status = ""+xhr.status;
 92         } catch(e) {
 93             //IE 6 has an internal error
 94         }
 95 
 96         switch (this.readyState) {
 97 
 98             case  XHRConst.READY_STATE_OPENED:
 99                 this._addProgressAttributes(myevt, 10, 100);
100 
101                 this.onprogress(myevt);
102                 break;
103 
104             case XHRConst.READY_STATE_HEADERS_RECEIVED:
105                 this._addProgressAttributes(myevt, 25, 100);
106 
107                 this.onprogress(myevt);
108                 break;
109 
110             case XHRConst.READY_STATE_LOADING:
111                 if (this._loadingCalled) break;
112                 this._loadingCalled = true;
113                 this._addProgressAttributes(myevt, 50, 100);
114 
115                 this.onprogress(myevt);
116                 break;
117 
118             case XHRConst.READY_STATE_DONE:
119                 this._addProgressAttributes(myevt, 100, 100);
120                 //xhr level1 does not have timeout handler
121                 if (this._timeoutTimer) {
122                     //normally the timeout should not cause anything anymore
123                     //but just to make sure
124                     window.clearTimeout(this._timeoutTimer);
125                     this._timeoutTimer = null;
126                 }
127                 this._transferRequestValues();
128                 this.onprogress(myevt);
129                 try {
130                     var status = xhr.status;
131                     if (status >= XHRConst.STATUS_OK_MINOR && status < XHRConst.STATUS_OK_MAJOR) {
132                         this.onload(myevt);
133                     } else {
134                         myevt.type = "error";
135                         this.onerror(myevt);
136                     }
137                 } finally {
138 					//remove for xhr level2 support
139                     this.onloadend(myevt);
140                 }
141         }
142     },
143 
144     _transferRequestValues: function() {
145         //this._Lang.mixMaps(this, this._xhrObject, true, null,
146         //        {responseText:1,responseXML:1,status:1,statusText:1,response:1});
147         var UDEF = "undefined";
148         var xhr = this._xhrObject;
149 
150         this.responseText = (UDEF != typeof xhr.responseText)?xhr.responseText: null;
151         this.responseXML = (UDEF != typeof xhr.responseXML)?xhr.responseXML: null;
152         this.status = (UDEF != typeof xhr.status)?xhr.status: null;
153         this.statusText = (UDEF != typeof xhr.statusText)?xhr.statusText: null;
154         this.response = (UDEF != typeof xhr.response)?xhr.response: null;
155     },
156 
157     _startTimeout: function() {
158         if (this.timeout == 0) return;
159 
160         var xhr = this._xhrObject;
161         //some browsers have timeouts in their xhr level 1.x objects implemented
162         //we leverage them whenever they exist
163         try {
164             if ('undefined' != typeof xhr.timeout) {
165                 xhr.timeout = this.timeout;
166                 xhr.ontimeout = this.ontimeout;
167                 return;
168             }
169         } catch (e) {
170             //firefox 12 has a bug here
171         }
172 
173 
174         this._timeoutTimer = setTimeout(this._Lang.hitch(this, function() {
175             if (xhr.readyState != this._XHRConst.READY_STATE_DONE) {
176 
177                 xhr.onreadystatechange = function() {
178                 };
179                 clearTimeout(this._timeoutTimer);
180                 xhr.abort();
181                 this.ontimeout({});
182             }
183         }), this.timeout);
184     },
185 
186     getXHRObject: function() {
187         return this._xhrObject;
188     }
189 
190 
191 });