~michael.nelson/ubuntu-webcatalog/1267731-import-sca-apps-error

« back to all changes in this revision

Viewing changes to src/webcatalog/static/yui/3.10.3/build/io-base/io-base-debug.js

  • Committer: Tarmac
  • Author(s): Stephen Stewart
  • Date: 2013-06-26 09:19:32 UTC
  • mfrom: (184.1.4 ubuntu-global-nav)
  • Revision ID: tarmac-20130626091932-8urtuli368k8p7ds
[r=beuno,jonas-drange] add ubuntu global nav to apps.ubuntu.com

Show diffs side-by-side

added added

removed removed

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