doc updates
[roojs1] / Roo / lib / Ajax.js
1 /*
2  * Portions of this file are based on pieces of Yahoo User Interface Library
3  * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4  * YUI licensed under the BSD License:
5  * http://developer.yahoo.net/yui/license.txt
6  * <script type="text/javascript">
7  *
8  */
9
10 (function() {
11     /**
12      * @class Roo.lib.Ajax
13      *
14      */
15     Roo.lib.Ajax = {
16         /**
17          * @static 
18          */
19         request : function(method, uri, cb, data, options) {
20             if(options){
21                 var hs = options.headers;
22                 if(hs){
23                     for(var h in hs){
24                         if(hs.hasOwnProperty(h)){
25                             this.initHeader(h, hs[h], false);
26                         }
27                     }
28                 }
29                 if(options.xmlData){
30                     this.initHeader('Content-Type', 'text/xml', false);
31                     method = 'POST';
32                     data = options.xmlData;
33                 }
34             }
35
36             return this.asyncRequest(method, uri, cb, data);
37         },
38
39         serializeForm : function(form) {
40             if(typeof form == 'string') {
41                 form = (document.getElementById(form) || document.forms[form]);
42             }
43
44             var el, name, val, disabled, data = '', hasSubmit = false;
45             for (var i = 0; i < form.elements.length; i++) {
46                 el = form.elements[i];
47                 disabled = form.elements[i].disabled;
48                 name = form.elements[i].name;
49                 val = form.elements[i].value;
50
51                 if (!disabled && name){
52                     switch (el.type)
53                             {
54                         case 'select-one':
55                         case 'select-multiple':
56                             for (var j = 0; j < el.options.length; j++) {
57                                 if (el.options[j].selected) {
58                                     if (Roo.isIE) {
59                                         data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
60                                     }
61                                     else {
62                                         data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
63                                     }
64                                 }
65                             }
66                             break;
67                         case 'radio':
68                         case 'checkbox':
69                             if (el.checked) {
70                                 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
71                             }
72                             break;
73                         case 'file':
74
75                         case undefined:
76
77                         case 'reset':
78
79                         case 'button':
80
81                             break;
82                         case 'submit':
83                             if(hasSubmit == false) {
84                                 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
85                                 hasSubmit = true;
86                             }
87                             break;
88                         default:
89                             data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
90                             break;
91                     }
92                 }
93             }
94             data = data.substr(0, data.length - 1);
95             return data;
96         },
97
98         headers:{},
99
100         hasHeaders:false,
101
102         useDefaultHeader:true,
103
104         defaultPostHeader:'application/x-www-form-urlencoded',
105
106         useDefaultXhrHeader:true,
107
108         defaultXhrHeader:'XMLHttpRequest',
109
110         hasDefaultHeaders:true,
111
112         defaultHeaders:{},
113
114         poll:{},
115
116         timeout:{},
117
118         pollInterval:50,
119
120         transactionId:0,
121
122         setProgId:function(id)
123         {
124             this.activeX.unshift(id);
125         },
126
127         setDefaultPostHeader:function(b)
128         {
129             this.useDefaultHeader = b;
130         },
131
132         setDefaultXhrHeader:function(b)
133         {
134             this.useDefaultXhrHeader = b;
135         },
136
137         setPollingInterval:function(i)
138         {
139             if (typeof i == 'number' && isFinite(i)) {
140                 this.pollInterval = i;
141             }
142         },
143
144         createXhrObject:function(transactionId)
145         {
146             var obj,http;
147             try
148             {
149
150                 http = new XMLHttpRequest();
151
152                 obj = { conn:http, tId:transactionId };
153             }
154             catch(e)
155             {
156                 for (var i = 0; i < this.activeX.length; ++i) {
157                     try
158                     {
159
160                         http = new ActiveXObject(this.activeX[i]);
161
162                         obj = { conn:http, tId:transactionId };
163                         break;
164                     }
165                     catch(e) {
166                     }
167                 }
168             }
169             finally
170             {
171                 return obj;
172             }
173         },
174
175         getConnectionObject:function()
176         {
177             var o;
178             var tId = this.transactionId;
179
180             try
181             {
182                 o = this.createXhrObject(tId);
183                 if (o) {
184                     this.transactionId++;
185                 }
186             }
187             catch(e) {
188             }
189             finally
190             {
191                 return o;
192             }
193         },
194
195         asyncRequest:function(method, uri, callback, postData)
196         {
197             var o = this.getConnectionObject();
198
199             if (!o) {
200                 return null;
201             }
202             else {
203                 o.conn.open(method, uri, true);
204
205                 if (this.useDefaultXhrHeader) {
206                     if (!this.defaultHeaders['X-Requested-With']) {
207                         this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
208                     }
209                 }
210
211                 if(postData && this.useDefaultHeader){
212                     this.initHeader('Content-Type', this.defaultPostHeader);
213                 }
214
215                  if (this.hasDefaultHeaders || this.hasHeaders) {
216                     this.setHeader(o);
217                 }
218
219                 this.handleReadyState(o, callback);
220                 o.conn.send(postData || null);
221
222                 return o;
223             }
224         },
225
226         handleReadyState:function(o, callback)
227         {
228             var oConn = this;
229
230             if (callback && callback.timeout) {
231                 this.timeout[o.tId] = window.setTimeout(function() {
232                     oConn.abort(o, callback, true);
233                 }, callback.timeout);
234             }
235
236             this.poll[o.tId] = window.setInterval(
237                     function() {
238                         if (o.conn && o.conn.readyState == 4) {
239                             window.clearInterval(oConn.poll[o.tId]);
240                             delete oConn.poll[o.tId];
241
242                             if(callback && callback.timeout) {
243                                 window.clearTimeout(oConn.timeout[o.tId]);
244                                 delete oConn.timeout[o.tId];
245                             }
246
247                             oConn.handleTransactionResponse(o, callback);
248                         }
249                     }
250                     , this.pollInterval);
251         },
252
253         handleTransactionResponse:function(o, callback, isAbort)
254         {
255
256             if (!callback) {
257                 this.releaseObject(o);
258                 return;
259             }
260
261             var httpStatus, responseObject;
262
263             try
264             {
265                 if (o.conn.status !== undefined && o.conn.status != 0) {
266                     httpStatus = o.conn.status;
267                 }
268                 else {
269                     httpStatus = 13030;
270                 }
271             }
272             catch(e) {
273
274
275                 httpStatus = 13030;
276             }
277
278             if (httpStatus >= 200 && httpStatus < 300) {
279                 responseObject = this.createResponseObject(o, callback.argument);
280                 if (callback.success) {
281                     if (!callback.scope) {
282                         callback.success(responseObject);
283                     }
284                     else {
285
286
287                         callback.success.apply(callback.scope, [responseObject]);
288                     }
289                 }
290             }
291             else {
292                 switch (httpStatus) {
293
294                     case 12002:
295                     case 12029:
296                     case 12030:
297                     case 12031:
298                     case 12152:
299                     case 13030:
300                         responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
301                         if (callback.failure) {
302                             if (!callback.scope) {
303                                 callback.failure(responseObject);
304                             }
305                             else {
306                                 callback.failure.apply(callback.scope, [responseObject]);
307                             }
308                         }
309                         break;
310                     default:
311                         responseObject = this.createResponseObject(o, callback.argument);
312                         if (callback.failure) {
313                             if (!callback.scope) {
314                                 callback.failure(responseObject);
315                             }
316                             else {
317                                 callback.failure.apply(callback.scope, [responseObject]);
318                             }
319                         }
320                 }
321             }
322
323             this.releaseObject(o);
324             responseObject = null;
325         },
326
327         createResponseObject:function(o, callbackArg)
328         {
329             var obj = {};
330             var headerObj = {};
331
332             try
333             {
334                 var headerStr = o.conn.getAllResponseHeaders();
335                 var header = headerStr.split('\n');
336                 for (var i = 0; i < header.length; i++) {
337                     var delimitPos = header[i].indexOf(':');
338                     if (delimitPos != -1) {
339                         headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
340                     }
341                 }
342             }
343             catch(e) {
344             }
345
346             obj.tId = o.tId;
347             obj.status = o.conn.status;
348             obj.statusText = o.conn.statusText;
349             obj.getResponseHeader = headerObj;
350             obj.getAllResponseHeaders = headerStr;
351             obj.responseText = o.conn.responseText;
352             obj.responseXML = o.conn.responseXML;
353
354             if (typeof callbackArg !== undefined) {
355                 obj.argument = callbackArg;
356             }
357
358             return obj;
359         },
360
361         createExceptionObject:function(tId, callbackArg, isAbort)
362         {
363             var COMM_CODE = 0;
364             var COMM_ERROR = 'communication failure';
365             var ABORT_CODE = -1;
366             var ABORT_ERROR = 'transaction aborted';
367
368             var obj = {};
369
370             obj.tId = tId;
371             if (isAbort) {
372                 obj.status = ABORT_CODE;
373                 obj.statusText = ABORT_ERROR;
374             }
375             else {
376                 obj.status = COMM_CODE;
377                 obj.statusText = COMM_ERROR;
378             }
379
380             if (callbackArg) {
381                 obj.argument = callbackArg;
382             }
383
384             return obj;
385         },
386
387         initHeader:function(label, value, isDefault)
388         {
389             var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
390
391             if (headerObj[label] === undefined) {
392                 headerObj[label] = value;
393             }
394             else {
395
396
397                 headerObj[label] = value + "," + headerObj[label];
398             }
399
400             if (isDefault) {
401                 this.hasDefaultHeaders = true;
402             }
403             else {
404                 this.hasHeaders = true;
405             }
406         },
407
408
409         setHeader:function(o)
410         {
411             if (this.hasDefaultHeaders) {
412                 for (var prop in this.defaultHeaders) {
413                     if (this.defaultHeaders.hasOwnProperty(prop)) {
414                         o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
415                     }
416                 }
417             }
418
419             if (this.hasHeaders) {
420                 for (var prop in this.headers) {
421                     if (this.headers.hasOwnProperty(prop)) {
422                         o.conn.setRequestHeader(prop, this.headers[prop]);
423                     }
424                 }
425                 this.headers = {};
426                 this.hasHeaders = false;
427             }
428         },
429
430         resetDefaultHeaders:function() {
431             delete this.defaultHeaders;
432             this.defaultHeaders = {};
433             this.hasDefaultHeaders = false;
434         },
435
436         abort:function(o, callback, isTimeout)
437         {
438             if(this.isCallInProgress(o)) {
439                 o.conn.abort();
440                 window.clearInterval(this.poll[o.tId]);
441                 delete this.poll[o.tId];
442                 if (isTimeout) {
443                     delete this.timeout[o.tId];
444                 }
445
446                 this.handleTransactionResponse(o, callback, true);
447
448                 return true;
449             }
450             else {
451                 return false;
452             }
453         },
454
455
456         isCallInProgress:function(o)
457         {
458             if (o && o.conn) {
459                 return o.conn.readyState != 4 && o.conn.readyState != 0;
460             }
461             else {
462
463                 return false;
464             }
465         },
466
467
468         releaseObject:function(o)
469         {
470
471             o.conn = null;
472
473             o = null;
474         },
475
476         activeX:[
477         'MSXML2.XMLHTTP.3.0',
478         'MSXML2.XMLHTTP',
479         'Microsoft.XMLHTTP'
480         ]
481
482
483     };
484 })();