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