~bcsaller/juju-gui/update-reductions

« back to all changes in this revision

Viewing changes to lib/yui/build/io-base/io-base-debug.js

  • Committer: kapil.foss at gmail
  • Date: 2012-07-13 18:45:59 UTC
  • Revision ID: kapil.foss@gmail.com-20120713184559-2xl7be17egsrz0c9
reshape

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
YUI 3.5.1 (build 22)
3
 
Copyright 2012 Yahoo! Inc. All rights reserved.
4
 
Licensed under the BSD License.
5
 
http://yuilibrary.com/license/
6
 
*/
7
 
YUI.add('io-base', function(Y) {
8
 
 
9
 
/**
10
 
Base IO functionality. Provides basic XHR transport support.
11
 
@module io-base
12
 
@main io-base
13
 
@for IO
14
 
**/
15
 
 
16
 
var // List of events that comprise the IO event lifecycle.
17
 
    EVENTS = ['start', 'complete', 'end', 'success', 'failure', 'progress'],
18
 
 
19
 
    // Whitelist of used XHR response object properties.
20
 
    XHR_PROPS = ['status', 'statusText', 'responseText', 'responseXML'],
21
 
 
22
 
    win = Y.config.win,
23
 
    uid = 0;
24
 
 
25
 
/**
26
 
The IO class is a utility that brokers HTTP requests through a simplified
27
 
interface.  Specifically, it allows JavaScript to make HTTP requests to
28
 
a resource without a page reload.  The underlying transport for making
29
 
same-domain requests is the XMLHttpRequest object.  IO can also use
30
 
Flash, if specified as a transport, for cross-domain requests.
31
 
 
32
 
@class IO
33
 
@constructor
34
 
@param {Object} config Object of EventTarget's publish method configurations
35
 
                    used to configure IO's events.
36
 
**/
37
 
function IO (config) {
38
 
    var io = this;
39
 
 
40
 
    io._uid = 'io:' + uid++;
41
 
    io._init(config);
42
 
    Y.io._map[io._uid] = io;
43
 
}
44
 
 
45
 
IO.prototype = {
46
 
    //--------------------------------------
47
 
    //  Properties
48
 
    //--------------------------------------
49
 
 
50
 
   /**
51
 
    * A counter that increments for each transaction.
52
 
    *
53
 
    * @property _id
54
 
    * @private
55
 
    * @type {Number}
56
 
    */
57
 
    _id: 0,
58
 
 
59
 
   /**
60
 
    * Object of IO HTTP headers sent with each transaction.
61
 
    *
62
 
    * @property _headers
63
 
    * @private
64
 
    * @type {Object}
65
 
    */
66
 
    _headers: {
67
 
        'X-Requested-With' : 'XMLHttpRequest'
68
 
    },
69
 
 
70
 
   /**
71
 
    * Object that stores timeout values for any transaction with a defined
72
 
    * "timeout" configuration property.
73
 
    *
74
 
    * @property _timeout
75
 
    * @private
76
 
    * @type {Object}
77
 
    */
78
 
    _timeout: {},
79
 
 
80
 
    //--------------------------------------
81
 
    //  Methods
82
 
    //--------------------------------------
83
 
 
84
 
    _init: function(config) {
85
 
        var io = this, i, len;
86
 
 
87
 
        io.cfg = config || {};
88
 
 
89
 
        Y.augment(io, Y.EventTarget);
90
 
        for (i = 0, len = EVENTS.length; i < len; ++i) {
91
 
            // Publish IO global events with configurations, if any.
92
 
            // IO global events are set to broadcast by default.
93
 
            // These events use the "io:" namespace.
94
 
            io.publish('io:' + EVENTS[i], Y.merge({ broadcast: 1 }, config));
95
 
            // Publish IO transaction events with configurations, if
96
 
            // any.  These events use the "io-trn:" namespace.
97
 
            io.publish('io-trn:' + EVENTS[i], config);
98
 
        }
99
 
    },
100
 
 
101
 
   /**
102
 
    * Method that creates a unique transaction object for each request.
103
 
    *
104
 
    * @method _create
105
 
    * @private
106
 
    * @param {Object} cfg Configuration object subset to determine if
107
 
    *                 the transaction is an XDR or file upload,
108
 
    *                 requiring an alternate transport.
109
 
    * @param {Number} id Transaction id
110
 
    * @return {Object} The transaction object
111
 
    */
112
 
    _create: function(config, id) {
113
 
        var io = this,
114
 
            transaction = {
115
 
                id : Y.Lang.isNumber(id) ? id : io._id++,
116
 
                uid: io._uid
117
 
            },
118
 
            alt = config.xdr ? config.xdr.use : null,
119
 
            form = config.form && config.form.upload ? 'iframe' : null,
120
 
            use;
121
 
 
122
 
        if (alt === 'native') {
123
 
            // Non-IE  can use XHR level 2 and not rely on an
124
 
            // external transport.
125
 
            alt = Y.UA.ie ? 'xdr' : null;
126
 
        }
127
 
 
128
 
        use = alt || form;
129
 
        transaction = use ? Y.merge(Y.IO.customTransport(use), transaction) :
130
 
                            Y.merge(Y.IO.defaultTransport(), transaction);
131
 
 
132
 
        if (transaction.notify) {
133
 
            config.notify = function (e, t, c) { io.notify(e, t, c); };
134
 
        }
135
 
 
136
 
        if (!use) {
137
 
            if (win && win.FormData && config.data instanceof FormData) {
138
 
                transaction.c.upload.onprogress = function (e) {
139
 
                    io.progress(transaction, e, config);
140
 
                };
141
 
                transaction.c.onload = function (e) {
142
 
                    io.load(transaction, e, config);
143
 
                };
144
 
                transaction.c.onerror = function (e) {
145
 
                    io.error(transaction, e, config);
146
 
                };
147
 
                transaction.upload = true;
148
 
            }
149
 
        }
150
 
 
151
 
        return transaction;
152
 
    },
153
 
 
154
 
    _destroy: function(transaction) {
155
 
        if (win && !transaction.notify && !transaction.xdr) {
156
 
            if (XHR && !transaction.upload) {
157
 
                transaction.c.onreadystatechange = null;
158
 
            } else if (transaction.upload) {
159
 
                transaction.c.upload.onprogress = null;
160
 
                transaction.c.onload = null;
161
 
                transaction.c.onerror = null;
162
 
            } else if (Y.UA.ie && !transaction.e) {
163
 
                // IE, when using XMLHttpRequest as an ActiveX Object, will throw
164
 
                // a "Type Mismatch" error if the event handler is set to "null".
165
 
                transaction.c.abort();
166
 
            }
167
 
        }
168
 
 
169
 
        transaction = transaction.c = null;
170
 
    },
171
 
 
172
 
   /**
173
 
    * Method for creating and firing events.
174
 
    *
175
 
    * @method _evt
176
 
    * @private
177
 
    * @param {String} eventName Event to be published.
178
 
    * @param {Object} transaction Transaction object.
179
 
    * @param {Object} config Configuration data subset for event subscription.
180
 
    */
181
 
    _evt: function(eventName, transaction, config) {
182
 
        var io          = this, params,
183
 
            args        = config['arguments'],
184
 
            emitFacade  = io.cfg.emitFacade,
185
 
            globalEvent = "io:" + eventName,
186
 
            trnEvent    = "io-trn:" + eventName;
187
 
 
188
 
        // Workaround for #2532107
189
 
        this.detach(trnEvent);
190
 
 
191
 
        if (transaction.e) {
192
 
            transaction.c = { status: 0, statusText: transaction.e };
193
 
        }
194
 
 
195
 
        // Fire event with parameters or an Event Facade.
196
 
        params = [ emitFacade ?
197
 
            {
198
 
                id: transaction.id,
199
 
                data: transaction.c,
200
 
                cfg: config,
201
 
                'arguments': args
202
 
            } :
203
 
            transaction.id
204
 
        ];
205
 
 
206
 
        if (!emitFacade) {
207
 
            if (eventName === EVENTS[0] || eventName === EVENTS[2]) {
208
 
                if (args) {
209
 
                    params.push(args);
210
 
                }
211
 
            } else {
212
 
                if (transaction.evt) {
213
 
                    params.push(transaction.evt);
214
 
                } else {
215
 
                    params.push(transaction.c);
216
 
                }
217
 
                if (args) {
218
 
                    params.push(args);
219
 
                }
220
 
            }
221
 
        }
222
 
 
223
 
        params.unshift(globalEvent);
224
 
        // Fire global events.
225
 
        io.fire.apply(io, params);
226
 
        // Fire transaction events, if receivers are defined.
227
 
        if (config.on) {
228
 
            params[0] = trnEvent;
229
 
            io.once(trnEvent, config.on[eventName], config.context || Y);
230
 
            io.fire.apply(io, params);
231
 
        }
232
 
    },
233
 
 
234
 
   /**
235
 
    * Fires event "io:start" and creates, fires a transaction-specific
236
 
    * start event, if `config.on.start` is defined.
237
 
    *
238
 
    * @method start
239
 
    * @param {Object} transaction Transaction object.
240
 
    * @param {Object} config Configuration object for the transaction.
241
 
    */
242
 
    start: function(transaction, config) {
243
 
       /**
244
 
        * Signals the start of an IO request.
245
 
        * @event io:start
246
 
        */
247
 
        this._evt(EVENTS[0], transaction, config);
248
 
    },
249
 
 
250
 
   /**
251
 
    * Fires event "io:complete" and creates, fires a
252
 
    * transaction-specific "complete" event, if config.on.complete is
253
 
    * defined.
254
 
    *
255
 
    * @method complete
256
 
    * @param {Object} transaction Transaction object.
257
 
    * @param {Object} config Configuration object for the transaction.
258
 
    */
259
 
    complete: function(transaction, config) {
260
 
       /**
261
 
        * Signals the completion of the request-response phase of a
262
 
        * transaction. Response status and data are accessible, if
263
 
        * available, in this event.
264
 
        * @event io:complete
265
 
        */
266
 
        this._evt(EVENTS[1], transaction, config);
267
 
    },
268
 
 
269
 
   /**
270
 
    * Fires event "io:end" and creates, fires a transaction-specific "end"
271
 
    * event, if config.on.end is defined.
272
 
    *
273
 
    * @method end
274
 
    * @param {Object} transaction Transaction object.
275
 
    * @param {Object} config Configuration object for the transaction.
276
 
    */
277
 
    end: function(transaction, config) {
278
 
       /**
279
 
        * Signals the end of the transaction lifecycle.
280
 
        * @event io:end
281
 
        */
282
 
        this._evt(EVENTS[2], transaction, config);
283
 
        this._destroy(transaction);
284
 
    },
285
 
 
286
 
   /**
287
 
    * Fires event "io:success" and creates, fires a transaction-specific
288
 
    * "success" event, if config.on.success is defined.
289
 
    *
290
 
    * @method success
291
 
    * @param {Object} transaction Transaction object.
292
 
    * @param {Object} config Configuration object for the transaction.
293
 
    */
294
 
    success: function(transaction, config) {
295
 
       /**
296
 
        * Signals an HTTP response with status in the 2xx range.
297
 
        * Fires after io:complete.
298
 
        * @event io:success
299
 
        */
300
 
        this._evt(EVENTS[3], transaction, config);
301
 
        this.end(transaction, config);
302
 
    },
303
 
 
304
 
   /**
305
 
    * Fires event "io:failure" and creates, fires a transaction-specific
306
 
    * "failure" event, if config.on.failure is defined.
307
 
    *
308
 
    * @method failure
309
 
    * @param {Object} transaction Transaction object.
310
 
    * @param {Object} config Configuration object for the transaction.
311
 
    */
312
 
    failure: function(transaction, config) {
313
 
       /**
314
 
        * Signals an HTTP response with status outside of the 2xx range.
315
 
        * Fires after io:complete.
316
 
        * @event io:failure
317
 
        */
318
 
        this._evt(EVENTS[4], transaction, config);
319
 
        this.end(transaction, config);
320
 
    },
321
 
 
322
 
   /**
323
 
    * Fires event "io:progress" and creates, fires a transaction-specific
324
 
    * "progress" event -- for XMLHttpRequest file upload -- if
325
 
    * config.on.progress is defined.
326
 
    *
327
 
    * @method progress
328
 
    * @param {Object} transaction Transaction object.
329
 
    * @param {Object} progress event.
330
 
    * @param {Object} config Configuration object for the transaction.
331
 
    */
332
 
    progress: function(transaction, e, config) {
333
 
       /**
334
 
        * Signals the interactive state during a file upload transaction.
335
 
        * This event fires after io:start and before io:complete.
336
 
        * @event io:progress
337
 
        */
338
 
        transaction.evt = e;
339
 
        this._evt(EVENTS[5], transaction, config);
340
 
    },
341
 
 
342
 
   /**
343
 
    * Fires event "io:complete" and creates, fires a transaction-specific
344
 
    * "complete" event -- for XMLHttpRequest file upload -- if
345
 
    * config.on.complete is defined.
346
 
    *
347
 
    * @method load
348
 
    * @param {Object} transaction Transaction object.
349
 
    * @param {Object} load event.
350
 
    * @param {Object} config Configuration object for the transaction.
351
 
    */
352
 
    load: function (transaction, e, config) {
353
 
        transaction.evt = e.target;
354
 
        this._evt(EVENTS[1], transaction, config);
355
 
    },
356
 
 
357
 
   /**
358
 
    * Fires event "io:failure" and creates, fires a transaction-specific
359
 
    * "failure" event -- for XMLHttpRequest file upload -- if
360
 
    * config.on.failure is defined.
361
 
    *
362
 
    * @method error
363
 
    * @param {Object} transaction Transaction object.
364
 
    * @param {Object} error event.
365
 
    * @param {Object} config Configuration object for the transaction.
366
 
    */
367
 
    error: function (transaction, e, config) {
368
 
        transaction.evt = e;
369
 
        this._evt(EVENTS[4], transaction, config);
370
 
    },
371
 
 
372
 
   /**
373
 
    * Retry an XDR transaction, using the Flash tranport, if the native
374
 
    * transport fails.
375
 
    *
376
 
    * @method _retry
377
 
    * @private
378
 
    * @param {Object} transaction Transaction object.
379
 
    * @param {String} uri Qualified path to transaction resource.
380
 
    * @param {Object} config Configuration object for the transaction.
381
 
    */
382
 
    _retry: function(transaction, uri, config) {
383
 
        this._destroy(transaction);
384
 
        config.xdr.use = 'flash';
385
 
        return this.send(uri, config, transaction.id);
386
 
    },
387
 
 
388
 
   /**
389
 
    * Method that concatenates string data for HTTP GET transactions.
390
 
    *
391
 
    * @method _concat
392
 
    * @private
393
 
    * @param {String} uri URI or root data.
394
 
    * @param {String} data Data to be concatenated onto URI.
395
 
    * @return {String}
396
 
    */
397
 
    _concat: function(uri, data) {
398
 
        uri += (uri.indexOf('?') === -1 ? '?' : '&') + data;
399
 
        return uri;
400
 
    },
401
 
 
402
 
   /**
403
 
    * Stores default client headers for all transactions. If a label is
404
 
    * passed with no value argument, the header will be deleted.
405
 
    *
406
 
    * @method setHeader
407
 
    * @param {String} name HTTP header
408
 
    * @param {String} value HTTP header value
409
 
    */
410
 
    setHeader: function(name, value) {
411
 
        if (value) {
412
 
            this._headers[name] = value;
413
 
        } else {
414
 
            delete this._headers[name];
415
 
        }
416
 
    },
417
 
 
418
 
   /**
419
 
    * Method that sets all HTTP headers to be sent in a transaction.
420
 
    *
421
 
    * @method _setHeaders
422
 
    * @private
423
 
    * @param {Object} transaction - XHR instance for the specific transaction.
424
 
    * @param {Object} headers - HTTP headers for the specific transaction, as
425
 
    *                    defined in the configuration object passed to YUI.io().
426
 
    */
427
 
    _setHeaders: function(transaction, headers) {
428
 
        headers = Y.merge(this._headers, headers);
429
 
        Y.Object.each(headers, function(value, name) {
430
 
            if (value !== 'disable') {
431
 
                transaction.setRequestHeader(name, headers[name]);
432
 
            }
433
 
        });
434
 
    },
435
 
 
436
 
   /**
437
 
    * Starts timeout count if the configuration object has a defined
438
 
    * timeout property.
439
 
    *
440
 
    * @method _startTimeout
441
 
    * @private
442
 
    * @param {Object} transaction Transaction object generated by _create().
443
 
    * @param {Object} timeout Timeout in milliseconds.
444
 
    */
445
 
    _startTimeout: function(transaction, timeout) {
446
 
        var io = this;
447
 
 
448
 
        io._timeout[transaction.id] = setTimeout(function() {
449
 
            io._abort(transaction, 'timeout');
450
 
        }, timeout);
451
 
    },
452
 
 
453
 
   /**
454
 
    * Clears the timeout interval started by _startTimeout().
455
 
    *
456
 
    * @method _clearTimeout
457
 
    * @private
458
 
    * @param {Number} id - Transaction id.
459
 
    */
460
 
    _clearTimeout: function(id) {
461
 
        clearTimeout(this._timeout[id]);
462
 
        delete this._timeout[id];
463
 
    },
464
 
 
465
 
   /**
466
 
    * Method that determines if a transaction response qualifies as success
467
 
    * or failure, based on the response HTTP status code, and fires the
468
 
    * appropriate success or failure events.
469
 
    *
470
 
    * @method _result
471
 
    * @private
472
 
    * @static
473
 
    * @param {Object} transaction Transaction object generated by _create().
474
 
    * @param {Object} config Configuration object passed to io().
475
 
    */
476
 
    _result: function(transaction, config) {
477
 
        var status;
478
 
        // Firefox will throw an exception if attempting to access
479
 
        // an XHR object's status property, after a request is aborted.
480
 
        try {
481
 
            status = transaction.c.status;
482
 
        } catch(e) {
483
 
            status = 0;
484
 
        }
485
 
 
486
 
        // IE reports HTTP 204 as HTTP 1223.
487
 
        if (status >= 200 && status < 300 || status === 304 || status === 1223) {
488
 
            this.success(transaction, config);
489
 
        } else {
490
 
            this.failure(transaction, config);
491
 
        }
492
 
    },
493
 
 
494
 
   /**
495
 
    * Event handler bound to onreadystatechange.
496
 
    *
497
 
    * @method _rS
498
 
    * @private
499
 
    * @param {Object} transaction Transaction object generated by _create().
500
 
    * @param {Object} config Configuration object passed to YUI.io().
501
 
    */
502
 
    _rS: function(transaction, config) {
503
 
        var io = this;
504
 
 
505
 
        if (transaction.c.readyState === 4) {
506
 
            if (config.timeout) {
507
 
                io._clearTimeout(transaction.id);
508
 
            }
509
 
 
510
 
            // Yield in the event of request timeout or abort.
511
 
            setTimeout(function() {
512
 
                io.complete(transaction, config);
513
 
                io._result(transaction, config);
514
 
            }, 0);
515
 
        }
516
 
    },
517
 
 
518
 
   /**
519
 
    * Terminates a transaction due to an explicit abort or timeout.
520
 
    *
521
 
    * @method _abort
522
 
    * @private
523
 
    * @param {Object} transaction Transaction object generated by _create().
524
 
    * @param {String} type Identifies timed out or aborted transaction.
525
 
    */
526
 
    _abort: function(transaction, type) {
527
 
        if (transaction && transaction.c) {
528
 
            transaction.e = type;
529
 
            transaction.c.abort();
530
 
        }
531
 
    },
532
 
 
533
 
   /**
534
 
    * Requests a transaction. `send()` is implemented as `Y.io()`.  Each
535
 
    * transaction may include a configuration object.  Its properties are:
536
 
    *
537
 
    * <dl>
538
 
    *   <dt>method</dt>
539
 
    *     <dd>HTTP method verb (e.g., GET or POST). If this property is not
540
 
    *         not defined, the default value will be GET.</dd>
541
 
    *
542
 
    *   <dt>data</dt>
543
 
    *     <dd>This is the name-value string that will be sent as the
544
 
    *     transaction data. If the request is HTTP GET, the data become
545
 
    *     part of querystring. If HTTP POST, the data are sent in the
546
 
    *     message body.</dd>
547
 
    *
548
 
    *   <dt>xdr</dt>
549
 
    *     <dd>Defines the transport to be used for cross-domain requests.
550
 
    *     By setting this property, the transaction will use the specified
551
 
    *     transport instead of XMLHttpRequest. The properties of the
552
 
    *     transport object are:
553
 
    *     <dl>
554
 
    *       <dt>use</dt>
555
 
    *         <dd>The transport to be used: 'flash' or 'native'</dd>
556
 
    *       <dt>dataType</dt>
557
 
    *         <dd>Set the value to 'XML' if that is the expected response
558
 
    *         content type.</dd>
559
 
    *     </dl></dd>
560
 
    *
561
 
    *   <dt>form</dt>
562
 
    *     <dd>Form serialization configuration object.  Its properties are:
563
 
    *     <dl>
564
 
    *       <dt>id</dt>
565
 
    *         <dd>Node object or id of HTML form</dd>
566
 
    *       <dt>useDisabled</dt>
567
 
    *         <dd>`true` to also serialize disabled form field values
568
 
    *         (defaults to `false`)</dd>
569
 
    *     </dl></dd>
570
 
    *
571
 
    *   <dt>on</dt>
572
 
    *     <dd>Assigns transaction event subscriptions. Available events are:
573
 
    *     <dl>
574
 
    *       <dt>start</dt>
575
 
    *         <dd>Fires when a request is sent to a resource.</dd>
576
 
    *       <dt>complete</dt>
577
 
    *         <dd>Fires when the transaction is complete.</dd>
578
 
    *       <dt>success</dt>
579
 
    *         <dd>Fires when the HTTP response status is within the 2xx
580
 
    *         range.</dd>
581
 
    *       <dt>failure</dt>
582
 
    *         <dd>Fires when the HTTP response status is outside the 2xx
583
 
    *         range, if an exception occurs, if the transation is aborted,
584
 
    *         or if the transaction exceeds a configured `timeout`.</dd>
585
 
    *       <dt>end</dt>
586
 
    *         <dd>Fires at the conclusion of the transaction
587
 
    *            lifecycle, after `success` or `failure`.</dd>
588
 
    *     </dl>
589
 
    *
590
 
    *     <p>Callback functions for `start` and `end` receive the id of the
591
 
    *     transaction as a first argument. For `complete`, `success`, and
592
 
    *     `failure`, callbacks receive the id and the response object
593
 
    *     (usually the XMLHttpRequest instance).  If the `arguments`
594
 
    *     property was included in the configuration object passed to
595
 
    *     `Y.io()`, the configured data will be passed to all callbacks as
596
 
    *     the last argument.</p>
597
 
    *     </dd>
598
 
    *
599
 
    *   <dt>sync</dt>
600
 
    *     <dd>Pass `true` to make a same-domain transaction synchronous.
601
 
    *     <strong>CAVEAT</strong>: This will negatively impact the user
602
 
    *     experience. Have a <em>very</em> good reason if you intend to use
603
 
    *     this.</dd>
604
 
    *
605
 
    *   <dt>context</dt>
606
 
    *     <dd>The "`this'" object for all configured event handlers. If a
607
 
    *     specific context is needed for individual callbacks, bind the
608
 
    *     callback to a context using `Y.bind()`.</dd>
609
 
    *
610
 
    *   <dt>headers</dt>
611
 
    *     <dd>Object map of transaction headers to send to the server. The
612
 
    *     object keys are the header names and the values are the header
613
 
    *     values.</dd>
614
 
    *
615
 
    *   <dt>timeout</dt>
616
 
    *     <dd>Millisecond threshold for the transaction before being
617
 
    *     automatically aborted.</dd>
618
 
    *
619
 
    *   <dt>arguments</dt>
620
 
    *     <dd>User-defined data passed to all registered event handlers.
621
 
    *     This value is available as the second argument in the "start" and
622
 
    *     "end" event handlers. It is the third argument in the "complete",
623
 
    *     "success", and "failure" event handlers. <strong>Be sure to quote
624
 
    *     this property name in the transaction configuration as
625
 
    *     "arguments" is a reserved word in JavaScript</strong> (e.g.
626
 
    *     `Y.io({ ..., "arguments": stuff })`).</dd>
627
 
    * </dl>
628
 
    *
629
 
    * @method send
630
 
    * @public
631
 
    * @param {String} uri Qualified path to transaction resource.
632
 
    * @param {Object} config Configuration object for the transaction.
633
 
    * @param {Number} id Transaction id, if already set.
634
 
    * @return {Object}
635
 
    */
636
 
    send: function(uri, config, id) {
637
 
        var transaction, method, i, len, sync, data,
638
 
            io = this,
639
 
            u = uri,
640
 
            response = {};
641
 
 
642
 
        config = config ? Y.Object(config) : {};
643
 
        transaction = io._create(config, id);
644
 
        method = config.method ? config.method.toUpperCase() : 'GET';
645
 
        sync = config.sync;
646
 
        data = config.data;
647
 
 
648
 
        // Serialize an map object into a key-value string using
649
 
        // querystring-stringify-simple.
650
 
        if ((Y.Lang.isObject(data) && !data.nodeType) && !transaction.upload) {
651
 
            data = Y.QueryString.stringify(data);
652
 
        }
653
 
 
654
 
        if (config.form) {
655
 
            if (config.form.upload) {
656
 
                // This is a file upload transaction, calling
657
 
                // upload() in io-upload-iframe.
658
 
                return io.upload(transaction, uri, config);
659
 
            } else {
660
 
                // Serialize HTML form data into a key-value string.
661
 
                data = io._serialize(config.form, data);
662
 
            }
663
 
        }
664
 
 
665
 
        if (data) {
666
 
            switch (method) {
667
 
                case 'GET':
668
 
                case 'HEAD':
669
 
                case 'DELETE':
670
 
                    u = io._concat(u, data);
671
 
                    data = '';
672
 
                    Y.log('HTTP' + method + ' with data.  The querystring is: ' + u, 'info', 'io');
673
 
                    break;
674
 
                case 'POST':
675
 
                case 'PUT':
676
 
                    // If Content-Type is defined in the configuration object, or
677
 
                    // or as a default header, it will be used instead of
678
 
                    // 'application/x-www-form-urlencoded; charset=UTF-8'
679
 
                    config.headers = Y.merge({
680
 
                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
681
 
                    }, config.headers);
682
 
                    break;
683
 
            }
684
 
        }
685
 
 
686
 
        if (transaction.xdr) {
687
 
            // Route data to io-xdr module for flash and XDomainRequest.
688
 
            return io.xdr(u, transaction, config);
689
 
        }
690
 
        else if (transaction.notify) {
691
 
            // Route data to custom transport
692
 
            return transaction.c.send(transaction, uri, config);
693
 
        }
694
 
 
695
 
        if (!sync && !transaction.upload) {
696
 
            transaction.c.onreadystatechange = function() {
697
 
                io._rS(transaction, config);
698
 
            };
699
 
        }
700
 
 
701
 
        try {
702
 
            // Determine if request is to be set as
703
 
            // synchronous or asynchronous.
704
 
            transaction.c.open(method, u, !sync, config.username || null, config.password || null);
705
 
            io._setHeaders(transaction.c, config.headers || {});
706
 
            io.start(transaction, config);
707
 
 
708
 
            // Will work only in browsers that implement the
709
 
            // Cross-Origin Resource Sharing draft.
710
 
            if (config.xdr && config.xdr.credentials) {
711
 
                if (!Y.UA.ie) {
712
 
                    transaction.c.withCredentials = true;
713
 
                }
714
 
            }
715
 
 
716
 
            // Using "null" with HTTP POST will result in a request
717
 
            // with no Content-Length header defined.
718
 
            transaction.c.send(data);
719
 
 
720
 
            if (sync) {
721
 
                // Create a response object for synchronous transactions,
722
 
                // mixing id and arguments properties with the xhr
723
 
                // properties whitelist.
724
 
                for (i = 0, len = XHR_PROPS.length; i < len; ++i) {
725
 
                    response[XHR_PROPS[i]] = transaction.c[XHR_PROPS[i]];
726
 
                }
727
 
 
728
 
                response.getAllResponseHeaders = function() {
729
 
                    return transaction.c.getAllResponseHeaders();
730
 
                };
731
 
 
732
 
                response.getResponseHeader = function(name) {
733
 
                    return transaction.c.getResponseHeader(name);
734
 
                };
735
 
 
736
 
                io.complete(transaction, config);
737
 
                io._result(transaction, config);
738
 
 
739
 
                return response;
740
 
            }
741
 
        } catch(e) {
742
 
            if (transaction.xdr) {
743
 
                // This exception is usually thrown by browsers
744
 
                // that do not support XMLHttpRequest Level 2.
745
 
                // Retry the request with the XDR transport set
746
 
                // to 'flash'.  If the Flash transport is not
747
 
                // initialized or available, the transaction
748
 
                // will resolve to a transport error.
749
 
                return io._retry(transaction, uri, config);
750
 
            } else {
751
 
                io.complete(transaction, config);
752
 
                io._result(transaction, config);
753
 
            }
754
 
        }
755
 
 
756
 
        // If config.timeout is defined, and the request is standard XHR,
757
 
        // initialize timeout polling.
758
 
        if (config.timeout) {
759
 
            io._startTimeout(transaction, config.timeout);
760
 
            Y.log('Configuration timeout set to: ' + config.timeout, 'info', 'io');
761
 
        }
762
 
 
763
 
        return {
764
 
            id: transaction.id,
765
 
            abort: function() {
766
 
                return transaction.c ? io._abort(transaction, 'abort') : false;
767
 
            },
768
 
            isInProgress: function() {
769
 
                return transaction.c ? (transaction.c.readyState % 4) : false;
770
 
            },
771
 
            io: io
772
 
        };
773
 
    }
774
 
};
775
 
 
776
 
/**
777
 
Method for initiating an ajax call.  The first argument is the url end
778
 
point for the call.  The second argument is an object to configure the
779
 
transaction and attach event subscriptions.  The configuration object
780
 
supports the following properties:
781
 
 
782
 
<dl>
783
 
  <dt>method</dt>
784
 
    <dd>HTTP method verb (e.g., GET or POST). If this property is not
785
 
        not defined, the default value will be GET.</dd>
786
 
 
787
 
  <dt>data</dt>
788
 
    <dd>This is the name-value string that will be sent as the
789
 
    transaction data. If the request is HTTP GET, the data become
790
 
    part of querystring. If HTTP POST, the data are sent in the
791
 
    message body.</dd>
792
 
 
793
 
  <dt>xdr</dt>
794
 
    <dd>Defines the transport to be used for cross-domain requests.
795
 
    By setting this property, the transaction will use the specified
796
 
    transport instead of XMLHttpRequest. The properties of the
797
 
    transport object are:
798
 
    <dl>
799
 
      <dt>use</dt>
800
 
        <dd>The transport to be used: 'flash' or 'native'</dd>
801
 
      <dt>dataType</dt>
802
 
        <dd>Set the value to 'XML' if that is the expected response
803
 
        content type.</dd>
804
 
    </dl></dd>
805
 
 
806
 
  <dt>form</dt>
807
 
    <dd>Form serialization configuration object.  Its properties are:
808
 
    <dl>
809
 
      <dt>id</dt>
810
 
        <dd>Node object or id of HTML form</dd>
811
 
      <dt>useDisabled</dt>
812
 
        <dd>`true` to also serialize disabled form field values
813
 
        (defaults to `false`)</dd>
814
 
    </dl></dd>
815
 
 
816
 
  <dt>on</dt>
817
 
    <dd>Assigns transaction event subscriptions. Available events are:
818
 
    <dl>
819
 
      <dt>start</dt>
820
 
        <dd>Fires when a request is sent to a resource.</dd>
821
 
      <dt>complete</dt>
822
 
        <dd>Fires when the transaction is complete.</dd>
823
 
      <dt>success</dt>
824
 
        <dd>Fires when the HTTP response status is within the 2xx
825
 
        range.</dd>
826
 
      <dt>failure</dt>
827
 
        <dd>Fires when the HTTP response status is outside the 2xx
828
 
        range, if an exception occurs, if the transation is aborted,
829
 
        or if the transaction exceeds a configured `timeout`.</dd>
830
 
      <dt>end</dt>
831
 
        <dd>Fires at the conclusion of the transaction
832
 
           lifecycle, after `success` or `failure`.</dd>
833
 
    </dl>
834
 
 
835
 
    <p>Callback functions for `start` and `end` receive the id of the
836
 
    transaction as a first argument. For `complete`, `success`, and
837
 
    `failure`, callbacks receive the id and the response object
838
 
    (usually the XMLHttpRequest instance).  If the `arguments`
839
 
    property was included in the configuration object passed to
840
 
    `Y.io()`, the configured data will be passed to all callbacks as
841
 
    the last argument.</p>
842
 
    </dd>
843
 
 
844
 
  <dt>sync</dt>
845
 
    <dd>Pass `true` to make a same-domain transaction synchronous.
846
 
    <strong>CAVEAT</strong>: This will negatively impact the user
847
 
    experience. Have a <em>very</em> good reason if you intend to use
848
 
    this.</dd>
849
 
 
850
 
  <dt>context</dt>
851
 
    <dd>The "`this'" object for all configured event handlers. If a
852
 
    specific context is needed for individual callbacks, bind the
853
 
    callback to a context using `Y.bind()`.</dd>
854
 
 
855
 
  <dt>headers</dt>
856
 
    <dd>Object map of transaction headers to send to the server. The
857
 
    object keys are the header names and the values are the header
858
 
    values.</dd>
859
 
 
860
 
  <dt>timeout</dt>
861
 
    <dd>Millisecond threshold for the transaction before being
862
 
    automatically aborted.</dd>
863
 
 
864
 
  <dt>arguments</dt>
865
 
    <dd>User-defined data passed to all registered event handlers.
866
 
    This value is available as the second argument in the "start" and
867
 
    "end" event handlers. It is the third argument in the "complete",
868
 
    "success", and "failure" event handlers. <strong>Be sure to quote
869
 
    this property name in the transaction configuration as
870
 
    "arguments" is a reserved word in JavaScript</strong> (e.g.
871
 
    `Y.io({ ..., "arguments": stuff })`).</dd>
872
 
</dl>
873
 
 
874
 
@method io
875
 
@static
876
 
@param {String} url qualified path to transaction resource.
877
 
@param {Object} config configuration object for the transaction.
878
 
@return {Object}
879
 
@for YUI
880
 
**/
881
 
Y.io = function(url, config) {
882
 
    // Calling IO through the static interface will use and reuse
883
 
    // an instance of IO.
884
 
    var transaction = Y.io._map['io:0'] || new IO();
885
 
    return transaction.send.apply(transaction, [url, config]);
886
 
};
887
 
 
888
 
/**
889
 
Method for setting and deleting IO HTTP headers to be sent with every
890
 
request.
891
 
 
892
 
Hosted as a property on the `io` function (e.g. `Y.io.header`).
893
 
 
894
 
@method header
895
 
@param {String} name HTTP header
896
 
@param {String} value HTTP header value
897
 
@static
898
 
**/
899
 
Y.io.header = function(name, value) {
900
 
    // Calling IO through the static interface will use and reuse
901
 
    // an instance of IO.
902
 
    var transaction = Y.io._map['io:0'] || new IO();
903
 
    transaction.setHeader(name, value);
904
 
};
905
 
 
906
 
Y.IO = IO;
907
 
// Map of all IO instances created.
908
 
Y.io._map = {};
909
 
var XHR = win && win.XMLHttpRequest,
910
 
    XDR = win && win.XDomainRequest,
911
 
    AX = win && win.ActiveXObject;
912
 
 
913
 
 
914
 
Y.mix(Y.IO, {
915
 
    /**
916
 
    * The ID of the default IO transport, defaults to `xhr`
917
 
    * @property _default
918
 
    * @type {String}
919
 
    * @static
920
 
    */
921
 
    _default: 'xhr',
922
 
    /**
923
 
    *
924
 
    * @method defaultTransport
925
 
    * @static
926
 
    * @param {String} [id] The transport to set as the default, if empty a new transport is created.
927
 
    * @return {Object} The transport object with a `send` method
928
 
    */
929
 
    defaultTransport: function(id) {
930
 
        if (id) {
931
 
            Y.log('Setting default IO to: ' + id, 'info', 'io');
932
 
            Y.IO._default = id;
933
 
        } else {
934
 
            var o = {
935
 
                c: Y.IO.transports[Y.IO._default](),
936
 
                notify: Y.IO._default === 'xhr' ? false : true
937
 
            };
938
 
            Y.log('Creating default transport: ' + Y.IO._default, 'info', 'io');
939
 
            return o;
940
 
        }
941
 
    },
942
 
    /**
943
 
    * An object hash of custom transports available to IO
944
 
    * @property transports
945
 
    * @type {Object}
946
 
    * @static
947
 
    */
948
 
    transports: {
949
 
        xhr: function () {
950
 
            return XHR ? new XMLHttpRequest() :
951
 
                AX ? new ActiveXObject('Microsoft.XMLHTTP') : null;
952
 
        },
953
 
        xdr: function () {
954
 
            return XDR ? new XDomainRequest() : null;
955
 
        },
956
 
        iframe: function () { return {}; },
957
 
        flash: null,
958
 
        nodejs: null
959
 
    },
960
 
    /**
961
 
    * Create a custom transport of type and return it's object
962
 
    * @method customTransport
963
 
    * @param {String} id The id of the transport to create.
964
 
    * @static
965
 
    */
966
 
    customTransport: function(id) {
967
 
        var o = { c: Y.IO.transports[id]() };
968
 
 
969
 
        o[(id === 'xdr' || id === 'flash') ? 'xdr' : 'notify'] = true;
970
 
        return o;
971
 
    }
972
 
});
973
 
 
974
 
Y.mix(Y.IO.prototype, {
975
 
    /**
976
 
    * Fired from the notify method of the transport which in turn fires
977
 
    * the event on the IO object.
978
 
    * @method notify
979
 
    * @param {String} event The name of the event
980
 
    * @param {Object} transaction The transaction object
981
 
    * @param {Object} config The configuration object for this transaction
982
 
    */
983
 
    notify: function(event, transaction, config) {
984
 
        var io = this;
985
 
 
986
 
        switch (event) {
987
 
            case 'timeout':
988
 
            case 'abort':
989
 
            case 'transport error':
990
 
                transaction.c = { status: 0, statusText: event };
991
 
                event = 'failure';
992
 
            default:
993
 
                io[event].apply(io, [transaction, config]);
994
 
        }
995
 
    }
996
 
});
997
 
 
998
 
 
999
 
 
1000
 
 
1001
 
}, '3.5.1' ,{requires:['event-custom-base', 'querystring-stringify-simple']});