]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/io/io-base.js
Release 6.2.0beta4
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / io / io-base.js
1 /*
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 3.0.0
6 build: 1549
7 */
8 YUI.add('io-base', function(Y) {
9
10    /**
11         * Base IO functionality. Provides basic XHR transport support.
12         * @module io
13         * @submodule io-base
14         */
15
16    /**
17         * The io class is a utility that brokers HTTP requests through a simplified
18         * interface.  Specifically, it allows JavaScript to make HTTP requests to
19         * a resource without a page reload.  The underlying transport for making
20         * same-domain requests is the XMLHttpRequest object.  YUI.io can also use
21         * Flash, if specified as a transport, for cross-domain requests.
22         *
23         * @class io
24         */
25
26    /**
27         * @event io:start
28         * @description This event is fired by YUI.io when a transaction is initiated.
29         * @type Event Custom
30         */
31         var E_START = 'io:start',
32
33    /**
34         * @event io:complete
35         * @description This event is fired by YUI.io when a transaction is complete.
36         * Response status and data are accessible, if available.
37         * @type Event Custom
38         */
39         E_COMPLETE = 'io:complete',
40
41    /**
42         * @event io:success
43         * @description This event is fired by YUI.io when a transaction is complete, and
44         * the HTTP status resolves to HTTP2xx.
45         * @type Event Custom
46         */
47         E_SUCCESS = 'io:success',
48
49    /**
50         * @event io:failure
51         * @description This event is fired by YUI.io when a transaction is complete, and
52         * the HTTP status resolves to HTTP4xx, 5xx and above.
53         * @type Event Custom
54         */
55         E_FAILURE = 'io:failure',
56
57    /**
58         * @event io:end
59         * @description This event signifies the end of the transaction lifecycle.  The
60         * transaction transport is destroyed.
61         * @type Event Custom
62         */
63         E_END = 'io:end',
64
65         //--------------------------------------
66         //  Properties
67         //--------------------------------------
68    /**
69         * @description A transaction counter that increments for each transaction.
70         *
71         * @property transactionId
72         * @private
73         * @static
74         * @type int
75         */
76         transactionId = 0,
77
78    /**
79         * @description Object of default HTTP headers to be initialized and sent
80         * for all transactions.
81         *
82         * @property _headers
83         * @private
84         * @static
85         * @type object
86         */
87         _headers = {
88                 'X-Requested-With' : 'XMLHttpRequest'
89         },
90
91    /**
92         * @description Object that stores timeout values for any transaction with
93         * a defined "timeout" configuration property.
94         *
95         * @property _timeout
96         * @private
97         * @static
98         * @type object
99         */
100         _timeout = {},
101
102         // Window reference
103         w = Y.config.win;
104
105         //--------------------------------------
106         //  Methods
107         //--------------------------------------
108    /**
109         * @description Method for requesting a transaction. _io() is implemented as
110         * yui.io().  Each transaction may include a configuration object.  Its
111         * properties are:
112         *
113         * method: HTTP method verb (e.g., GET or POST). If this property is not
114         *         not defined, the default value will be GET.
115         *
116         * data: This is the name-value string that will be sent as the transaction
117     *           data.  If the request is HTTP GET, the data become part of
118     *           querystring. If HTTP POST, the data are sent in the message body.
119         *
120         * xdr: Defines the transport to be used for cross-domain requests.  By
121         *      setting this property, the transaction will use the specified
122         *      transport instead of XMLHttpRequest.  Currently, the only alternate
123         *      transport supported is Flash (e.g., { xdr: 'flash' }).
124         *
125         * form: This is a defined object used to process HTML form as data.  The
126         *       properties are:
127         *       {
128         *             id: object, //HTML form object or id of HTML form
129         *         useDisabled: boolean, //Allow disabled HTML form field values
130         *                      to be sent as part of the data.
131         *       }
132         *
133         * on: This is a defined object used to create and handle specific
134         *     events during a transaction lifecycle.  These events will fire in
135         *     addition to the global io events. The events are:
136         *         start - This event is fired when a request is sent to a resource.
137         *     complete - This event fires when the transaction is complete.
138         *     success - This event fires when the response status resolves to
139         *               HTTP 2xx.
140         *     failure - This event fires when the response status resolves to
141         *               HTTP 4xx, 5xx; and, for all transaction exceptions,
142         *               including aborted transactions and transaction timeouts.
143         *         end -  This even is fired at the conclusion of the transaction
144         *                        lifecycle, after a success or failure resolution.
145         *
146         *     The properties are:
147         *     {
148         *       start: function(id, args){},
149         *       complete: function(id, responseobject, args){},
150         *       success: function(id, responseobject, args){},
151         *       failure: function(id, responseobject, args){},
152         *       end: function(id, args){}
153         *     }
154         *         Each property can reference a function or be written as an
155         *     inline function.
156         *
157         *     context: Object reference for an event handler when it is implemented
158         *              as a method of a base object. Defining "context" will preserve
159         *              the proper reference of "this" used in the event handler.
160         *     headers: This is a defined object of client headers, as many as.
161         *              desired for the transaction.  These headers are sentThe object
162         *              pattern is:
163         *              {
164         *                        header: value
165         *              }
166         *
167         * timeout: This value, defined as milliseconds, is a time threshold for the
168         *          transaction. When this threshold is reached, and the transaction's
169         *          Complete event has not yet fired, the transaction will be aborted.
170         * arguments: Object, array, string, or number passed to all registered
171         *            event handlers.  This value is available as the second
172         *            argument in the "start" and "abort" event handlers; and, it is
173         *            the third argument in the "complete", "success", and "failure"
174         *            event handlers.
175         *
176         * @method _io
177         * @private
178         * @static
179         * @param {string} uri - qualified path to transaction resource.
180         * @param {object} c - configuration object for the transaction.
181         * @param {number} i - transaction id, if already set by queue.
182         * @return object
183         */
184         function _io(uri, c, i) {
185                 var f, o, m;
186                         c = c || {};
187                         o = _create(c.xdr || c.form, i);
188                         m = c.method ? c.method.toUpperCase() : 'GET';
189
190                 if (c.form) {
191                         if (c.form.upload) {
192                                 return Y.io._upload(o, uri, c);
193                         }
194                         else {
195                                 f = Y.io._serialize(c.form, c.data);
196                                 if (m === 'POST') {
197                                         c.data = f;
198                                         _setHeader('Content-Type', 'application/x-www-form-urlencoded');
199                                 }
200                                 else if (m === 'GET') {
201                                         uri = _concat(uri, f);
202                                 }
203                         }
204                 }
205                 else if (c.data && m === 'GET') {
206                         uri = _concat(uri, c.data);
207                 }
208
209                 if (c.xdr) {
210                         if (c.xdr.use === 'native' && window.XDomainRequest || c.xdr.use === 'flash') {
211                                 return Y.io.xdr(uri, o, c);
212                         }
213                         if (c.xdr.credentials) {
214                                 o.c.withCredentials = true;
215                         }
216                 }
217
218                 o.c.onreadystatechange = function() { _readyState(o, c); };
219                 try {
220                         o.c.open(m, uri, true);
221                 }
222                 catch(e0){
223                         if (c.xdr) {
224                                 // This exception is usually thrown by browsers
225                                 // that do not support native XDR transactions.
226                                 return _resend(o, uri, c);
227                         }
228                 }
229
230                 if (c.data && m === 'POST') {
231                         _setHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
232                 }
233
234                 _setHeaders(o.c, c.headers || {});
235                 try {
236                         // Using "null" will result in a POST request with
237                         // no Content-Length defined.
238                         o.c.send(c.data || '');
239                 }
240                 catch(e1) {
241                         if (c.xdr) {
242                                 // This exception is usually thrown by browsers
243                                 // that do not support native XDR transactions.
244                                 return _resend(o, uri, c);
245                         }
246                 }
247
248                 _ioStart(o.id, c);
249                 // If config.timeout is defined, and the request is standard XHR,
250                 // initialize timeout polling.
251                 if (c.timeout) {
252                         _startTimeout(o, c.timeout);
253                 }
254
255                 return {
256                         id: o.id,
257                         abort: function() {
258                                 return o.c ? _ioCancel(o, 'abort') : false;
259                         },
260                         isInProgress: function() {
261                                 return o.c ? o.c.readyState !== 4 && o.c.readyState !== 0 : false;
262                         }
263                 }
264         }
265
266    /**
267         * @description Method for creating and subscribing transaction events.
268         *
269         * @method _subscribe
270         * @private
271         * @static
272         * @param {string} e - event to be published
273         * @param {object} c - configuration data subset for event subscription.
274         *
275         * @return void
276         */
277         function _subscribe(e, c){
278                 var evt = new Y.EventTarget().publish('transaction:' + e);
279                 evt.subscribe(c.on[e], (c.context || Y), c.arguments);
280
281                 return evt;
282         }
283
284    /**
285         * @description Fires event "io:start" and creates, fires a
286         * transaction-specific start event, if config.on.start is
287         * defined.
288         *
289         * @method _ioStart
290         * @private
291         * @static
292         * @param {number} id - transaction id
293         * @param {object} c - configuration object for the transaction.
294         *
295     * @return void
296         */
297         function _ioStart(id, c) {
298                 var evt;
299                         // Set default value of argument c, property "on" to Object if
300                         // the property is null or undefined.
301                         c.on = c.on || {};
302
303                 Y.fire(E_START, id);
304                 if (c.on.start) {
305                         evt = _subscribe('start', c);
306                         evt.fire(id);
307                 }
308         }
309
310
311    /**
312         * @description Fires event "io:complete" and creates, fires a
313         * transaction-specific "complete" event, if config.on.complete is
314         * defined.
315         *
316         * @method _ioComplete
317         * @private
318         * @static
319         * @param {object} o - transaction object.
320         * @param {object} c - configuration object for the transaction.
321         *
322     * @return void
323         */
324         function _ioComplete(o, c) {
325                 var evt,
326                         r = o.status ? { status: 0, statusText: o.status } : o.c;
327                         // Set default value of argument c, property "on" to Object if
328                         // the property is null or undefined.
329                         c.on = c.on || {};
330
331                 Y.fire(E_COMPLETE, o.id, r);
332                 if (c.on.complete) {
333                         evt = _subscribe('complete', c);
334                         evt.fire(o.id, r);
335                 }
336         }
337
338    /**
339         * @description Fires event "io:success" and creates, fires a
340         * transaction-specific "success" event, if config.on.success is
341         * defined.
342         *
343         * @method _ioSuccess
344         * @private
345         * @static
346         * @param {object} o - transaction object.
347         * @param {object} c - configuration object for the transaction.
348         *
349     * @return void
350         */
351         function _ioSuccess(o, c) {
352                 var evt;
353                         // Set default value of argument c, property "on" to Object if
354                         // the property is null or undefined.
355                         c.on = c.on || {};
356
357                 Y.fire(E_SUCCESS, o.id, o.c);
358                 if (c.on.success) {
359                         evt = _subscribe('success', c);
360                         evt.fire(o.id, o.c);
361                 }
362
363                 _ioEnd(o, c);
364         }
365
366    /**
367         * @description Fires event "io:failure" and creates, fires a
368         * transaction-specific "failure" event, if config.on.failure is
369         * defined.
370         *
371         * @method _ioFailure
372         * @private
373         * @static
374         * @param {object} o - transaction object.
375         * @param {object} c - configuration object for the transaction.
376         *
377     * @return void
378         */
379         function _ioFailure(o, c) {
380                 var evt,
381                         r = o.status ? { status: 0, statusText: o.status } : o.c;
382                         // Set default value of argument c, property "on" to Object if
383                         // the property is null or undefined.
384                         c.on = c.on || {};
385
386                 Y.fire(E_FAILURE, o.id, r);
387                 if (c.on.failure) {
388                         evt = _subscribe('failure', c);
389                         evt.fire(o.id, r);
390                 }
391
392                 _ioEnd(o, c);
393         }
394
395    /**
396         * @description Fires event "io:end" and creates, fires a
397         * transaction-specific "end" event, if config.on.end is
398         * defined.
399         *
400         * @method _ioEnd
401         * @private
402         * @static
403         * @param {object} o - transaction object.
404         * @param {object} c - configuration object for the transaction.
405         *
406     * @return void
407         */
408         function _ioEnd(o, c) {
409                 var evt;
410                         // Set default value of argument c, property "on" to Object if
411                         // the property is null or undefined.
412                         c.on = c.on || {};
413
414                 Y.fire(E_END, o.id);
415                 if (c.on.end) {
416                         evt = _subscribe('end', c);
417                         evt.fire(o.id);
418                 }
419
420                 _destroy(o, c.xdr ? true : false );
421         }
422
423    /**
424         * @description Terminates a transaction due to an explicit abort or
425         * timeout.
426         *
427         * @method _ioCancel
428         * @private
429         * @static
430         * @param {object} o - Transaction object generated by _create().
431         * @param {string} s - Identifies timed out or aborted transaction.
432         *
433     * @return void
434         */
435         function _ioCancel(o, s) {
436                 if (o && o.c) {
437                         o.status = s;
438                         o.c.abort();
439                 }
440         }
441
442    /**
443         * @description Resends an XDR transaction, using the Flash tranport,
444         * if the native transport fails.
445         *
446         * @method _resend
447         * @private
448         * @static
449
450         * @param {object} o - Transaction object generated by _create().
451         * @param {string} uri - qualified path to transaction resource.
452         * @param {object} c - configuration object for the transaction.
453         *
454     * @return void
455         */
456         function _resend(o, uri, c) {
457                 var id = parseInt(o.id);
458
459                 _destroy(o);
460                 c.xdr.use = 'flash';
461
462                 return Y.io(uri, c, id);
463         }
464
465    /**
466         * @description Method that increments _transactionId for each transaction.
467         *
468         * @method _id
469         * @private
470         * @static
471     * @return int
472         */
473         function _id() {
474                 var id = transactionId;
475
476                 transactionId++;
477
478                 return id;
479         }
480
481    /**
482         * @description Method that creates a unique transaction object for each
483         * request.
484         *
485         * @method _create
486         * @private
487         * @static
488         * @param {number} c - configuration object subset to determine if
489         *                     the transaction is an XDR or file upload,
490         *                     requiring an alternate transport.
491         * @param {number} i - transaction id
492         * @return object
493         */
494         function _create(c, i) {
495                 var o = {};
496                         o.id = Y.Lang.isNumber(i) ? i : _id();
497                         c = c || {};
498
499                 if (!c.use && !c.upload) {
500                         o.c = _xhr();
501                 }
502                 else if (c.use) {
503                         if (c.use === 'flash') {
504                                 o.c = Y.io._transport[c.use];
505                         }
506                         else if (c.use === 'native' && window.XDomainRequest) {
507                                 o.c = new XDomainRequest();
508                         }
509                         else {
510                                 o.c = _xhr();
511                         }
512                 }
513                 else {
514                         o.c = {};
515                 }
516
517                 return o;
518         };
519
520    /**
521         * @description Method that creates the XMLHttpRequest transport
522         *
523         * @method _xhr
524         * @private
525         * @static
526         * @return object
527         */
528         function _xhr() {
529                 return w.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
530         }
531
532    /**
533         * @description Method that concatenates string data for HTTP GET transactions.
534         *
535         * @method _concat
536         * @private
537         * @static
538         * @param {string} s - URI or root data.
539         * @param {string} d - data to be concatenated onto URI.
540         * @return int
541         */
542         function _concat(s, d) {
543                 s += ((s.indexOf('?') == -1) ? '?' : '&') + d;
544                 return s;
545         }
546
547    /**
548         * @description Method that stores default client headers for all transactions.
549         * If a label is passed with no value argument, the header will be deleted.
550         *
551         * @method _setHeader
552         * @private
553         * @static
554         * @param {string} l - HTTP header
555         * @param {string} v - HTTP header value
556         * @return int
557         */
558         function _setHeader(l, v) {
559                 if (v) {
560                         _headers[l] = v;
561                 }
562                 else {
563                         delete _headers[l];
564                 }
565         }
566
567    /**
568         * @description Method that sets all HTTP headers to be sent in a transaction.
569         *
570         * @method _setHeaders
571         * @private
572         * @static
573         * @param {object} o - XHR instance for the specific transaction.
574         * @param {object} h - HTTP headers for the specific transaction, as defined
575         *                     in the configuration object passed to YUI.io().
576         * @return void
577         */
578         function _setHeaders(o, h) {
579                 var p;
580
581                 for (p in _headers) {
582                         if (_headers.hasOwnProperty(p)) {
583                                 if (h[p]) {
584                                         // Configuration headers will supersede IO preset headers,
585                                         // if headers match.
586                                         break;
587                                 }
588                                 else {
589                                         h[p] = _headers[p];
590                                 }
591                         }
592                 }
593
594                 for (p in h) {
595                         if (h.hasOwnProperty(p)) {
596                                 o.setRequestHeader(p, h[p]);
597                         }
598                 }
599         }
600
601    /**
602         * @description Starts timeout count if the configuration object
603         * has a defined timeout property.
604         *
605         * @method _startTimeout
606         * @private
607         * @static
608         * @param {object} o - Transaction object generated by _create().
609         * @param {object} c - Configuration object passed to YUI.io().
610         * @return void
611         */
612         function _startTimeout(o, timeout) {
613                 _timeout[o.id] = w.setTimeout(function() { _ioCancel(o, 'timeout'); }, timeout);
614         }
615
616    /**
617         * @description Clears the timeout interval started by _startTimeout().
618         *
619         * @method _clearTimeout
620         * @private
621         * @static
622         * @param {number} id - Transaction id.
623         * @return void
624         */
625         function _clearTimeout(id) {
626                 w.clearTimeout(_timeout[id]);
627                 delete _timeout[id];
628         }
629
630    /**
631         * @description Event handler bound to onreadystatechange.
632         *
633         * @method _readyState
634         * @private
635         * @static
636         * @param {object} o - Transaction object generated by _create().
637         * @param {object} c - Configuration object passed to YUI.io().
638         * @return void
639         */
640         function _readyState(o, c) {
641                 if (o.c.readyState === 4) {
642                         if (c.timeout) {
643                                 _clearTimeout(o.id);
644                         }
645
646                         w.setTimeout(
647                                 function() {
648                                         _ioComplete(o, c);
649                                         _handleResponse(o, c);
650                                 }, 0);
651                 }
652         }
653
654    /**
655         * @description Method that determines if a transaction response qualifies
656         * as success or failure, based on the response HTTP status code, and
657         * fires the appropriate success or failure events.
658         *
659         * @method _handleResponse
660         * @private
661         * @static
662         * @param {object} o - Transaction object generated by _create().
663         * @param {object} c - Configuration object passed to io().
664         * @return void
665         */
666         function _handleResponse(o, c) {
667                 var status;
668                 try{
669                         if (o.c.status && o.c.status !== 0) {
670                                 status = o.c.status;
671                         }
672                         else {
673                                 status = 0;
674                         }
675                 }
676                 catch(e) {
677                         status = 0;
678                 }
679
680                 // IE reports HTTP 204 as HTTP 1223.
681                 if (status >= 200 && status < 300 || status === 1223) {
682                         _ioSuccess(o, c);
683                 }
684                 else {
685                         _ioFailure(o, c);
686                 }
687         }
688
689         function _destroy(o, transport) {
690                 // IE, when using XMLHttpRequest as an ActiveX Object, will throw
691                 // a "Type Mismatch" error if the event handler is set to "null".
692                 if(w.XMLHttpRequest && !transport) {
693                         if (o.c) {
694                                 o.c.onreadystatechange = null;
695                         }
696                 }
697
698                 o.c = null;
699                 o = null;
700         }
701
702         _io.start = _ioStart;
703         _io.complete = _ioComplete;
704         _io.success = _ioSuccess;
705         _io.failure = _ioFailure;
706         _io.end = _ioEnd;
707         _io._id = _id;
708         _io._timeout = _timeout;
709
710         //--------------------------------------
711         //  Begin public interface definition
712         //--------------------------------------
713    /**
714         * @description Method that stores default client headers for all transactions.
715         * If a label is passed with no value argument, the header will be deleted.
716         * This is the interface for _setHeader().
717         *
718         * @method header
719         * @public
720         * @static
721         * @param {string} l - HTTP header
722         * @param {string} v - HTTP header value
723         * @return int
724         */
725         _io.header = _setHeader;
726
727    /**
728         * @description Method for requesting a transaction. This
729         * is the interface for _io().
730         *
731         * @method io
732         * @public
733         * @static
734     * @param {string} uri - qualified path to transaction resource.
735     * @param {object} c - configuration object for the transaction.
736     * @return object
737     */
738         Y.io = _io;
739         Y.io.http = _io;
740
741
742
743 }, '3.0.0' ,{requires:['event-custom-base']});