~ubuntu-branches/ubuntu/utopic/moodle/utopic

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Thijs Kinkhorst
  • Date: 2014-05-12 16:10:38 UTC
  • mfrom: (36.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20140512161038-puyqf65k4e0s8ytz
Tags: 2.6.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

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