[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/io-base/ -> io-base-debug.js (source)

   1  /*
   2  YUI 3.17.2 (build 9c3c78e)
   3  Copyright 2014 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>username</dt>
 625      *     <dd>Username to use in a HTTP authentication.</dd>
 626      *
 627      *   <dt>password</dt>
 628      *     <dd>Password to use in a HTTP authentication.</dd>
 629      *
 630      *   <dt>timeout</dt>
 631      *     <dd>Millisecond threshold for the transaction before being
 632      *     automatically aborted.</dd>
 633      *
 634      *   <dt>arguments</dt>
 635      *     <dd>User-defined data passed to all registered event handlers.
 636      *     This value is available as the second argument in the "start" and
 637      *     "end" event handlers. It is the third argument in the "complete",
 638      *     "success", and "failure" event handlers. <strong>Be sure to quote
 639      *     this property name in the transaction configuration as
 640      *     "arguments" is a reserved word in JavaScript</strong> (e.g.
 641      *     `Y.io({ ..., "arguments": stuff })`).</dd>
 642      * </dl>
 643      *
 644      * @method send
 645      * @public
 646      * @param {String} uri Qualified path to transaction resource.
 647      * @param {Object} config Configuration object for the transaction.
 648      * @param {Number} id Transaction id, if already set.
 649      * @return {Object}
 650      */
 651      send: function(uri, config, id) {
 652          var transaction, method, i, len, sync, data,
 653              io = this,
 654              u = uri,
 655              response = {};
 656  
 657          config = config ? Y.Object(config) : {};
 658          transaction = io._create(config, id);
 659          method = config.method ? config.method.toUpperCase() : 'GET';
 660          sync = config.sync;
 661          data = config.data;
 662  
 663          // Serialize a map object into a key-value string using
 664          // querystring-stringify-simple.
 665          if ((Y.Lang.isObject(data) && !data.nodeType) && !transaction.upload) {
 666              if (Y.QueryString && Y.QueryString.stringify) {
 667                  Y.log('Stringifying config.data for request', 'info', 'io');
 668                  config.data = data = Y.QueryString.stringify(data);
 669              } else {
 670                  Y.log('Failed to stringify config.data object, likely because `querystring-stringify-simple` is missing.', 'warn', 'io');
 671              }
 672          }
 673  
 674          if (config.form) {
 675              if (config.form.upload) {
 676                  // This is a file upload transaction, calling
 677                  // upload() in io-upload-iframe.
 678                  return io.upload(transaction, uri, config);
 679              } else {
 680                  // Serialize HTML form data into a key-value string.
 681                  data = io._serialize(config.form, data);
 682              }
 683          }
 684  
 685          // Convert falsy values to an empty string. This way IE can't be
 686          // rediculous and translate `undefined` to "undefined".
 687          data || (data = '');
 688  
 689          if (data) {
 690              switch (method) {
 691                  case 'GET':
 692                  case 'HEAD':
 693                  case 'DELETE':
 694                      u = io._concat(u, data);
 695                      data = '';
 696                      Y.log('HTTP' + method + ' with data.  The querystring is: ' + u, 'info', 'io');
 697                      break;
 698                  case 'POST':
 699                  case 'PUT':
 700                      // If Content-Type is defined in the configuration object, or
 701                      // or as a default header, it will be used instead of
 702                      // 'application/x-www-form-urlencoded; charset=UTF-8'
 703                      config.headers = Y.merge({
 704                          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
 705                      }, config.headers);
 706                      break;
 707              }
 708          }
 709  
 710          if (transaction.xdr) {
 711              // Route data to io-xdr module for flash and XDomainRequest.
 712              return io.xdr(u, transaction, config);
 713          }
 714          else if (transaction.notify) {
 715              // Route data to custom transport
 716              return transaction.c.send(transaction, uri, config);
 717          }
 718  
 719          if (!sync && !transaction.upload) {
 720              transaction.c.onreadystatechange = function() {
 721                  io._rS(transaction, config);
 722              };
 723          }
 724  
 725          try {
 726              // Determine if request is to be set as
 727              // synchronous or asynchronous.
 728              transaction.c.open(method, u, !sync, config.username || null, config.password || null);
 729              io._setHeaders(transaction.c, config.headers || {});
 730              io.start(transaction, config);
 731  
 732              // Will work only in browsers that implement the
 733              // Cross-Origin Resource Sharing draft.
 734              if (config.xdr && config.xdr.credentials && SUPPORTS_CORS) {
 735                  transaction.c.withCredentials = true;
 736              }
 737  
 738              // Using "null" with HTTP POST will result in a request
 739              // with no Content-Length header defined.
 740              transaction.c.send(data);
 741  
 742              if (sync) {
 743                  // Create a response object for synchronous transactions,
 744                  // mixing id and arguments properties with the xhr
 745                  // properties whitelist.
 746                  for (i = 0, len = XHR_PROPS.length; i < len; ++i) {
 747                      response[XHR_PROPS[i]] = transaction.c[XHR_PROPS[i]];
 748                  }
 749  
 750                  response.getAllResponseHeaders = function() {
 751                      return transaction.c.getAllResponseHeaders();
 752                  };
 753  
 754                  response.getResponseHeader = function(name) {
 755                      return transaction.c.getResponseHeader(name);
 756                  };
 757  
 758                  io.complete(transaction, config);
 759                  io._result(transaction, config);
 760  
 761                  return response;
 762              }
 763          } catch(e) {
 764              if (transaction.xdr) {
 765                  // This exception is usually thrown by browsers
 766                  // that do not support XMLHttpRequest Level 2.
 767                  // Retry the request with the XDR transport set
 768                  // to 'flash'.  If the Flash transport is not
 769                  // initialized or available, the transaction
 770                  // will resolve to a transport error.
 771                  return io._retry(transaction, uri, config);
 772              } else {
 773                  io.complete(transaction, config);
 774                  io._result(transaction, config);
 775              }
 776          }
 777  
 778          // If config.timeout is defined, and the request is standard XHR,
 779          // initialize timeout polling.
 780          if (config.timeout) {
 781              io._startTimeout(transaction, config.timeout);
 782              Y.log('Configuration timeout set to: ' + config.timeout, 'info', 'io');
 783          }
 784  
 785          return {
 786              id: transaction.id,
 787              abort: function() {
 788                  return transaction.c ? io._abort(transaction, 'abort') : false;
 789              },
 790              isInProgress: function() {
 791                  return transaction.c ? (transaction.c.readyState % 4) : false;
 792              },
 793              io: io
 794          };
 795      }
 796  };
 797  
 798  /**
 799  Method for initiating an ajax call.  The first argument is the url end
 800  point for the call.  The second argument is an object to configure the
 801  transaction and attach event subscriptions.  The configuration object
 802  supports the following properties:
 803  
 804  <dl>
 805    <dt>method</dt>
 806      <dd>HTTP method verb (e.g., GET or POST). If this property is not
 807          not defined, the default value will be GET.</dd>
 808  
 809    <dt>data</dt>
 810      <dd>This is the name-value string that will be sent as the
 811      transaction data. If the request is HTTP GET, the data become
 812      part of querystring. If HTTP POST, the data are sent in the
 813      message body.</dd>
 814  
 815    <dt>xdr</dt>
 816      <dd>Defines the transport to be used for cross-domain requests.
 817      By setting this property, the transaction will use the specified
 818      transport instead of XMLHttpRequest. The properties of the
 819      transport object are:
 820      <dl>
 821        <dt>use</dt>
 822          <dd>The transport to be used: 'flash' or 'native'</dd>
 823        <dt>dataType</dt>
 824          <dd>Set the value to 'XML' if that is the expected response
 825          content type.</dd>
 826      </dl></dd>
 827  
 828    <dt>form</dt>
 829      <dd>Form serialization configuration object.  Its properties are:
 830      <dl>
 831        <dt>id</dt>
 832          <dd>Node object or id of HTML form</dd>
 833        <dt>useDisabled</dt>
 834          <dd>`true` to also serialize disabled form field values
 835          (defaults to `false`)</dd>
 836      </dl></dd>
 837  
 838    <dt>on</dt>
 839      <dd>Assigns transaction event subscriptions. Available events are:
 840      <dl>
 841        <dt>start</dt>
 842          <dd>Fires when a request is sent to a resource.</dd>
 843        <dt>complete</dt>
 844          <dd>Fires when the transaction is complete.</dd>
 845        <dt>success</dt>
 846          <dd>Fires when the HTTP response status is within the 2xx
 847          range.</dd>
 848        <dt>failure</dt>
 849          <dd>Fires when the HTTP response status is outside the 2xx
 850          range, if an exception occurs, if the transation is aborted,
 851          or if the transaction exceeds a configured `timeout`.</dd>
 852        <dt>end</dt>
 853          <dd>Fires at the conclusion of the transaction
 854             lifecycle, after `success` or `failure`.</dd>
 855      </dl>
 856  
 857      <p>Callback functions for `start` and `end` receive the id of the
 858      transaction as a first argument. For `complete`, `success`, and
 859      `failure`, callbacks receive the id and the response object
 860      (usually the XMLHttpRequest instance).  If the `arguments`
 861      property was included in the configuration object passed to
 862      `Y.io()`, the configured data will be passed to all callbacks as
 863      the last argument.</p>
 864      </dd>
 865  
 866    <dt>sync</dt>
 867      <dd>Pass `true` to make a same-domain transaction synchronous.
 868      <strong>CAVEAT</strong>: This will negatively impact the user
 869      experience. Have a <em>very</em> good reason if you intend to use
 870      this.</dd>
 871  
 872    <dt>context</dt>
 873      <dd>The "`this'" object for all configured event handlers. If a
 874      specific context is needed for individual callbacks, bind the
 875      callback to a context using `Y.bind()`.</dd>
 876  
 877    <dt>headers</dt>
 878      <dd>Object map of transaction headers to send to the server. The
 879      object keys are the header names and the values are the header
 880      values.</dd>
 881  
 882    <dt>timeout</dt>
 883      <dd>Millisecond threshold for the transaction before being
 884      automatically aborted.</dd>
 885  
 886    <dt>arguments</dt>
 887      <dd>User-defined data passed to all registered event handlers.
 888      This value is available as the second argument in the "start" and
 889      "end" event handlers. It is the third argument in the "complete",
 890      "success", and "failure" event handlers. <strong>Be sure to quote
 891      this property name in the transaction configuration as
 892      "arguments" is a reserved word in JavaScript</strong> (e.g.
 893      `Y.io({ ..., "arguments": stuff })`).</dd>
 894  </dl>
 895  
 896  @method io
 897  @static
 898  @param {String} url qualified path to transaction resource.
 899  @param {Object} config configuration object for the transaction.
 900  @return {Object}
 901  @for YUI
 902  **/
 903  Y.io = function(url, config) {
 904      // Calling IO through the static interface will use and reuse
 905      // an instance of IO.
 906      var transaction = Y.io._map['io:0'] || new IO();
 907      return transaction.send.apply(transaction, [url, config]);
 908  };
 909  
 910  /**
 911  Method for setting and deleting IO HTTP headers to be sent with every
 912  request.
 913  
 914  Hosted as a property on the `io` function (e.g. `Y.io.header`).
 915  
 916  @method header
 917  @param {String} name HTTP header
 918  @param {String} value HTTP header value
 919  @static
 920  **/
 921  Y.io.header = function(name, value) {
 922      // Calling IO through the static interface will use and reuse
 923      // an instance of IO.
 924      var transaction = Y.io._map['io:0'] || new IO();
 925      transaction.setHeader(name, value);
 926  };
 927  
 928  Y.IO = IO;
 929  // Map of all IO instances created.
 930  Y.io._map = {};
 931  var XHR = win && win.XMLHttpRequest,
 932      XDR = win && win.XDomainRequest,
 933      AX = win && win.ActiveXObject,
 934  
 935      // Checks for the presence of the `withCredentials` in an XHR instance
 936      // object, which will be present if the environment supports CORS.
 937      SUPPORTS_CORS = XHR && 'withCredentials' in (new XMLHttpRequest());
 938  
 939  
 940  Y.mix(Y.IO, {
 941      /**
 942      * The ID of the default IO transport, defaults to `xhr`
 943      * @property _default
 944      * @type {String}
 945      * @static
 946      */
 947      _default: 'xhr',
 948      /**
 949      *
 950      * @method defaultTransport
 951      * @static
 952      * @param {String} [id] The transport to set as the default, if empty a new transport is created.
 953      * @return {Object} The transport object with a `send` method
 954      */
 955      defaultTransport: function(id) {
 956          if (id) {
 957              Y.log('Setting default IO to: ' + id, 'info', 'io');
 958              Y.IO._default = id;
 959          } else {
 960              var o = {
 961                  c: Y.IO.transports[Y.IO._default](),
 962                  notify: Y.IO._default === 'xhr' ? false : true
 963              };
 964              Y.log('Creating default transport: ' + Y.IO._default, 'info', 'io');
 965              return o;
 966          }
 967      },
 968      /**
 969      * An object hash of custom transports available to IO
 970      * @property transports
 971      * @type {Object}
 972      * @static
 973      */
 974      transports: {
 975          xhr: function () {
 976              return XHR ? new XMLHttpRequest() :
 977                  AX ? new ActiveXObject('Microsoft.XMLHTTP') : null;
 978          },
 979          xdr: function () {
 980              return XDR ? new XDomainRequest() : null;
 981          },
 982          iframe: function () { return {}; },
 983          flash: null,
 984          nodejs: null
 985      },
 986      /**
 987      * Create a custom transport of type and return it's object
 988      * @method customTransport
 989      * @param {String} id The id of the transport to create.
 990      * @static
 991      */
 992      customTransport: function(id) {
 993          var o = { c: Y.IO.transports[id]() };
 994  
 995          o[(id === 'xdr' || id === 'flash') ? 'xdr' : 'notify'] = true;
 996          return o;
 997      }
 998  });
 999  
1000  Y.mix(Y.IO.prototype, {
1001      /**
1002      * Fired from the notify method of the transport which in turn fires
1003      * the event on the IO object.
1004      * @method notify
1005      * @param {String} event The name of the event
1006      * @param {Object} transaction The transaction object
1007      * @param {Object} config The configuration object for this transaction
1008      */
1009      notify: function(event, transaction, config) {
1010          var io = this;
1011  
1012          switch (event) {
1013              case 'timeout':
1014              case 'abort':
1015              case 'transport error':
1016                  transaction.c = { status: 0, statusText: event };
1017                  event = 'failure';
1018              default:
1019                  io[event].apply(io, [transaction, config]);
1020          }
1021      }
1022  });
1023  
1024  
1025  
1026  
1027  }, '3.17.2', {"requires": ["event-custom-base", "querystring-stringify-simple"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1