source: Dev/trunk/src/client/dojo/request/xhr.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 8.3 KB
Line 
1define([
2        '../errors/RequestError',
3        './watch',
4        './handlers',
5        './util',
6        '../has'/*=====,
7        '../request',
8        '../_base/declare' =====*/
9], function(RequestError, watch, handlers, util, has/*=====, request, declare =====*/){
10        has.add('native-xhr', function(){
11                // if true, the environment has a native XHR implementation
12                return typeof XMLHttpRequest !== 'undefined';
13        });
14        has.add('dojo-force-activex-xhr', function(){
15                return has('activex') && !document.addEventListener && window.location.protocol === 'file:';
16        });
17
18        has.add('native-xhr2', function(){
19                if(!has('native-xhr')){ return; }
20                var x = new XMLHttpRequest();
21                return typeof x['addEventListener'] !== 'undefined' &&
22                        (typeof opera === 'undefined' || typeof x['upload'] !== 'undefined');
23        });
24
25        has.add('native-formdata', function(){
26                // if true, the environment has a native FormData implementation
27                return typeof FormData === 'function';
28        });
29
30        function handleResponse(response, error){
31                var _xhr = response.xhr;
32                response.status = response.xhr.status;
33                response.text = _xhr.responseText;
34
35                if(response.options.handleAs === 'xml'){
36                        response.data = _xhr.responseXML;
37                }
38
39                if(!error){
40                        try{
41                                handlers(response);
42                        }catch(e){
43                                error = e;
44                        }
45                }
46
47                if(error){
48                        this.reject(error);
49                }else if(util.checkStatus(_xhr.status)){
50                        this.resolve(response);
51                }else{
52                        error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status, response);
53
54                        this.reject(error);
55                }
56        }
57
58        var isValid, isReady, addListeners, cancel;
59        if(has('native-xhr2')){
60                // Any platform with XHR2 will only use the watch mechanism for timeout.
61
62                isValid = function(response){
63                        // summary:
64                        //              Check to see if the request should be taken out of the watch queue
65                        return !this.isFulfilled();
66                };
67                cancel = function(dfd, response){
68                        // summary:
69                        //              Canceler for deferred
70                        response.xhr.abort();
71                };
72                addListeners = function(_xhr, dfd, response){
73                        // summary:
74                        //              Adds event listeners to the XMLHttpRequest object
75                        function onLoad(evt){
76                                dfd.handleResponse(response);
77                        }
78                        function onError(evt){
79                                var _xhr = evt.target;
80                                var error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status, response);
81                                dfd.handleResponse(response, error);
82                        }
83
84                        function onProgress(evt){
85                                if(evt.lengthComputable){
86                                        response.loaded = evt.loaded;
87                                        response.total = evt.total;
88                                        dfd.progress(response);
89                                }
90                        }
91
92                        _xhr.addEventListener('load', onLoad, false);
93                        _xhr.addEventListener('error', onError, false);
94                        _xhr.addEventListener('progress', onProgress, false);
95
96                        return function(){
97                                _xhr.removeEventListener('load', onLoad, false);
98                                _xhr.removeEventListener('error', onError, false);
99                                _xhr.removeEventListener('progress', onProgress, false);
100                                _xhr = null;
101                        };
102                };
103        }else{
104                isValid = function(response){
105                        return response.xhr.readyState; //boolean
106                };
107                isReady = function(response){
108                        return 4 === response.xhr.readyState; //boolean
109                };
110                cancel = function(dfd, response){
111                        // summary:
112                        //              canceller function for util.deferred call.
113                        var xhr = response.xhr;
114                        var _at = typeof xhr.abort;
115                        if(_at === 'function' || _at === 'object' || _at === 'unknown'){
116                                xhr.abort();
117                        }
118                };
119        }
120
121        function getHeader(headerName){
122                return this.xhr.getResponseHeader(headerName);
123        }
124
125        var undefined,
126                defaultOptions = {
127                        data: null,
128                        query: null,
129                        sync: false,
130                        method: 'GET'
131                };
132        function xhr(url, options, returnDeferred){
133                var response = util.parseArgs(
134                        url,
135                        util.deepCreate(defaultOptions, options),
136                        has('native-formdata') && options && options.data && options.data instanceof FormData
137                );
138                url = response.url;
139                options = response.options;
140
141                var remover,
142                        last = function(){
143                                remover && remover();
144                        };
145
146                //Make the Deferred object for this xhr request.
147                var dfd = util.deferred(
148                        response,
149                        cancel,
150                        isValid,
151                        isReady,
152                        handleResponse,
153                        last
154                );
155                var _xhr = response.xhr = xhr._create();
156
157                if(!_xhr){
158                        // If XHR factory somehow returns nothings,
159                        // cancel the deferred.
160                        dfd.cancel(new RequestError('XHR was not created'));
161                        return returnDeferred ? dfd : dfd.promise;
162                }
163
164                response.getHeader = getHeader;
165
166                if(addListeners){
167                        remover = addListeners(_xhr, dfd, response);
168                }
169
170                var data = options.data,
171                        async = !options.sync,
172                        method = options.method;
173
174                try{
175                        // IE6 won't let you call apply() on the native function.
176                        _xhr.open(method, url, async, options.user || undefined, options.password || undefined);
177
178                        if(options.withCredentials){
179                                _xhr.withCredentials = options.withCredentials;
180                        }
181
182                        var headers = options.headers,
183                                contentType = 'application/x-www-form-urlencoded';
184                        if(headers){
185                                for(var hdr in headers){
186                                        if(hdr.toLowerCase() === 'content-type'){
187                                                contentType = headers[hdr];
188                                        }else if(headers[hdr]){
189                                                //Only add header if it has a value. This allows for instance, skipping
190                                                //insertion of X-Requested-With by specifying empty value.
191                                                _xhr.setRequestHeader(hdr, headers[hdr]);
192                                        }
193                                }
194                        }
195
196                        if(contentType && contentType !== false){
197                                _xhr.setRequestHeader('Content-Type', contentType);
198                        }
199                        if(!headers || !('X-Requested-With' in headers)){
200                                _xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
201                        }
202
203                        if(util.notify){
204                                util.notify.emit('send', response, dfd.promise.cancel);
205                        }
206                        _xhr.send(data);
207                }catch(e){
208                        dfd.reject(e);
209                }
210
211                watch(dfd);
212                _xhr = null;
213
214                return returnDeferred ? dfd : dfd.promise;
215        }
216
217        /*=====
218        xhr = function(url, options){
219                // summary:
220                //              Sends a request using XMLHttpRequest with the given URL and options.
221                // url: String
222                //              URL to request
223                // options: dojo/request/xhr.__Options?
224                //              Options for the request.
225                // returns: dojo/request.__Promise
226        };
227        xhr.__BaseOptions = declare(request.__BaseOptions, {
228                // sync: Boolean?
229                //              Whether to make a synchronous request or not. Default
230                //              is `false` (asynchronous).
231                // data: String|Object|FormData?
232                //              Data to transfer. This is ignored for GET and DELETE
233                //              requests.
234                // headers: Object?
235                //              Headers to use for the request.
236                // user: String?
237                //              Username to use during the request.
238                // password: String?
239                //              Password to use during the request.
240                // withCredentials: Boolean?
241                //              For cross-site requests, whether to send credentials
242                //              or not.
243        });
244        xhr.__MethodOptions = declare(null, {
245                // method: String?
246                //              The HTTP method to use to make the request. Must be
247                //              uppercase. Default is `"GET"`.
248        });
249        xhr.__Options = declare([xhr.__BaseOptions, xhr.__MethodOptions]);
250
251        xhr.get = function(url, options){
252                // summary:
253                //              Send an HTTP GET request using XMLHttpRequest with the given URL and options.
254                // url: String
255                //              URL to request
256                // options: dojo/request/xhr.__BaseOptions?
257                //              Options for the request.
258                // returns: dojo/request.__Promise
259        };
260        xhr.post = function(url, options){
261                // summary:
262                //              Send an HTTP POST request using XMLHttpRequest with the given URL and options.
263                // url: String
264                //              URL to request
265                // options: dojo/request/xhr.__BaseOptions?
266                //              Options for the request.
267                // returns: dojo/request.__Promise
268        };
269        xhr.put = function(url, options){
270                // summary:
271                //              Send an HTTP PUT request using XMLHttpRequest with the given URL and options.
272                // url: String
273                //              URL to request
274                // options: dojo/request/xhr.__BaseOptions?
275                //              Options for the request.
276                // returns: dojo/request.__Promise
277        };
278        xhr.del = function(url, options){
279                // summary:
280                //              Send an HTTP DELETE request using XMLHttpRequest with the given URL and options.
281                // url: String
282                //              URL to request
283                // options: dojo/request/xhr.__BaseOptions?
284                //              Options for the request.
285                // returns: dojo/request.__Promise
286        };
287        =====*/
288        xhr._create = function(){
289                // summary:
290                //              does the work of portably generating a new XMLHTTPRequest object.
291                throw new Error('XMLHTTP not available');
292        };
293        if(has('native-xhr') && !has('dojo-force-activex-xhr')){
294                xhr._create = function(){
295                        return new XMLHttpRequest();
296                };
297        }else if(has('activex')){
298                try{
299                        new ActiveXObject('Msxml2.XMLHTTP');
300                        xhr._create = function(){
301                                return new ActiveXObject('Msxml2.XMLHTTP');
302                        };
303                }catch(e){
304                        try{
305                                new ActiveXObject('Microsoft.XMLHTTP');
306                                xhr._create = function(){
307                                        return new ActiveXObject('Microsoft.XMLHTTP');
308                                };
309                        }catch(e){}
310                }
311        }
312
313        util.addCommonMethods(xhr);
314
315        return xhr;
316});
Note: See TracBrowser for help on using the repository browser.