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