]> git.proxmox.com Git - extjs.git/blame - extjs/packages/core/src/data/Connection.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / core / src / data / Connection.js
CommitLineData
6527f429
DM
1/**\r
2 * The Connection class encapsulates a connection to the page's originating domain, allowing requests to be made either\r
3 * to a configured URL, or to a URL specified at request time.\r
4 *\r
5 * Requests made by this class are asynchronous, and will return immediately. No data from the server will be available\r
6 * to the statement immediately following the {@link #request} call. To process returned data, use a success callback\r
7 * in the request options object, or an {@link #requestcomplete event listener}.\r
8 *\r
9 * # File Uploads\r
10 *\r
11 * File uploads are not performed using normal "Ajax" techniques, that is they are not performed using XMLHttpRequests.\r
12 * Instead the form is submitted in the standard manner with the DOM <form> element temporarily modified to have its\r
13 * target set to refer to a dynamically generated, hidden <iframe> which is inserted into the document but removed\r
14 * after the return data has been gathered.\r
15 *\r
16 * The server response is parsed by the browser to create the document for the IFRAME. If the server is using JSON to\r
17 * send the return object, then the Content-Type header must be set to "text/html" in order to tell the browser to\r
18 * insert the text unchanged into the document body.\r
19 *\r
20 * Characters which are significant to an HTML parser must be sent as HTML entities, so encode `<` as `&lt;`, `&` as\r
21 * `&amp;` etc.\r
22 *\r
23 * The response text is retrieved from the document, and a fake XMLHttpRequest object is created containing a\r
24 * responseText property in order to conform to the requirements of event handlers and callbacks.\r
25 *\r
26 * Be aware that file upload packets are sent with the content type multipart/form and some server technologies\r
27 * (notably JEE) may require some custom processing in order to retrieve parameter names and parameter values from the\r
28 * packet content.\r
29 *\r
30 * Also note that it's not possible to check the response code of the hidden iframe, so the success handler will ALWAYS fire.\r
31 *\r
32 * # Binary Posts\r
33 *\r
34 * The class supports posting binary data to the server by using native browser capabilities, or a flash polyfill plugin in browsers that do not support native binary posting (e.g. Internet Explorer version 9 or less). A number of limitations exist when the polyfill is used:\r
35 *\r
36 * - Only asynchronous connections are supported.\r
37 * - Only the POST method can be used.\r
38 * - The return data can only be binary for now. Set the {@link Ext.data.Connection#binary binary} parameter to <tt>true</tt>.\r
39 * - Only the 0, 1 and 4 (complete) readyState values will be reported to listeners.\r
40 * - The flash object will be injected at the bottom of the document and should be invisible.\r
41 * - Important: See note about packaing the flash plugin with the app in the documenetation of {@link Ext.data.flash.BinaryXhr BinaryXhr}.\r
42 *\r
43 */\r
44Ext.define('Ext.data.Connection', {\r
45 mixins: {\r
46 observable: 'Ext.mixin.Observable'\r
47 },\r
48\r
49 requires: [\r
50 'Ext.data.request.Ajax',\r
51 'Ext.data.request.Form',\r
52 'Ext.data.flash.BinaryXhr',\r
53 'Ext.Deferred'\r
54 ],\r
55\r
56 statics: {\r
57 requestId: 0\r
58 },\r
59\r
60 enctypeRe: /multipart\/form-data/i,\r
61\r
62 config: {\r
63 /**\r
64 * @cfg {String} url\r
65 * The URL for this connection.\r
66 */\r
67 url: null,\r
68\r
69 /**\r
70 * @cfg {Boolean} async\r
71 * `true` if this request should run asynchronously. Setting this to `false` should generally\r
72 * be avoided, since it will cause the UI to be blocked, the user won't be able to interact\r
73 * with the browser until the request completes.\r
74 */\r
75 async: true,\r
76\r
77 /**\r
78 * @cfg {String} username\r
79 * The username to pass when using {@link #withCredentials}.\r
80 */\r
81 username: '',\r
82\r
83 /**\r
84 * @cfg {String} password\r
85 * The password to pass when using {@link #withCredentials}.\r
86 */\r
87 password: '',\r
88\r
89 /**\r
90 * @cfg {Boolean} disableCaching\r
91 * True to add a unique cache-buster param to GET requests.\r
92 */\r
93 disableCaching: true,\r
94\r
95 /**\r
96 * @cfg {Boolean} withCredentials\r
97 * True to set `withCredentials = true` on the XHR object\r
98 */\r
99 withCredentials: false,\r
100\r
101 /**\r
102 * @cfg {Boolean} binary\r
103 * True if the response should be treated as binary data. If true, the binary\r
104 * data will be accessible as a "responseBytes" property on the response object.\r
105 */\r
106 binary: false,\r
107\r
108 /**\r
109 * @cfg {Boolean} cors\r
110 * True to enable CORS support on the XHR object. Currently the only effect of this option\r
111 * is to use the XDomainRequest object instead of XMLHttpRequest if the browser is IE8 or above.\r
112 */\r
113 cors: false,\r
114\r
115 isXdr: false,\r
116\r
117 defaultXdrContentType: 'text/plain',\r
118\r
119 /**\r
120 * @cfg {String} disableCachingParam\r
121 * Change the parameter which is sent went disabling caching through a cache buster.\r
122 */\r
123 disableCachingParam: '_dc',\r
124\r
125 /**\r
126 * @cfg {Number} [timeout=30000] The timeout in milliseconds to be used for \r
127 * requests. \r
128 * Defaults to 30000 milliseconds (30 seconds).\r
129 * \r
130 * When a request fails due to timeout the XMLHttpRequest response object will \r
131 * contain:\r
132 * \r
133 * timedout: true\r
134 */\r
135 timeout: 30000,\r
136\r
137 /**\r
138 * @cfg {Object} [extraParams] Any parameters to be appended to the request.\r
139 */\r
140 extraParams: null,\r
141\r
142 /**\r
143 * @cfg {Boolean} [autoAbort=false]\r
144 * Whether this request should abort any pending requests.\r
145 */\r
146 autoAbort: false,\r
147\r
148 /**\r
149 * @cfg {String} method\r
150 * The default HTTP method to be used for requests.\r
151 *\r
152 * If not set, but {@link #request} params are present, POST will be used;\r
153 * otherwise, GET will be used.\r
154 */\r
155 method: null,\r
156\r
157 /**\r
158 * @cfg {Object} defaultHeaders\r
159 * An object containing request headers which are added to each request made by this object.\r
160 */\r
161 defaultHeaders: null,\r
162\r
163 /**\r
164 * @cfg {String} defaultPostHeader\r
165 * The default header to be sent out with any post request.\r
166 */\r
167 defaultPostHeader : 'application/x-www-form-urlencoded; charset=UTF-8',\r
168\r
169 /**\r
170 * @cfg {Boolean} useDefaultXhrHeader\r
171 * `true` to send the {@link #defaultXhrHeader} along with any request.\r
172 */\r
173 useDefaultXhrHeader : true,\r
174\r
175 /**\r
176 * @cfg {String}\r
177 * The header to send with Ajax requests. Also see {@link #useDefaultXhrHeader}.\r
178 */\r
179 defaultXhrHeader : 'XMLHttpRequest'\r
180 },\r
181\r
182 /**\r
183 * @event beforerequest\r
184 * @preventable\r
185 * Fires before a network request is made to retrieve a data object.\r
186 * @param {Ext.data.Connection} conn This Connection object.\r
187 * @param {Object} options The options config object passed to the {@link #request} method.\r
188 */\r
189 \r
190 /**\r
191 * @event requestcomplete\r
192 * Fires if the request was successfully completed.\r
193 * @param {Ext.data.Connection} conn This Connection object.\r
194 * @param {Object} response The XHR object containing the response data.\r
195 * See [The XMLHttpRequest Object](http://www.w3.org/TR/XMLHttpRequest/) for details.\r
196 * @param {Object} options The options config object passed to the {@link #request} method.\r
197 */\r
198 \r
199 /**\r
200 * @event requestexception\r
201 * Fires if an error HTTP status was returned from the server. This event may also\r
202 * be listened to in the event that a request has timed out or has been aborted.\r
203 * See [HTTP Status Code Definitions](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)\r
204 * for details of HTTP status codes.\r
205 * @param {Ext.data.Connection} conn This Connection object.\r
206 * @param {Object} response The XHR object containing the response data.\r
207 * See [The XMLHttpRequest Object](http://www.w3.org/TR/XMLHttpRequest/) for details.\r
208 * @param {Object} options The options config object passed to the {@link #request} method.\r
209 */\r
210 \r
211 constructor: function(config) {\r
212 // Will call initConfig\r
213 this.mixins.observable.constructor.call(this, config);\r
214 \r
215 this.requests = {};\r
216 },\r
217\r
218 /**\r
219 * Sends an HTTP (Ajax) request to a remote server.\r
220 *\r
221 * **Important:** Ajax server requests are asynchronous, and this call will\r
222 * return before the response has been received.\r
223 *\r
224 * Instead, process any returned data using a promise:\r
225 *\r
226 * Ext.Ajax.request({\r
227 * url: 'ajax_demo/sample.json'\r
228 * }).then(function(response, opts) {\r
229 * var obj = Ext.decode(response.responseText);\r
230 * console.dir(obj);\r
231 * },\r
232 * function(response, opts) {\r
233 * console.log('server-side failure with status code ' + response.status);\r
234 * });\r
235 *\r
236 * Or in callback functions:\r
237 *\r
238 * Ext.Ajax.request({\r
239 * url: 'ajax_demo/sample.json',\r
240 *\r
241 * success: function(response, opts) {\r
242 * var obj = Ext.decode(response.responseText);\r
243 * console.dir(obj);\r
244 * },\r
245 *\r
246 * failure: function(response, opts) {\r
247 * console.log('server-side failure with status code ' + response.status);\r
248 * }\r
249 * });\r
250 *\r
251 * To execute a callback function in the correct scope, use the `scope` option.\r
252 *\r
253 * @param {Object} options An object which may contain the following properties:\r
254 *\r
255 * (The options object may also contain any other property which might be needed to perform\r
256 * postprocessing in a callback because it is passed to callback functions.)\r
257 *\r
258 * @param {String/Function} options.url The URL to which to send the request, or a function\r
259 * to call which returns a URL string. The scope of the function is specified by the `scope` option.\r
260 * Defaults to the configured `url`.\r
261 *\r
262 * @param {Boolean} options.async `true` if this request should run asynchronously.\r
263 * Setting this to `false` should generally be avoided, since it will cause the UI to be\r
264 * blocked, the user won't be able to interact with the browser until the request completes.\r
265 * Defaults to `true`.\r
266 *\r
267 * @param {Object/String/Function} options.params An object containing properties which are\r
268 * used as parameters to the request, a url encoded string or a function to call to get either. The scope\r
269 * of the function is specified by the `scope` option.\r
270 *\r
271 * @param {String} options.method The HTTP method to use\r
272 * for the request. Defaults to the configured method, or if no method was configured,\r
273 * "GET" if no parameters are being sent, and "POST" if parameters are being sent. Note that\r
274 * the method name is case-sensitive and should be all caps.\r
275 *\r
276 * @param {Function} options.callback The function to be called upon receipt of the HTTP response.\r
277 * The callback is called regardless of success or failure and is passed the following parameters:\r
278 * @param {Object} options.callback.options The parameter to the request call.\r
279 * @param {Boolean} options.callback.success True if the request succeeded.\r
280 * @param {Object} options.callback.response The XMLHttpRequest object containing the response data.\r
281 * See [www.w3.org/TR/XMLHttpRequest/](http://www.w3.org/TR/XMLHttpRequest/) for details about\r
282 * accessing elements of the response.\r
283 *\r
284 * @param {Function} options.success The function to be called upon success of the request.\r
285 * The callback is passed the following parameters:\r
286 * @param {Object} options.success.response The XMLHttpRequest object containing the response data.\r
287 * @param {Object} options.success.options The parameter to the request call.\r
288 *\r
289 * @param {Function} options.failure The function to be called upon failure of the request.\r
290 * The callback is passed the following parameters:\r
291 * @param {Object} options.failure.response The XMLHttpRequest object containing the response data.\r
292 * @param {Object} options.failure.options The parameter to the request call.\r
293 *\r
294 * @param {Object} options.scope The scope in which to execute the callbacks: The "this" object for\r
295 * the callback function. If the `url`, or `params` options were specified as functions from which to\r
296 * draw values, then this also serves as the scope for those function calls. Defaults to the browser\r
297 * window.\r
298 *\r
299 * @param {Number} options.timeout The timeout in milliseconds to be used for this \r
300 * request. \r
301 * Defaults to 30000 milliseconds (30 seconds).\r
302 * \r
303 * When a request fails due to timeout the XMLHttpRequest response object will \r
304 * contain:\r
305 * \r
306 * timedout: true\r
307 *\r
308 * @param {Ext.Element/HTMLElement/String} options.form The `<form>` Element or the id of the `<form>`\r
309 * to pull parameters from.\r
310 *\r
311 * @param {Boolean} options.isUpload **Only meaningful when used with the `form` option.**\r
312 *\r
313 * True if the form object is a file upload (will be set automatically if the form was configured\r
314 * with **`enctype`** `"multipart/form-data"`).\r
315 *\r
316 * File uploads are not performed using normal "Ajax" techniques, that is they are **not**\r
317 * performed using XMLHttpRequests. Instead the form is submitted in the standard manner with the\r
318 * DOM `<form>` element temporarily modified to have its [target][] set to refer to a dynamically\r
319 * generated, hidden `<iframe>` which is inserted into the document but removed after the return data\r
320 * has been gathered.\r
321 *\r
322 * The server response is parsed by the browser to create the document for the IFRAME. If the\r
323 * server is using JSON to send the return object, then the [Content-Type][] header must be set to\r
324 * "text/html" in order to tell the browser to insert the text unchanged into the document body.\r
325 *\r
326 * The response text is retrieved from the document, and a fake XMLHttpRequest object is created\r
327 * containing a `responseText` property in order to conform to the requirements of event handlers\r
328 * and callbacks.\r
329 *\r
330 * Be aware that file upload packets are sent with the content type [multipart/form][] and some server\r
331 * technologies (notably JEE) may require some custom processing in order to retrieve parameter names\r
332 * and parameter values from the packet content.\r
333 *\r
334 * [target]: http://www.w3.org/TR/REC-html40/present/frames.html#adef-target\r
335 * [Content-Type]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17\r
336 * [multipart/form]: http://www.faqs.org/rfcs/rfc2388.html\r
337 *\r
338 * @param {Object} options.headers Request headers to set for the request.\r
339 * The XHR will attempt to set an appropriate Content-Type based on the params/data passed\r
340 * to the request. To prevent this, setting the Content-Type header to `null` or `undefined`\r
341 * will not attempt to set any Content-Type and it will be left to the browser.\r
342 *\r
343 * @param {Object} options.xmlData XML document to use for the post. Note: This will be used instead\r
344 * of params for the post data. Any params will be appended to the URL.\r
345 *\r
346 * @param {Object/String} options.jsonData JSON data to use as the post. Note: This will be used\r
347 * instead of params for the post data. Any params will be appended to the URL.\r
348 *\r
349 * @param {String} options.rawData A raw string to use as the post. Note: This will be used\r
350 * instead of params for the post data. Any params will be appended to the URL.\r
351 *\r
352 * @param {Array} options.binaryData An array of bytes to submit in binary form. Any params will be appended to the URL. If binaryData is present, you must set {@link Ext.data.Connection#binary binary} to <tt>true</tt> and options.method to <tt>POST</tt>.\r
353 *\r
354 * @param {Boolean} options.disableCaching True to add a unique cache-buster param to GET requests.\r
355 *\r
356 * @param {Boolean} options.withCredentials True to add the withCredentials property to the XHR object\r
357 *\r
358 * @param {String} options.username The username to pass when using `withCredentials`.\r
359 *\r
360 * @param {String} options.password The password to pass when using `withCredentials`.\r
361 *\r
362 * @param {Boolean} options.binary True if the response should be treated as binary data. If true, the binary\r
363 * data will be accessible as a "responseBytes" property on the response object.\r
364 *\r
365 * @return {Ext.data.request.Base} The request object. This may be used to abort the\r
366 * request.\r
367 */\r
368 request: function(options) {\r
369 options = options || {};\r
370 \r
371 var me = this,\r
372 requestOptions, request;\r
373 \r
374 if (me.fireEvent('beforerequest', me, options) !== false) {\r
375 requestOptions = me.setOptions(options, options.scope || Ext.global);\r
376 \r
377 request = me.createRequest(options, requestOptions);\r
378 \r
379 return request.start(requestOptions.data);\r
380 }\r
381\r
382 Ext.callback(options.callback, options.scope, [options, undefined, undefined]);\r
383\r
384 return Ext.Deferred.rejected([options, undefined, undefined]);\r
385 },\r
386\r
387 createRequest: function(options, requestOptions) {\r
388 var me = this,\r
389 type = options.type || requestOptions.type,\r
390 request;\r
391 \r
392 // If request type is not specified we have to deduce it\r
393 if (!type) {\r
394 type = me.isFormUpload(options) ? 'form' : 'ajax';\r
395 }\r
396 \r
397 // if autoabort is set, cancel the current transactions\r
398 if (options.autoAbort || me.getAutoAbort()) {\r
399 me.abort();\r
400 }\r
401 \r
402 // It is possible for the original options object to be mutated if somebody\r
403 // had overridden Connection.setOptions method; it is also possible that such\r
404 // override would do a sensible thing and mutate outgoing requestOptions instead.\r
405 // So we have to pass *both* to the Request constructor, along with the set\r
406 // of defaults potentially set on the Connection instance.\r
407 // If it looks ridiculous, that's because it is; things we have to do for\r
408 // backward compatibility...\r
409 request = Ext.Factory.request({\r
410 type: type,\r
411 owner: me,\r
412 options: options,\r
413 requestOptions: requestOptions,\r
414 ownerConfig: me.getConfig()\r
415 });\r
416 \r
417 me.requests[request.id] = request;\r
418 me.latestId = request.id;\r
419 \r
420 return request;\r
421 },\r
422\r
423 /**\r
424 * Detects whether the form is intended to be used for an upload.\r
425 * @private\r
426 */\r
427 isFormUpload: function(options) {\r
428 var form = this.getForm(options);\r
429 \r
430 if (form) {\r
431 return options.isUpload || this.enctypeRe.test(form.getAttribute('enctype'));\r
432 }\r
433 \r
434 return false;\r
435 },\r
436\r
437 /**\r
438 * Gets the form object from options.\r
439 * @private\r
440 * @param {Object} options The request options\r
441 * @return {HTMLElement} The form, null if not passed\r
442 */\r
443 getForm: function(options) {\r
444 return Ext.getDom(options.form);\r
445 },\r
446\r
447 /**\r
448 * Sets various options such as the url, params for the request\r
449 * @param {Object} options The initial options\r
450 * @param {Object} scope The scope to execute in\r
451 * @return {Object} The params for the request\r
452 */\r
453 setOptions: function(options, scope) {\r
454 var me = this,\r
455 params = options.params || {},\r
456 extraParams = me.getExtraParams(),\r
457 urlParams = options.urlParams,\r
458 url = options.url || me.getUrl(),\r
459 cors = options.cors,\r
460 jsonData = options.jsonData,\r
461 method,\r
462 disableCache,\r
463 data;\r
464\r
465 if (cors !== undefined) {\r
466 me.setCors(cors);\r
467 }\r
468\r
469 // allow params to be a method that returns the params object\r
470 if (Ext.isFunction(params)) {\r
471 params = params.call(scope, options);\r
472 }\r
473\r
474 // allow url to be a method that returns the actual url\r
475 if (Ext.isFunction(url)) {\r
476 url = url.call(scope, options);\r
477 }\r
478\r
479 url = this.setupUrl(options, url);\r
480\r
481 //<debug>\r
482 if (!url) {\r
483 Ext.raise({\r
484 options: options,\r
485 msg: 'No URL specified'\r
486 });\r
487 }\r
488 //</debug>\r
489\r
490 // check for xml or json data, and make sure json data is encoded\r
491 data = options.rawData || options.binaryData || options.xmlData || jsonData || null;\r
492 if (jsonData && !Ext.isPrimitive(jsonData)) {\r
493 data = Ext.encode(data);\r
494 }\r
495 // Check for binary data. Transform if needed\r
496 if (options.binaryData) {\r
497 //<debug>\r
498 if (!Ext.isArray(options.binaryData)) {\r
499 Ext.log.warn("Binary submission data must be an array of byte values! Instead got " + typeof(options.binaryData));\r
500 }\r
501 //</debug>\r
502 if (me.nativeBinaryPostSupport()) {\r
503 data = (new Uint8Array(options.binaryData));\r
504 if ((Ext.isChrome && Ext.chromeVersion < 22) || Ext.isSafari || Ext.isGecko) {\r
505 data = data.buffer; // send the underlying buffer, not the view, since that's not supported on versions of chrome older than 22\r
506 }\r
507 }\r
508 }\r
509\r
510 // make sure params are a url encoded string and include any extraParams if specified\r
511 if (Ext.isObject(params)) {\r
512 params = Ext.Object.toQueryString(params);\r
513 }\r
514\r
515 if (Ext.isObject(extraParams)) {\r
516 extraParams = Ext.Object.toQueryString(extraParams);\r
517 }\r
518\r
519 params = params + ((extraParams) ? ((params) ? '&' : '') + extraParams : '');\r
520\r
521 urlParams = Ext.isObject(urlParams) ? Ext.Object.toQueryString(urlParams) : urlParams;\r
522\r
523 params = this.setupParams(options, params);\r
524\r
525 // decide the proper method for this request\r
526 method = (options.method || me.getMethod() || ((params || data) ? 'POST' : 'GET')).toUpperCase();\r
527 this.setupMethod(options, method);\r
528\r
529 disableCache = options.disableCaching !== false ? (options.disableCaching || me.getDisableCaching()) : false;\r
530 // if the method is get append date to prevent caching\r
531 if (method === 'GET' && disableCache) {\r
532 url = Ext.urlAppend(url, (options.disableCachingParam || me.getDisableCachingParam()) + '=' + (new Date().getTime()));\r
533 }\r
534\r
535 // if the method is get or there is json/xml data append the params to the url\r
536 if ((method == 'GET' || data) && params) {\r
537 url = Ext.urlAppend(url, params);\r
538 params = null;\r
539 }\r
540\r
541 // allow params to be forced into the url\r
542 if (urlParams) {\r
543 url = Ext.urlAppend(url, urlParams);\r
544 }\r
545\r
546 return {\r
547 url: url,\r
548 method: method,\r
549 data: data || params || null\r
550 };\r
551 },\r
552\r
553 /**\r
554 * Template method for overriding url\r
555 * @private\r
556 * @param {Object} options\r
557 * @param {String} url\r
558 * @return {String} The modified url\r
559 */\r
560 setupUrl: function(options, url) {\r
561 var form = this.getForm(options);\r
562 \r
563 if (form) {\r
564 url = url || form.action;\r
565 }\r
566 \r
567 return url;\r
568 },\r
569\r
570 /**\r
571 * Template method for overriding params\r
572 * @private\r
573 * @param {Object} options\r
574 * @param {String} params\r
575 * @return {String} The modified params\r
576 */\r
577 setupParams: function(options, params) {\r
578 var form = this.getForm(options),\r
579 serializedForm;\r
580 \r
581 if (form && !this.isFormUpload(options)) {\r
582 serializedForm = Ext.Element.serializeForm(form);\r
583 params = params ? (params + '&' + serializedForm) : serializedForm;\r
584 }\r
585 \r
586 return params;\r
587 },\r
588\r
589 /**\r
590 * Template method for overriding method\r
591 * @private\r
592 * @param {Object} options\r
593 * @param {String} method\r
594 * @return {String} The modified method\r
595 */\r
596 setupMethod: function(options, method) {\r
597 if (this.isFormUpload(options)) {\r
598 return 'POST';\r
599 }\r
600 \r
601 return method;\r
602 },\r
603\r
604 /**\r
605 * Determines whether this object has a request outstanding.\r
606 *\r
607 * @param {Object} [request] Defaults to the last transaction\r
608 *\r
609 * @return {Boolean} True if there is an outstanding request.\r
610 */\r
611 isLoading: function(request) {\r
612 if (!request) {\r
613 request = this.getLatest();\r
614 }\r
615 \r
616 return request ? request.isLoading() : false;\r
617 },\r
618\r
619 /**\r
620 * Aborts an active request.\r
621 * @param {Ext.ajax.Request} [request] Defaults to the last request\r
622 */\r
623 abort: function(request) {\r
624 if (!request) {\r
625 request = this.getLatest();\r
626 }\r
627\r
628 if (request && request.isLoading()) {\r
629 request.abort();\r
630 }\r
631 },\r
632\r
633 /**\r
634 * Aborts all active requests\r
635 */\r
636 abortAll: function() {\r
637 var requests = this.requests,\r
638 id;\r
639\r
640 for (id in requests) {\r
641 this.abort(requests[id]);\r
642 }\r
643 },\r
644\r
645 /**\r
646 * Gets the most recent request\r
647 * @return {Object} The request. Null if there is no recent request\r
648 * @private\r
649 */\r
650 getLatest: function() {\r
651 var id = this.latestId,\r
652 request;\r
653\r
654 if (id) {\r
655 request = this.requests[id];\r
656 }\r
657 \r
658 return request || null;\r
659 },\r
660\r
661 /**\r
662 * Clears the timeout on the request\r
663 * @param {Object} request The request\r
664 * @private\r
665 */\r
666 clearTimeout: function(request) {\r
667 if (!request) {\r
668 request = this.getLatest();\r
669 }\r
670 \r
671 if (request) {\r
672 request.clearTimer();\r
673 }\r
674 },\r
675 \r
676 onRequestComplete: function(request) {\r
677 delete this.requests[request.id];\r
678 },\r
679 \r
680 /**\r
681 * @return {Boolean} `true` if the browser can natively post binary data.\r
682 * @private\r
683 */\r
684 nativeBinaryPostSupport: function() {\r
685 return Ext.isChrome ||\r
686 (Ext.isSafari && Ext.isDefined(window.Uint8Array)) ||\r
687 (Ext.isGecko && Ext.isDefined(window.Uint8Array));\r
688 }\r
689});\r