[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |