]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/io/io.js
Release 6.2.0beta4
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / io / io.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']});
744
745 YUI.add('io-form', function(Y) {
746
747    /**
748     * Extends the IO base class to enable HTML form data serialization, when specified
749     * in the transaction's configuration object.
750     * @module io
751     * @submodule io-form
752     */
753
754     Y.mix(Y.io, {
755        /**
756         * @description Method to enumerate through an HTML form's elements collection
757         * and return a string comprised of key-value pairs.
758         *
759         * @method _serialize
760         * @private
761         * @static
762         * @param {object} c - YUI form node or HTML form id.
763         * @param {string} s - Transaction data defined in the configuration.
764         * @return string
765         */
766         _serialize: function(c, s) {
767                         var eUC = encodeURIComponent,
768                 data = [],
769                 useDf = c.useDisabled || false,
770                 item = 0,
771                 id = (typeof c.id === 'string') ? c.id : c.id.getAttribute('id'),
772                 e, f, n, v, d, i, il, j, jl, o;
773
774                 if (!id) {
775                                         id = Y.guid('io:');
776                                         c.id.setAttribute('id', id);
777                                 }
778
779                 f = Y.config.doc.getElementById(id);
780
781             // Iterate over the form elements collection to construct the
782             // label-value pairs.
783             for (i = 0, il = f.elements.length; i < il; ++i) {
784                 e = f.elements[i];
785                 d = e.disabled;
786                 n = e.name;
787
788                 if ((useDf) ? n : (n && !d)) {
789                     n = encodeURIComponent(n) + '=';
790                     v = encodeURIComponent(e.value);
791
792                     switch (e.type) {
793                         // Safari, Opera, FF all default options.value from .text if
794                         // value attribute not specified in markup
795                         case 'select-one':
796                             if (e.selectedIndex > -1) {
797                                 o = e.options[e.selectedIndex];
798                                 data[item++] = n + eUC((o.attributes.value && o.attributes.value.specified) ? o.value : o.text);
799                             }
800                             break;
801                         case 'select-multiple':
802                             if (e.selectedIndex > -1) {
803                                 for (j = e.selectedIndex, jl = e.options.length; j < jl; ++j) {
804                                     o = e.options[j];
805                                     if (o.selected) {
806                                       data[item++] = n + eUC((o.attributes.value && o.attributes.value.specified) ? o.value : o.text);
807                                     }
808                                 }
809                             }
810                             break;
811                         case 'radio':
812                         case 'checkbox':
813                             if(e.checked){
814                                 data[item++] = n + v;
815                             }
816                             break;
817                         case 'file':
818                             // stub case as XMLHttpRequest will only send the file path as a string.
819                         case undefined:
820                             // stub case for fieldset element which returns undefined.
821                         case 'reset':
822                             // stub case for input type reset button.
823                         case 'button':
824                             // stub case for input type button elements.
825                             break;
826                         case 'submit':
827                         default:
828                             data[item++] = n + v;
829                     }
830                 }
831             }
832             return s ? data.join('&') + "&" + s : data.join('&');
833         }
834     }, true);
835
836
837
838 }, '3.0.0' ,{requires:['io-base','node-base','node-style']});
839
840 YUI.add('io-xdr', function(Y) {
841
842    /**
843     * Extends the IO base class to provide an alternate, Flash transport, for making
844     * cross-domain requests.
845         * @module io
846         * @submodule io-xdr
847         */
848
849    /**
850         * @event io:xdrReady
851         * @description This event is fired by YUI.io when the specified transport is
852         * ready for use.
853         * @type Event Custom
854         */
855         var E_XDR_READY = 'io:xdrReady',
856
857
858    /**
859         * @description Object that stores callback handlers for cross-domain requests
860         * when using Flash as the transport.
861         *
862         * @property _fn
863         * @private
864         * @static
865         * @type object
866         */
867         _fn = {},
868
869    /**
870         * @description Map of transaction state used when XDomainRequest is the
871         * XDR transport.
872         *
873         * @property _rS
874         * @private
875         * @static
876         * @type object
877         */
878         _rS = {};
879
880    /**
881         * @description Method that creates the Flash transport swf.
882         *
883         * @method _swf
884         * @private
885         * @static
886         * @param {string} uri - location of io.swf.
887         * @param {string} yid - YUI instance id.
888         * @return void
889         */
890         function _swf(uri, yid) {
891                 var o = '<object id="yuiIoSwf" type="application/x-shockwave-flash" data="' +
892                         uri + '" width="0" height="0">' +
893                         '<param name="movie" value="' + uri + '">' +
894                         '<param name="FlashVars" value="yid=' + yid + '">' +
895                 '<param name="allowScriptAccess" value="always">' +
896                         '</object>',
897                     c = document.createElement('div');
898
899                 document.body.appendChild(c);
900                 c.innerHTML = o;
901         }
902
903    /**
904         * @description Sets event handlers for XDomainRequest transactions.
905         *
906         * @method _xdr
907         * @private
908         * @static
909     * @param {object} o - Transaction object generated by _create() in io-base.
910         * @param {object} c - configuration object for the transaction.
911         * @return void
912         */
913         function _xdr(o, c) {
914                 o.c.onprogress = function() { _rS[o.id] = 3; }
915                 o.c.onload = function() {
916                         _rS[o.id] = 4;
917                         Y.io.xdrResponse(o, c, 'success');
918                 };
919                 o.c.onerror = function() {
920                         _rS[o.id] = 4;
921                         Y.io.xdrResponse(o, c, 'failure');
922                 };
923                 if (c.timeout) {
924                         o.c.ontimeout = function() {
925                                 _rS[o.id] = 4;
926                                 Y.io.xdrResponse(o, c, 'timeout');
927                         };
928                         o.c.timeout = c.timeout;
929                 }
930         }
931
932    /**
933         * @description Creates a response object for XDR transactions, for success
934         * and failure cases.
935         *
936         * @method _data
937         * @private
938         * @static
939     * @param {object} o - Transaction object generated by _create() in io-base.
940         * @param {boolean} isFlash - True if Flash was used as the transport.
941         * @param {boolean} isXML - True if the response data are XML.
942         *
943         * @return object
944         */
945         function _data(o, isFlash, isXML) {
946                 var text, xml;
947
948                 if (!o.status) {
949                         text = isFlash ? decodeURI(o.c.responseText) : o.c.responseText;
950                         xml = isXML ? Y.DataType.XML.parse(text) : null;
951
952                         return { id: o.id, c: { responseText: text, responseXML: xml } };
953                 }
954                 else {
955                         return { id: o.id, status: o.status };
956                 }
957
958         }
959
960    /**
961         * @description Method for intiating an XDR transaction abort.
962         *
963         * @method _abort
964         * @private
965         * @static
966         * @param {object} o - Transaction object generated by _create() in io-base.
967         * @param {object} c - configuration object for the transaction.
968         */
969         function _abort(o, c) {
970                 return c.xdr.use === 'flash' ? o.c.abort(o.id, c) : o.c.abort();
971         }
972
973    /**
974         * @description Method for determining if an XDR transaction has completed
975         * and all data are received.
976         *
977         * @method _isInProgress.
978         * @private
979         * @static
980         * @param {object} o - Transaction object generated by _create() in io-base.
981         * @param {object} c - configuration object for the transaction.
982         */
983         function _isInProgress(o, t) {
984                 return (t === 'flash' && o.c) ? o.c.isInProgress(o.id) : _rS[o.id] !== 4;
985         }
986
987     Y.mix(Y.io, {
988
989            /**
990                 * @description Map of io transports.
991                 *
992                 * @property _transport
993                 * @private
994                 * @static
995                 * @type object
996                 */
997                 _transport: {},
998
999            /**
1000                 * @description Method for accessing the transport's interface for making a
1001                 * cross-domain transaction.
1002                 *
1003                 * @method _xdr
1004                 * @private
1005                 * @static
1006                 * @param {string} uri - qualified path to transaction resource.
1007         * @param {object} o - Transaction object generated by _create() in io-base.
1008                 * @param {object} c - configuration object for the transaction.
1009                 */
1010                 xdr: function(uri, o, c) {
1011                         if (c.on && c.xdr.use === 'flash') {
1012                                 _fn[o.id] = {
1013                                         on: c.on,
1014                                         context: c.context,
1015                                         arguments: c.arguments
1016                                 };
1017                                 // These nodes do not need to be serialized across Flash's
1018                                 // ExternalInterface.  Doing so will result in exceptions.
1019                                 c.context = null;
1020                                 c.form = null;
1021
1022                                 o.c.send(uri, c, o.id);
1023                         }
1024                         else if (window.XDomainRequest) {
1025                                 _xdr(o, c);
1026                                 o.c.open(c.method || 'GET', uri);
1027                                 o.c.send(c.data);
1028                         }
1029
1030                         return {
1031                                 id: o.id,
1032                                 abort: function() {
1033                                         return o.c ? _abort(o, c) : false;
1034                                 },
1035                                 isInProgress: function() {
1036                                         return o.c ? _isInProgress(o, c.xdr.use) : false;
1037                                 }
1038                         }
1039                 },
1040
1041            /**
1042                 * @description Response controller for cross-domain requests when using the
1043                 * Flash transport or IE8's XDomainRequest object.
1044                 *
1045                 * @method xdrResponse
1046                 * @private
1047                 * @static
1048         * @param {object} o - Transaction object generated by _create() in io-base.
1049                 * @param {object} c - configuration object for the transaction.
1050                 * @param {string} e - Event name
1051                 * @return object
1052                 */
1053                 xdrResponse: function(o, c, e) {
1054                         var m, fn,
1055                                 isFlash = c.xdr.use === 'flash' ? true : false,
1056                                 isXML = c.xdr.dataType === 'xml' ? true : false;
1057                                 c.on = c.on || {};
1058
1059                         if (isFlash) {
1060                                 m = _fn || {};
1061                                 fn = m[o.id] ? m[o.id] : null;
1062                                 if (fn) {
1063                                         c.on = fn.on;
1064                                         c.context = fn.context;
1065                                         c.arguments = fn.arguments;
1066                                 }
1067                         }
1068                         if (e === ('abort' || 'timeout')) {
1069                                 o.status = e;
1070                         }
1071
1072                         switch (e) {
1073                                 case 'start':
1074                                         Y.io.start(o.id, c);
1075                                         break;
1076                                 case 'success':
1077                                         Y.io.success(_data(o, isFlash, isXML), c);
1078                                         isFlash ? delete m[o.id] : delete _rS[o.id];
1079                                         break;
1080                                 case 'timeout':
1081                                 case 'abort':
1082                                 case 'failure':
1083                                         Y.io.failure(_data(o, isFlash, isXML), c);
1084                                         isFlash ? delete m[o.id] : delete _rS[o.id];
1085                                         break;
1086                         }
1087                 },
1088
1089            /**
1090                 * @description Fires event "io:xdrReady"
1091                 *
1092                 * @method xdrReady
1093                 * @private
1094                 * @static
1095                 * @param {number} id - transaction id
1096                 * @param {object} c - configuration object for the transaction.
1097                 *
1098                 * @return void
1099                 */
1100                 xdrReady: function(id) {
1101                         Y.fire(E_XDR_READY, id);
1102                 },
1103
1104            /**
1105                 * @description Method to initialize the desired transport.
1106                 *
1107                 * @method transport
1108                 * @public
1109                 * @static
1110                 * @param {object} o - object of transport configurations.
1111                 * @return void
1112                 */
1113                 transport: function(o) {
1114                         var id = o.yid ? o.yid : Y.id;
1115
1116                         _swf(o.src, id);
1117                         this._transport.flash = Y.config.doc.getElementById('yuiIoSwf');
1118                 }
1119         });
1120
1121
1122
1123 }, '3.0.0' ,{requires:['io-base','datatype-xml']});
1124
1125 YUI.add('io-upload-iframe', function(Y) {
1126
1127    /**
1128         * Extends the IO base class to enable file uploads, with HTML forms,
1129         * using an iframe as the transport medium.
1130         * @module io
1131         * @submodule io-upload-iframe
1132         */
1133
1134         var w = Y.config.win;
1135    /**
1136         * @description Parses the POST data object and creates hidden form elements
1137         * for each key-value, and appends them to the HTML form object.
1138         * @method appendData
1139         * @private
1140         * @static
1141         * @param {object} f HTML form object.
1142         * @param {string} s The key-value POST data.
1143         * @return {array} o Array of created fields.
1144         */
1145         function _addData(f, s) {
1146                 var o = [],
1147                         m = s.split('='),
1148                         i, l;
1149
1150                 for (i = 0, l = m.length - 1; i < l; i++) {
1151                         o[i] = document.createElement('input');
1152                         o[i].type = 'hidden';
1153                         o[i].name = m[i].substring(m[i].lastIndexOf('&') + 1);
1154                         o[i].value = (i + 1 === l) ? m[i + 1] : m[i + 1].substring(0, (m[i + 1].lastIndexOf('&')));
1155                         f.appendChild(o[i]);
1156                 }
1157
1158                 return o;
1159         }
1160
1161    /**
1162         * @description Removes the custom fields created to pass additional POST
1163         * data, along with the HTML form fields.
1164         * @method f
1165         * @private
1166         * @static
1167         * @param {object} f HTML form object.
1168         * @param {object} o HTML form fields created from configuration.data.
1169         * @return {void}
1170         */
1171         function _removeData(f, o) {
1172                 var i, l;
1173
1174                 for(i = 0, l = o.length; i < l; i++){
1175                         f.removeChild(o[i]);
1176                 }
1177         }
1178
1179    /**
1180         * @description Sets the appropriate attributes and values to the HTML
1181         * form, in preparation of a file upload transaction.
1182         * @method _setAttrs
1183         * @private
1184         * @static
1185         * @param {object} f HTML form object.
1186         * @param {object} id The Transaction ID.
1187         * @param {object} uri Qualified path to transaction resource.
1188         * @return {void}
1189         */
1190         function _setAttrs(f, id, uri) {
1191                 var ie8 = (document.documentMode && document.documentMode === 8) ? true : false;
1192
1193                 f.setAttribute('action', uri);
1194                 f.setAttribute('method', 'POST');
1195                 f.setAttribute('target', 'ioupload' + id );
1196                 f.setAttribute(Y.UA.ie && !ie8 ? 'encoding' : 'enctype', 'multipart/form-data');
1197         }
1198
1199    /**
1200         * @description Sets the appropriate attributes and values to the HTML
1201         * form, in preparation of a file upload transaction.
1202         * @method _resetAttrs
1203         * @private
1204         * @static
1205         * @param {object} f HTML form object.
1206         * @param {object} a Object of original attributes.
1207         * @return {void}
1208         */
1209         function _resetAttrs(f, a){
1210                 var p;
1211
1212                 for (p in a) {
1213                         if (a.hasOwnProperty(a, p)) {
1214                                 if (a[p]) {
1215                                         f.setAttribute(p, f[p]);
1216                                 }
1217                                 else {
1218                                         f.removeAttribute(p);
1219                                 }
1220                         }
1221                 }
1222         }
1223
1224    /**
1225         * @description Creates the iframe transported used in file upload
1226         * transactions, and binds the response event handler.
1227         *
1228         * @method _create
1229         * @private
1230         * @static
1231     * @param {object} o Transaction object generated by _create().
1232     * @param {object} c Configuration object passed to YUI.io().
1233     * @return {void}
1234         */
1235         function _create(o, c) {
1236                 var i = Y.Node.create('<iframe id="ioupload' + o.id + '" name="ioupload' + o.id + '" />');
1237                         i._node.style.position = 'absolute';
1238                         i._node.style.top = '-1000px';
1239                         i._node.style.left = '-1000px';
1240
1241                 Y.one('body').appendChild(i);
1242                 // Bind the onload handler to the iframe to detect the file upload response.
1243                 Y.on("load", function() { _handle(o, c) }, '#ioupload' + o.id);
1244         }
1245
1246    /**
1247         * @description Bound to the iframe's Load event and processes
1248         * the response data.
1249         * @method _handle
1250         * @private
1251         * @static
1252         * @param {o} o The transaction object
1253         * @param {object} c Configuration object for the transaction.
1254         * @return {void}
1255         */
1256         function _handle(o, c) {
1257                 var d = Y.one('#ioupload' + o.id).get('contentWindow.document'),
1258                         b = d.one('body'),
1259                         xml = (d._node.nodeType === 9),
1260                         p;
1261
1262                 if (c.timeout) {
1263                         _clearTimeout(o.id);
1264                 }
1265
1266                 if (b) {
1267                         // When a response Content-Type of "text/plain" is used, Firefox and Safari
1268                         // will wrap the response string with <pre></pre>.
1269                         p = b.query('pre:first-child');
1270                         o.c.responseText = p ? p.get('innerHTML') : b.get('innerHTML');
1271                 }
1272                 else if (xml) {
1273                         o.c.responseXML =  d._node;
1274                 }
1275
1276                 Y.io.complete(o, c);
1277                 Y.io.end(o, c);
1278                 // The transaction is complete, so call _destroy to remove
1279                 // the event listener bound to the iframe transport, and then
1280                 // destroy the iframe.
1281                 w.setTimeout( function() { _destroy(o.id); }, 0);
1282         }
1283
1284    /**
1285         * @description Starts timeout count if the configuration object
1286         * has a defined timeout property.
1287         *
1288         * @method _startTimeout
1289         * @private
1290         * @static
1291     * @param {object} o Transaction object generated by _create().
1292     * @param {object} c Configuration object passed to YUI.io().
1293     * @return {void}
1294         */
1295         function _startTimeout(o, c) {
1296                 Y.io._timeout[o.id] = w.setTimeout(
1297                         function() {
1298                                 var r = { id: o.id, status: 'timeout' };
1299
1300                                 Y.io.complete(r, c);
1301                                 Y.io.end(r, c);
1302                         }, c.timeout);
1303         }
1304
1305    /**
1306         * @description Clears the timeout interval started by _startTimeout().
1307         * @method _clearTimeout
1308         * @private
1309         * @static
1310     * @param {number} id - Transaction ID.
1311     * @return {void}
1312         */
1313         function _clearTimeout(id) {
1314                 w.clearTimeout(Y.io._timeout[id]);
1315                 delete Y.io._timeout[id];
1316         }
1317
1318    /**
1319         * @description
1320         * @method _destroy
1321         * @private
1322         * @static
1323         * @param {o} o The transaction object
1324         * @param {object} uri Qualified path to transaction resource.
1325         * @param {object} c Configuration object for the transaction.
1326         * @return {void}
1327         */
1328         function _destroy(id) {
1329                 Y.Event.purgeElement('#ioupload' + id, false);
1330                 Y.one('body').removeChild(Y.one('#ioupload' + id));
1331         }
1332
1333         Y.mix(Y.io, {
1334            /**
1335                 * @description Uploads HTML form data, inclusive of files/attachments,
1336                 * using the iframe created in _create to facilitate the transaction.
1337                 * @method _upload
1338                 * @private
1339                 * @static
1340                 * @param {o} o The transaction object
1341                 * @param {object} uri Qualified path to transaction resource.
1342                 * @param {object} c Configuration object for the transaction.
1343                 * @return {void}
1344                 */
1345                 _upload: function(o, uri, c) {
1346                         var f = (typeof c.form.id === 'string') ? Y.config.doc.getElementById(c.form.id) : c.form.id,
1347                                 fields,
1348                                 // Track original HTML form attribute values.
1349                                 attr = {
1350                                         action: f.getAttribute('action'),
1351                                         target: f.getAttribute('target')
1352                                 };
1353
1354                         _create(o, c);
1355                         // Initialize the HTML form properties in case they are
1356                         // not defined in the HTML form.
1357                         _setAttrs(f, o.id, uri);
1358                         if (c.data) {
1359                                 fields = _addData(f, c.data);
1360                         }
1361
1362                         // Start polling if a callback is present and the timeout
1363                         // property has been defined.
1364                         if (c.timeout) {
1365                                 _startTimeout(o, c);
1366                         }
1367
1368                         // Start file upload.
1369                         f.submit();
1370                         Y.io.start(o.id, c);
1371                         if (c.data) {
1372                                 _removeData(f, fields);
1373                         }
1374                         // Restore HTML form attributes to their original values.
1375                         _resetAttrs(f, attr);
1376
1377                         return {
1378                                 id: o.id,
1379                                 abort: function() {
1380                                         var r = { id: o.id, status: 'abort' };
1381
1382                                         if (Y.one('#ioupload' + o.id)) {
1383                                                 _destroy(o.id);
1384                                                 Y.io.complete(r, c);
1385                                                 Y.io.end(r, c);
1386                                         }
1387                                         else {
1388                                                 return false;
1389                                         }
1390                                 },
1391                                 isInProgress: function() {
1392                                         return Y.one('#ioupload' + o.id) ? true : false;
1393                                 }
1394                         }
1395                 }
1396         });
1397
1398
1399
1400 }, '3.0.0' ,{requires:['io-base','node-base','event-base']});
1401
1402 YUI.add('io-queue', function(Y) {
1403
1404    /**
1405     * Extends the IO base class to implement Queue for synchronous
1406     * transaction processing.
1407         * @module io
1408         * @submodule io-queue
1409         */
1410
1411    /**
1412         * @description Array of transactions queued for processing
1413         *
1414         * @property _yQ
1415         * @private
1416         * @static
1417         * @type Object
1418         */
1419         var _q = new Y.Queue(),
1420
1421    /**
1422         * @description Reference to "io:complete" event handler.
1423         *
1424         * @property _e
1425         * @private
1426         * @static
1427         * @type Object
1428         */
1429         _e,
1430
1431         _activeId,
1432    /**
1433         * @description Property to determine whether the queue is set to
1434         * 1 (active) or 0 (inactive).  When inactive, transactions
1435         * will be stored in the queue until the queue is set to active.
1436         *
1437         * @property _qState
1438         * @private
1439         * @static
1440         * @type int
1441         */
1442         _qState = 1;
1443
1444    /**
1445         * @description Method for requesting a transaction, and queueing the
1446         * request before it is sent to the resource.
1447         *
1448         * @method _queue
1449         * @private
1450         * @static
1451         * @return Object
1452         */
1453         function _queue(uri, c) {
1454                 var o = { uri: uri, id: Y.io._id(), cfg:c };
1455
1456                 _q.add(o);
1457                 if (_qState === 1) {
1458                         _shift();
1459                 }
1460
1461                 return o;
1462         }
1463
1464    /**
1465         * @description Method Process the first transaction from the
1466         * queue in FIFO order.
1467         *
1468         * @method _shift
1469         * @private
1470         * @static
1471         * @return void
1472         */
1473         function _shift() {
1474                 var o = _q.next();
1475
1476                 _activeId = o.id;
1477                 _qState = 0;
1478                 Y.io(o.uri, o.cfg, o.id);
1479         }
1480
1481    /**
1482         * @description Method for promoting a transaction to the top of the queue.
1483         *
1484         * @method _unshift
1485         * @private
1486         * @static
1487         * @return void
1488         */
1489         function _unshift(o) {
1490                 _q.promote(o);
1491         }
1492
1493         function _next(id) {
1494                 _qState = 1;
1495                 if (_activeId === id && _q.size() > 0) {
1496                         _shift();
1497                 }
1498         }
1499
1500    /**
1501         * @description Method for removing a specific, pending transaction from
1502         * the queue.
1503         *
1504         * @method _remove
1505         * @private
1506         * @static
1507         * @return void
1508         */
1509         function _remove(o) {
1510                 _q.remove(o);
1511         }
1512
1513         function _start() {
1514                 _qState = 1;
1515
1516                 if (_q.size() > 0) {
1517                         _shift();
1518                 }
1519         }
1520
1521    /**
1522         * @description Method for setting queue processing to inactive.
1523         * Transaction requests to YUI.io.queue() will be stored in the queue, but
1524         * not processed until the queue is reset to "active".
1525         *
1526         * @method _stop
1527         * @private
1528         * @static
1529         * @return void
1530         */
1531         function _stop() {
1532                 _qState = 0;
1533         };
1534
1535    /**
1536         * @description Method to query the current size of the queue.
1537         *
1538         * @method _size
1539         * @private
1540         * @static
1541         * @return int
1542         */
1543         function _size() {
1544                 return _q.size();
1545         };
1546
1547         _e = Y.on('io:complete', function(id) { _next(id); }, Y.io);
1548
1549    /**
1550         * @description Method to query the current size of the queue, or to
1551         * set a maximum queue size.  This is the interface for _size().
1552         *
1553         * @method size
1554         * @public
1555         * @static
1556         * @param {number} i - Specified maximum size of queue.
1557     * @return number
1558         */
1559         _queue.size = _size;
1560
1561    /**
1562         * @description Method for setting the queue to active. If there are
1563         * transactions pending in the queue, they will be processed from the
1564         * queue in FIFO order. This is the interface for _start().
1565         *
1566         * @method start
1567         * @public
1568         * @static
1569     * @return void
1570         */
1571         _queue.start = _start;
1572
1573    /**
1574         * @description Method for setting queue processing to inactive.
1575         * Transaction requests to YUI.io.queue() will be stored in the queue, but
1576         * not processed until the queue is restarted. This is the
1577         * interface for _stop().
1578         *
1579         * @method stop
1580         * @public
1581         * @static
1582     * @return void
1583         */
1584         _queue.stop = _stop;
1585
1586    /**
1587         * @description Method for promoting a transaction to the top of the queue.
1588         * This is the interface for _unshift().
1589         *
1590         * @method promote
1591         * @public
1592         * @static
1593         * @param {Object} o - Reference to queued transaction.
1594     * @return void
1595         */
1596         _queue.promote = _unshift;
1597
1598    /**
1599         * @description Method for removing a specific, pending transaction from
1600         * the queue. This is the interface for _remove().
1601         *
1602         * @method remove
1603         * @public
1604         * @static
1605         * @param {Object} o - Reference to queued transaction.
1606     * @return void
1607         */
1608         _queue.remove = _remove;
1609
1610     Y.mix(Y.io, {
1611                 queue: _queue
1612     }, true);
1613
1614
1615
1616 }, '3.0.0' ,{requires:['io-base','queue-promote']});
1617
1618
1619
1620 YUI.add('io', function(Y){}, '3.0.0' ,{use:['io-base', 'io-form', 'io-xdr', 'io-upload-iframe', 'io-queue']});
1621