Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / docs / source / ext-base-ajax.html
1 <html>
2 <head>
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
4   <title>The source code</title>
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
7 </head>
8 <body  onload="prettyPrint();">
9     <pre class="prettyprint lang-js">/*!
10  * Ext JS Library 3.2.0
11  * Copyright(c) 2006-2010 Ext JS, Inc.
12  * licensing@extjs.com
13  * http://www.extjs.com/license
14  */
15 /*
16 * Portions of this file are based on pieces of Yahoo User Interface Library
17 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
18 * YUI licensed under the BSD License:
19 * http://developer.yahoo.net/yui/license.txt
20 */
21 Ext.lib.Ajax = function() {
22     var activeX = ['MSXML2.XMLHTTP.3.0',
23                    'MSXML2.XMLHTTP',
24                    'Microsoft.XMLHTTP'],
25         CONTENTTYPE = 'Content-Type';
26
27     // private
28     function setHeader(o) {
29         var conn = o.conn,
30             prop;
31
32         function setTheHeaders(conn, headers){
33             for (prop in headers) {
34                 if (headers.hasOwnProperty(prop)) {
35                     conn.setRequestHeader(prop, headers[prop]);
36                 }
37             }
38         }
39
40         if (pub.defaultHeaders) {
41             setTheHeaders(conn, pub.defaultHeaders);
42         }
43
44         if (pub.headers) {
45             setTheHeaders(conn, pub.headers);
46             delete pub.headers;
47         }
48     }
49
50     // private
51     function createExceptionObject(tId, callbackArg, isAbort, isTimeout) {
52         return {
53             tId : tId,
54             status : isAbort ? -1 : 0,
55             statusText : isAbort ? 'transaction aborted' : 'communication failure',
56             isAbort: isAbort,
57             isTimeout: isTimeout,
58             argument : callbackArg
59         };
60     }
61
62     // private
63     function initHeader(label, value) {
64         (pub.headers = pub.headers || {})[label] = value;
65     }
66
67     // private
68     function createResponseObject(o, callbackArg) {
69         var headerObj = {},
70             headerStr,
71             conn = o.conn,
72             t,
73             s,
74             // see: https://prototype.lighthouseapp.com/projects/8886/tickets/129-ie-mangles-http-response-status-code-204-to-1223
75             isBrokenStatus = conn.status == 1223;
76
77         try {
78             headerStr = o.conn.getAllResponseHeaders();
79             Ext.each(headerStr.replace(/\r\n/g, '\n').split('\n'), function(v){
80                 t = v.indexOf(':');
81                 if(t >= 0){
82                     s = v.substr(0, t).toLowerCase();
83                     if(v.charAt(t + 1) == ' '){
84                         ++t;
85                     }
86                     headerObj[s] = v.substr(t + 1);
87                 }
88             });
89         } catch(e) {}
90
91         return {
92             tId : o.tId,
93             // Normalize the status and statusText when IE returns 1223, see the above link.
94             status : isBrokenStatus ? 204 : conn.status,
95             statusText : isBrokenStatus ? 'No Content' : conn.statusText,
96             getResponseHeader : function(header){return headerObj[header.toLowerCase()];},
97             getAllResponseHeaders : function(){return headerStr},
98             responseText : conn.responseText,
99             responseXML : conn.responseXML,
100             argument : callbackArg
101         };
102     }
103
104     // private
105     function releaseObject(o) {
106         if (o.tId) {
107             pub.conn[o.tId] = null;
108         }
109         o.conn = null;
110         o = null;
111     }
112
113     // private
114     function handleTransactionResponse(o, callback, isAbort, isTimeout) {
115         if (!callback) {
116             releaseObject(o);
117             return;
118         }
119
120         var httpStatus, responseObject;
121
122         try {
123             if (o.conn.status !== undefined && o.conn.status != 0) {
124                 httpStatus = o.conn.status;
125             }
126             else {
127                 httpStatus = 13030;
128             }
129         }
130         catch(e) {
131             httpStatus = 13030;
132         }
133
134         if ((httpStatus >= 200 && httpStatus < 300) || (Ext.isIE && httpStatus == 1223)) {
135             responseObject = createResponseObject(o, callback.argument);
136             if (callback.success) {
137                 if (!callback.scope) {
138                     callback.success(responseObject);
139                 }
140                 else {
141                     callback.success.apply(callback.scope, [responseObject]);
142                 }
143             }
144         }
145         else {
146             switch (httpStatus) {
147                 case 12002:
148                 case 12029:
149                 case 12030:
150                 case 12031:
151                 case 12152:
152                 case 13030:
153                     responseObject = createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false), isTimeout);
154                     if (callback.failure) {
155                         if (!callback.scope) {
156                             callback.failure(responseObject);
157                         }
158                         else {
159                             callback.failure.apply(callback.scope, [responseObject]);
160                         }
161                     }
162                     break;
163                 default:
164                     responseObject = createResponseObject(o, callback.argument);
165                     if (callback.failure) {
166                         if (!callback.scope) {
167                             callback.failure(responseObject);
168                         }
169                         else {
170                             callback.failure.apply(callback.scope, [responseObject]);
171                         }
172                     }
173             }
174         }
175
176         releaseObject(o);
177         responseObject = null;
178     }
179
180     // private
181     function handleReadyState(o, callback){
182     callback = callback || {};
183         var conn = o.conn,
184             tId = o.tId,
185             poll = pub.poll,
186             cbTimeout = callback.timeout || null;
187
188         if (cbTimeout) {
189             pub.conn[tId] = conn;
190             pub.timeout[tId] = setTimeout(function() {
191                 pub.abort(o, callback, true);
192             }, cbTimeout);
193         }
194
195         poll[tId] = setInterval(
196             function() {
197                 if (conn && conn.readyState == 4) {
198                     clearInterval(poll[tId]);
199                     poll[tId] = null;
200
201                     if (cbTimeout) {
202                         clearTimeout(pub.timeout[tId]);
203                         pub.timeout[tId] = null;
204                     }
205
206                     handleTransactionResponse(o, callback);
207                 }
208             },
209             pub.pollInterval);
210     }
211
212     // private
213     function asyncRequest(method, uri, callback, postData) {
214         var o = getConnectionObject() || null;
215
216         if (o) {
217             o.conn.open(method, uri, true);
218
219             if (pub.useDefaultXhrHeader) {
220                 initHeader('X-Requested-With', pub.defaultXhrHeader);
221             }
222
223             if(postData && pub.useDefaultHeader && (!pub.headers || !pub.headers[CONTENTTYPE])){
224                 initHeader(CONTENTTYPE, pub.defaultPostHeader);
225             }
226
227             if (pub.defaultHeaders || pub.headers) {
228                 setHeader(o);
229             }
230
231             handleReadyState(o, callback);
232             o.conn.send(postData || null);
233         }
234         return o;
235     }
236
237     // private
238     function getConnectionObject() {
239         var o;
240
241         try {
242             if (o = createXhrObject(pub.transactionId)) {
243                 pub.transactionId++;
244             }
245         } catch(e) {
246         } finally {
247             return o;
248         }
249     }
250
251     // private
252     function createXhrObject(transactionId) {
253         var http;
254
255         try {
256             http = new XMLHttpRequest();
257         } catch(e) {
258             for (var i = 0; i < activeX.length; ++i) {
259                 try {
260                     http = new ActiveXObject(activeX[i]);
261                     break;
262                 } catch(e) {}
263             }
264         } finally {
265             return {conn : http, tId : transactionId};
266         }
267     }
268
269     var pub = {
270         request : function(method, uri, cb, data, options) {
271             if(options){
272                 var me = this,
273                     xmlData = options.xmlData,
274                     jsonData = options.jsonData,
275                     hs;
276
277                 Ext.applyIf(me, options);
278
279                 if(xmlData || jsonData){
280                     hs = me.headers;
281                     if(!hs || !hs[CONTENTTYPE]){
282                         initHeader(CONTENTTYPE, xmlData ? 'text/xml' : 'application/json');
283                     }
284                     data = xmlData || (!Ext.isPrimitive(jsonData) ? Ext.encode(jsonData) : jsonData);
285                 }
286             }
287             return asyncRequest(method || options.method || "POST", uri, cb, data);
288         },
289
290         serializeForm : function(form) {
291             var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements,
292                 hasSubmit = false,
293                 encoder = encodeURIComponent,
294                 element,
295                 options,
296                 name,
297                 val,
298                 data = '',
299                 type;
300
301             Ext.each(fElements, function(element) {
302                 name = element.name;
303                 type = element.type;
304
305                 if (!element.disabled && name){
306                     if(/select-(one|multiple)/i.test(type)) {
307                         Ext.each(element.options, function(opt) {
308                             if (opt.selected) {
309                                 data += String.format("{0}={1}&", encoder(name), encoder((opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttribute('value') !== null) ? opt.value : opt.text));
310                             }
311                         });
312                     } else if(!/file|undefined|reset|button/i.test(type)) {
313                             if(!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)){
314
315                                 data += encoder(name) + '=' + encoder(element.value) + '&';
316                                 hasSubmit = /submit/i.test(type);
317                             }
318                     }
319                 }
320             });
321             return data.substr(0, data.length - 1);
322         },
323
324         useDefaultHeader : true,
325         defaultPostHeader : 'application/x-www-form-urlencoded; charset=UTF-8',
326         useDefaultXhrHeader : true,
327         defaultXhrHeader : 'XMLHttpRequest',
328         poll : {},
329         timeout : {},
330         conn: {},
331         pollInterval : 50,
332         transactionId : 0,
333
334 //  This is never called - Is it worth exposing this?
335 //          setProgId : function(id) {
336 //              activeX.unshift(id);
337 //          },
338
339 //  This is never called - Is it worth exposing this?
340 //          setDefaultPostHeader : function(b) {
341 //              this.useDefaultHeader = b;
342 //          },
343
344 //  This is never called - Is it worth exposing this?
345 //          setDefaultXhrHeader : function(b) {
346 //              this.useDefaultXhrHeader = b;
347 //          },
348
349 //  This is never called - Is it worth exposing this?
350 //          setPollingInterval : function(i) {
351 //              if (typeof i == 'number' && isFinite(i)) {
352 //                  this.pollInterval = i;
353 //              }
354 //          },
355
356 //  This is never called - Is it worth exposing this?
357 //          resetDefaultHeaders : function() {
358 //              this.defaultHeaders = null;
359 //          },
360
361         abort : function(o, callback, isTimeout) {
362             var me = this,
363                 tId = o.tId,
364                 isAbort = false;
365
366             if (me.isCallInProgress(o)) {
367                 o.conn.abort();
368                 clearInterval(me.poll[tId]);
369                 me.poll[tId] = null;
370                 clearTimeout(pub.timeout[tId]);
371                 me.timeout[tId] = null;
372
373                 handleTransactionResponse(o, callback, (isAbort = true), isTimeout);
374             }
375             return isAbort;
376         },
377
378         isCallInProgress : function(o) {
379             // if there is a connection and readyState is not 0 or 4
380             return o.conn && !{0:true,4:true}[o.conn.readyState];
381         }
382     };
383     return pub;
384 }();</pre>    
385 </body>
386 </html>