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