PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/cia/media-src/js/yui-0.12.2/build/connection/connection.js

http://cia-vc.googlecode.com/
JavaScript | 965 lines | 486 code | 91 blank | 388 comment | 95 complexity | 3d223fdc1c3640d850bd17f329cd2fcd MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. Copyright (c) 2006, Yahoo! Inc. All rights reserved.
  3. Code licensed under the BSD License:
  4. http://developer.yahoo.net/yui/license.txt
  5. version: 0.12.2
  6. */
  7. /**
  8. * The Connection Manager provides a simplified interface to the XMLHttpRequest
  9. * object. It handles cross-browser instantiantion of XMLHttpRequest, negotiates the
  10. * interactive states and server response, returning the results to a pre-defined
  11. * callback you create.
  12. *
  13. * @namespace YAHOO.util
  14. * @module connection
  15. * @requires yahoo
  16. */
  17. /**
  18. * The Connection Manager singleton provides methods for creating and managing
  19. * asynchronous transactions.
  20. *
  21. * @class Connect
  22. */
  23. YAHOO.util.Connect =
  24. {
  25. /**
  26. * @description Array of MSFT ActiveX ids for XMLHttpRequest.
  27. * @property _msxml_progid
  28. * @private
  29. * @static
  30. * @type array
  31. */
  32. _msxml_progid:[
  33. 'MSXML2.XMLHTTP.3.0',
  34. 'MSXML2.XMLHTTP',
  35. 'Microsoft.XMLHTTP'
  36. ],
  37. /**
  38. * @description Object literal of HTTP header(s)
  39. * @property _http_header
  40. * @private
  41. * @static
  42. * @type object
  43. */
  44. _http_header:{},
  45. /**
  46. * @description Determines if HTTP headers are set.
  47. * @property _has_http_headers
  48. * @private
  49. * @static
  50. * @type boolean
  51. */
  52. _has_http_headers:false,
  53. /**
  54. * @description Determines if a default header of
  55. * Content-Type of 'application/x-www-form-urlencoded'
  56. * will be added to any client HTTP headers sent for POST
  57. * transactions.
  58. * @property _use_default_post_header
  59. * @private
  60. * @static
  61. * @type boolean
  62. */
  63. _use_default_post_header:true,
  64. /**
  65. * @description Determines if a default header of
  66. * Content-Type of 'application/x-www-form-urlencoded'
  67. * will be added to any client HTTP headers sent for POST
  68. * transactions.
  69. * @property _default_post_header
  70. * @private
  71. * @static
  72. * @type boolean
  73. */
  74. _default_post_header:'application/x-www-form-urlencoded',
  75. /**
  76. * @description Property modified by setForm() to determine if the data
  77. * should be submitted as an HTML form.
  78. * @property _isFormSubmit
  79. * @private
  80. * @static
  81. * @type boolean
  82. */
  83. _isFormSubmit:false,
  84. /**
  85. * @description Property modified by setForm() to determine if a file(s)
  86. * upload is expected.
  87. * @property _isFileUpload
  88. * @private
  89. * @static
  90. * @type boolean
  91. */
  92. _isFileUpload:false,
  93. /**
  94. * @description Property modified by setForm() to set a reference to the HTML
  95. * form node if the desired action is file upload.
  96. * @property _formNode
  97. * @private
  98. * @static
  99. * @type object
  100. */
  101. _formNode:null,
  102. /**
  103. * @description Property modified by setForm() to set the HTML form data
  104. * for each transaction.
  105. * @property _sFormData
  106. * @private
  107. * @static
  108. * @type string
  109. */
  110. _sFormData:null,
  111. /**
  112. * @description Collection of polling references to the polling mechanism in handleReadyState.
  113. * @property _poll
  114. * @private
  115. * @static
  116. * @type object
  117. */
  118. _poll:{},
  119. /**
  120. * @description Queue of timeout values for each transaction callback with a defined timeout value.
  121. * @property _timeOut
  122. * @private
  123. * @static
  124. * @type object
  125. */
  126. _timeOut:{},
  127. /**
  128. * @description The polling frequency, in milliseconds, for HandleReadyState.
  129. * when attempting to determine a transaction's XHR readyState.
  130. * The default is 50 milliseconds.
  131. * @property _polling_interval
  132. * @private
  133. * @static
  134. * @type int
  135. */
  136. _polling_interval:50,
  137. /**
  138. * @description A transaction counter that increments the transaction id for each transaction.
  139. * @property _transaction_id
  140. * @private
  141. * @static
  142. * @type int
  143. */
  144. _transaction_id:0,
  145. /**
  146. * @description Member to add an ActiveX id to the existing xml_progid array.
  147. * In the event(unlikely) a new ActiveX id is introduced, it can be added
  148. * without internal code modifications.
  149. * @method setProgId
  150. * @public
  151. * @static
  152. * @param {string} id The ActiveX id to be added to initialize the XHR object.
  153. * @return void
  154. */
  155. setProgId:function(id)
  156. {
  157. this._msxml_progid.unshift(id);
  158. },
  159. /**
  160. * @description Member to enable or disable the default POST header.
  161. * @method setDefaultPostHeader
  162. * @public
  163. * @static
  164. * @param {boolean} b Set and use default header - true or false .
  165. * @return void
  166. */
  167. setDefaultPostHeader:function(b)
  168. {
  169. this._use_default_post_header = b;
  170. },
  171. /**
  172. * @description Member to modify the default polling interval.
  173. * @method setPollingInterval
  174. * @public
  175. * @static
  176. * @param {int} i The polling interval in milliseconds.
  177. * @return void
  178. */
  179. setPollingInterval:function(i)
  180. {
  181. if(typeof i == 'number' && isFinite(i)){
  182. this._polling_interval = i;
  183. }
  184. },
  185. /**
  186. * @description Instantiates a XMLHttpRequest object and returns an object with two properties:
  187. * the XMLHttpRequest instance and the transaction id.
  188. * @method createXhrObject
  189. * @private
  190. * @static
  191. * @param {int} transactionId Property containing the transaction id for this transaction.
  192. * @return object
  193. */
  194. createXhrObject:function(transactionId)
  195. {
  196. var obj,http;
  197. try
  198. {
  199. // Instantiates XMLHttpRequest in non-IE browsers and assigns to http.
  200. http = new XMLHttpRequest();
  201. // Object literal with http and tId properties
  202. obj = { conn:http, tId:transactionId };
  203. }
  204. catch(e)
  205. {
  206. for(var i=0; i<this._msxml_progid.length; ++i){
  207. try
  208. {
  209. // Instantiates XMLHttpRequest for IE and assign to http.
  210. http = new ActiveXObject(this._msxml_progid[i]);
  211. // Object literal with conn and tId properties
  212. obj = { conn:http, tId:transactionId };
  213. break;
  214. }
  215. catch(e){}
  216. }
  217. }
  218. finally
  219. {
  220. return obj;
  221. }
  222. },
  223. /**
  224. * @description This method is called by asyncRequest to create a
  225. * valid connection object for the transaction. It also passes a
  226. * transaction id and increments the transaction id counter.
  227. * @method getConnectionObject
  228. * @private
  229. * @static
  230. * @return {object}
  231. */
  232. getConnectionObject:function()
  233. {
  234. var o;
  235. var tId = this._transaction_id;
  236. try
  237. {
  238. o = this.createXhrObject(tId);
  239. if(o){
  240. this._transaction_id++;
  241. }
  242. }
  243. catch(e){}
  244. finally
  245. {
  246. return o;
  247. }
  248. },
  249. /**
  250. * @description Method for initiating an asynchronous request via the XHR object.
  251. * @method asyncRequest
  252. * @public
  253. * @static
  254. * @param {string} method HTTP transaction method
  255. * @param {string} uri Fully qualified path of resource
  256. * @param {callback} callback User-defined callback function or object
  257. * @param {string} postData POST body
  258. * @return {object} Returns the connection object
  259. */
  260. asyncRequest:function(method, uri, callback, postData)
  261. {
  262. var o = this.getConnectionObject();
  263. if(!o){
  264. return null;
  265. }
  266. else{
  267. if(this._isFormSubmit){
  268. if(this._isFileUpload){
  269. this.uploadFile(o.tId, callback, uri, postData);
  270. this.releaseObject(o);
  271. return;
  272. }
  273. //If the specified HTTP method is GET, setForm() will return an
  274. //encoded string that is concatenated to the uri to
  275. //create a querystring.
  276. if(method == 'GET'){
  277. if(this._sFormData.length != 0){
  278. // If the URI already contains a querystring, append an ampersand
  279. // and then concatenate _sFormData to the URI.
  280. uri += ((uri.indexOf('?') == -1)?'?':'&') + this._sFormData;
  281. }
  282. else{
  283. uri += "?" + this._sFormData;
  284. }
  285. }
  286. else if(method == 'POST'){
  287. //If POST data exist in addition to the HTML form data,
  288. //it will be concatenated to the form data.
  289. postData = postData?this._sFormData + "&" + postData:this._sFormData;
  290. }
  291. }
  292. o.conn.open(method, uri, true);
  293. if(this._isFormSubmit || (postData && this._use_default_post_header)){
  294. this.initHeader('Content-Type', this._default_post_header);
  295. if(this._isFormSubmit){
  296. this.resetFormState();
  297. }
  298. }
  299. if(this._has_http_headers){
  300. this.setHeader(o);
  301. }
  302. this.handleReadyState(o, callback);
  303. o.conn.send(postData || null);
  304. return o;
  305. }
  306. },
  307. /**
  308. * @description This method serves as a timer that polls the XHR object's readyState
  309. * property during a transaction, instead of binding a callback to the
  310. * onreadystatechange event. Upon readyState 4, handleTransactionResponse
  311. * will process the response, and the timer will be cleared.
  312. * @method handleReadyState
  313. * @private
  314. * @static
  315. * @param {object} o The connection object
  316. * @param {callback} callback The user-defined callback object
  317. * @return {void}
  318. */
  319. handleReadyState:function(o, callback)
  320. {
  321. var oConn = this;
  322. if(callback && callback.timeout){
  323. this._timeOut[o.tId] = window.setTimeout(function(){ oConn.abort(o, callback, true); }, callback.timeout);
  324. }
  325. this._poll[o.tId] = window.setInterval(
  326. function(){
  327. if(o.conn && o.conn.readyState == 4){
  328. window.clearInterval(oConn._poll[o.tId]);
  329. delete oConn._poll[o.tId];
  330. if(callback && callback.timeout){
  331. delete oConn._timeOut[o.tId];
  332. }
  333. oConn.handleTransactionResponse(o, callback);
  334. }
  335. }
  336. ,this._polling_interval);
  337. },
  338. /**
  339. * @description This method attempts to interpret the server response and
  340. * determine whether the transaction was successful, or if an error or
  341. * exception was encountered.
  342. * @method handleTransactionResponse
  343. * @private
  344. * @static
  345. * @param {object} o The connection object
  346. * @param {object} callback The sser-defined callback object
  347. * @param {boolean} isAbort Determines if the transaction was aborted.
  348. * @return {void}
  349. */
  350. handleTransactionResponse:function(o, callback, isAbort)
  351. {
  352. // If no valid callback is provided, then do not process any callback handling.
  353. if(!callback){
  354. this.releaseObject(o);
  355. return;
  356. }
  357. var httpStatus, responseObject;
  358. try
  359. {
  360. if(o.conn.status !== undefined && o.conn.status != 0){
  361. httpStatus = o.conn.status;
  362. }
  363. else{
  364. httpStatus = 13030;
  365. }
  366. }
  367. catch(e){
  368. // 13030 is the custom code to indicate the condition -- in Mozilla/FF --
  369. // when the o object's status and statusText properties are
  370. // unavailable, and a query attempt throws an exception.
  371. httpStatus = 13030;
  372. }
  373. if(httpStatus >= 200 && httpStatus < 300){
  374. try
  375. {
  376. responseObject = this.createResponseObject(o, callback.argument);
  377. if(callback.success){
  378. if(!callback.scope){
  379. callback.success(responseObject);
  380. }
  381. else{
  382. // If a scope property is defined, the callback will be fired from
  383. // the context of the object.
  384. callback.success.apply(callback.scope, [responseObject]);
  385. }
  386. }
  387. }
  388. catch(e){}
  389. }
  390. else{
  391. try
  392. {
  393. switch(httpStatus){
  394. // The following cases are wininet.dll error codes that may be encountered.
  395. case 12002: // Server timeout
  396. case 12029: // 12029 to 12031 correspond to dropped connections.
  397. case 12030:
  398. case 12031:
  399. case 12152: // Connection closed by server.
  400. case 13030: // See above comments for variable status.
  401. responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort?isAbort:false));
  402. if(callback.failure){
  403. if(!callback.scope){
  404. callback.failure(responseObject);
  405. }
  406. else{
  407. callback.failure.apply(callback.scope, [responseObject]);
  408. }
  409. }
  410. break;
  411. default:
  412. responseObject = this.createResponseObject(o, callback.argument);
  413. if(callback.failure){
  414. if(!callback.scope){
  415. callback.failure(responseObject);
  416. }
  417. else{
  418. callback.failure.apply(callback.scope, [responseObject]);
  419. }
  420. }
  421. }
  422. }
  423. catch(e){}
  424. }
  425. this.releaseObject(o);
  426. responseObject = null;
  427. },
  428. /**
  429. * @description This method evaluates the server response, creates and returns the results via
  430. * its properties. Success and failure cases will differ in the response
  431. * object's property values.
  432. * @method createResponseObject
  433. * @private
  434. * @static
  435. * @param {object} o The connection object
  436. * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback
  437. * @return {object}
  438. */
  439. createResponseObject:function(o, callbackArg)
  440. {
  441. var obj = {};
  442. var headerObj = {};
  443. try
  444. {
  445. var headerStr = o.conn.getAllResponseHeaders();
  446. var header = headerStr.split('\n');
  447. for(var i=0; i<header.length; i++){
  448. var delimitPos = header[i].indexOf(':');
  449. if(delimitPos != -1){
  450. headerObj[header[i].substring(0,delimitPos)] = header[i].substring(delimitPos+2);
  451. }
  452. }
  453. }
  454. catch(e){}
  455. obj.tId = o.tId;
  456. obj.status = o.conn.status;
  457. obj.statusText = o.conn.statusText;
  458. obj.getResponseHeader = headerObj;
  459. obj.getAllResponseHeaders = headerStr;
  460. obj.responseText = o.conn.responseText;
  461. obj.responseXML = o.conn.responseXML;
  462. if(typeof callbackArg !== undefined){
  463. obj.argument = callbackArg;
  464. }
  465. return obj;
  466. },
  467. /**
  468. * @description If a transaction cannot be completed due to dropped or closed connections,
  469. * there may be not be enough information to build a full response object.
  470. * The failure callback will be fired and this specific condition can be identified
  471. * by a status property value of 0.
  472. *
  473. * If an abort was successful, the status property will report a value of -1.
  474. *
  475. * @method createExceptionObject
  476. * @private
  477. * @static
  478. * @param {int} tId The Transaction Id
  479. * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback
  480. * @param {boolean} isAbort Determines if the exception case is caused by a transaction abort
  481. * @return {object}
  482. */
  483. createExceptionObject:function(tId, callbackArg, isAbort)
  484. {
  485. var COMM_CODE = 0;
  486. var COMM_ERROR = 'communication failure';
  487. var ABORT_CODE = -1;
  488. var ABORT_ERROR = 'transaction aborted';
  489. var obj = {};
  490. obj.tId = tId;
  491. if(isAbort){
  492. obj.status = ABORT_CODE;
  493. obj.statusText = ABORT_ERROR;
  494. }
  495. else{
  496. obj.status = COMM_CODE;
  497. obj.statusText = COMM_ERROR;
  498. }
  499. if(callbackArg){
  500. obj.argument = callbackArg;
  501. }
  502. return obj;
  503. },
  504. /**
  505. * @description Public method that stores the custom HTTP headers for each transaction.
  506. * @method initHeader
  507. * @public
  508. * @static
  509. * @param {string} label The HTTP header label
  510. * @param {string} value The HTTP header value
  511. * @return {void}
  512. */
  513. initHeader:function(label,value)
  514. {
  515. if(this._http_header[label] === undefined){
  516. this._http_header[label] = value;
  517. }
  518. else{
  519. // Concatenate multiple values, comma-delimited,
  520. // for the same header label,
  521. this._http_header[label] = value + "," + this._http_header[label];
  522. }
  523. this._has_http_headers = true;
  524. },
  525. /**
  526. * @description Accessor that sets the HTTP headers for each transaction.
  527. * @method setHeader
  528. * @private
  529. * @static
  530. * @param {object} o The connection object for the transaction.
  531. * @return {void}
  532. */
  533. setHeader:function(o)
  534. {
  535. for(var prop in this._http_header){
  536. if(this._http_header.hasOwnProperty(prop)){
  537. o.conn.setRequestHeader(prop, this._http_header[prop]);
  538. }
  539. }
  540. delete this._http_header;
  541. this._http_header = {};
  542. this._has_http_headers = false;
  543. },
  544. /**
  545. * @description This method assembles the form label and value pairs and
  546. * constructs an encoded string.
  547. * asyncRequest() will automatically initialize the
  548. * transaction with a HTTP header Content-Type of
  549. * application/x-www-form-urlencoded.
  550. * @method setForm
  551. * @public
  552. * @static
  553. * @param {string || object} form id or name attribute, or form object.
  554. * @param {string} optional boolean to indicate SSL environment.
  555. * @param {string || boolean} optional qualified path of iframe resource for SSL in IE.
  556. * @return {string} string of the HTML form field name and value pairs..
  557. */
  558. setForm:function(formId, isUpload, secureUri)
  559. {
  560. this.resetFormState();
  561. var oForm;
  562. if(typeof formId == 'string'){
  563. // Determine if the argument is a form id or a form name.
  564. // Note form name usage is deprecated but supported
  565. // here for legacy reasons.
  566. oForm = (document.getElementById(formId) || document.forms[formId]);
  567. }
  568. else if(typeof formId == 'object'){
  569. // Treat argument as an HTML form object.
  570. oForm = formId;
  571. }
  572. else{
  573. return;
  574. }
  575. // If the isUpload argument is true, setForm will call createFrame to initialize
  576. // an iframe as the form target.
  577. //
  578. // The argument secureURI is also required by IE in SSL environments
  579. // where the secureURI string is a fully qualified HTTP path, used to set the source
  580. // of the iframe, to a stub resource in the same domain.
  581. if(isUpload){
  582. // Create iframe in preparation for file upload.
  583. this.createFrame(secureUri?secureUri:null);
  584. // Set form reference and file upload properties to true.
  585. this._isFormSubmit = true;
  586. this._isFileUpload = true;
  587. this._formNode = oForm;
  588. return;
  589. }
  590. var oElement, oName, oValue, oDisabled;
  591. var hasSubmit = false;
  592. // Iterate over the form elements collection to construct the
  593. // label-value pairs.
  594. for (var i=0; i<oForm.elements.length; i++){
  595. oElement = oForm.elements[i];
  596. oDisabled = oForm.elements[i].disabled;
  597. oName = oForm.elements[i].name;
  598. oValue = oForm.elements[i].value;
  599. // Do not submit fields that are disabled or
  600. // do not have a name attribute value.
  601. if(!oDisabled && oName)
  602. {
  603. switch (oElement.type)
  604. {
  605. case 'select-one':
  606. case 'select-multiple':
  607. for(var j=0; j<oElement.options.length; j++){
  608. if(oElement.options[j].selected){
  609. if(window.ActiveXObject){
  610. this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].attributes['value'].specified?oElement.options[j].value:oElement.options[j].text) + '&';
  611. }
  612. else{
  613. this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].hasAttribute('value')?oElement.options[j].value:oElement.options[j].text) + '&';
  614. }
  615. }
  616. }
  617. break;
  618. case 'radio':
  619. case 'checkbox':
  620. if(oElement.checked){
  621. this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
  622. }
  623. break;
  624. case 'file':
  625. // stub case as XMLHttpRequest will only send the file path as a string.
  626. case undefined:
  627. // stub case for fieldset element which returns undefined.
  628. case 'reset':
  629. // stub case for input type reset button.
  630. case 'button':
  631. // stub case for input type button elements.
  632. break;
  633. case 'submit':
  634. if(hasSubmit == false){
  635. this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
  636. hasSubmit = true;
  637. }
  638. break;
  639. default:
  640. this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
  641. break;
  642. }
  643. }
  644. }
  645. this._isFormSubmit = true;
  646. this._sFormData = this._sFormData.substr(0, this._sFormData.length - 1);
  647. return this._sFormData;
  648. },
  649. /**
  650. * @description Resets HTML form properties when an HTML form or HTML form
  651. * with file upload transaction is sent.
  652. * @method resetFormState
  653. * @private
  654. * @static
  655. * @return {void}
  656. */
  657. resetFormState:function(){
  658. this._isFormSubmit = false;
  659. this._isFileUpload = false;
  660. this._formNode = null;
  661. this._sFormData = "";
  662. },
  663. /**
  664. * @description Creates an iframe to be used for form file uploads. It is remove from the
  665. * document upon completion of the upload transaction.
  666. * @method createFrame
  667. * @private
  668. * @static
  669. * @param {string} secureUri Optional qualified path of iframe resource for SSL in IE.
  670. * @return {void}
  671. */
  672. createFrame:function(secureUri){
  673. // IE does not allow the setting of id and name attributes as object
  674. // properties via createElement(). A different iframe creation
  675. // pattern is required for IE.
  676. var frameId = 'yuiIO' + this._transaction_id;
  677. if(window.ActiveXObject){
  678. var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
  679. // IE will throw a security exception in an SSL environment if the
  680. // iframe source is undefined.
  681. if(typeof secureUri == 'boolean'){
  682. io.src = 'javascript:false';
  683. }
  684. else if(typeof secureURI == 'string'){
  685. // Deprecated
  686. io.src = secureUri;
  687. }
  688. }
  689. else{
  690. var io = document.createElement('iframe');
  691. io.id = frameId;
  692. io.name = frameId;
  693. }
  694. io.style.position = 'absolute';
  695. io.style.top = '-1000px';
  696. io.style.left = '-1000px';
  697. document.body.appendChild(io);
  698. },
  699. /**
  700. * @description Parses the POST data and creates hidden form elements
  701. * for each key-value, and appends them to the HTML form object.
  702. * @method appendPostData
  703. * @private
  704. * @static
  705. * @param {string} postData The HTTP POST data
  706. * @return {array} formElements Collection of hidden fields.
  707. */
  708. appendPostData:function(postData)
  709. {
  710. var formElements = [];
  711. var postMessage = postData.split('&');
  712. for(var i=0; i < postMessage.length; i++){
  713. var delimitPos = postMessage[i].indexOf('=');
  714. if(delimitPos != -1){
  715. formElements[i] = document.createElement('input');
  716. formElements[i].type = 'hidden';
  717. formElements[i].name = postMessage[i].substring(0,delimitPos);
  718. formElements[i].value = postMessage[i].substring(delimitPos+1);
  719. this._formNode.appendChild(formElements[i]);
  720. }
  721. }
  722. return formElements;
  723. },
  724. /**
  725. * @description Uploads HTML form, including files/attachments, to the
  726. * iframe created in createFrame.
  727. * @method uploadFile
  728. * @private
  729. * @static
  730. * @param {int} id The transaction id.
  731. * @param {object} callback - User-defined callback object.
  732. * @param {string} uri Fully qualified path of resource.
  733. * @return {void}
  734. */
  735. uploadFile:function(id, callback, uri, postData){
  736. // Each iframe has an id prefix of "yuiIO" followed
  737. // by the unique transaction id.
  738. var frameId = 'yuiIO' + id;
  739. var io = document.getElementById(frameId);
  740. // Initialize the HTML form properties in case they are
  741. // not defined in the HTML form.
  742. this._formNode.action = uri;
  743. this._formNode.method = 'POST';
  744. this._formNode.target = frameId;
  745. if(this._formNode.encoding){
  746. // IE does not respect property enctype for HTML forms.
  747. // Instead use property encoding.
  748. this._formNode.encoding = 'multipart/form-data';
  749. }
  750. else{
  751. this._formNode.enctype = 'multipart/form-data';
  752. }
  753. if(postData){
  754. var oElements = this.appendPostData(postData);
  755. }
  756. this._formNode.submit();
  757. if(oElements && oElements.length > 0){
  758. try
  759. {
  760. for(var i=0; i < oElements.length; i++){
  761. this._formNode.removeChild(oElements[i]);
  762. }
  763. }
  764. catch(e){}
  765. }
  766. // Reset HTML form status properties.
  767. this.resetFormState();
  768. // Create the upload callback handler that fires when the iframe
  769. // receives the load event. Subsequently, the event handler is detached
  770. // and the iframe removed from the document.
  771. var uploadCallback = function()
  772. {
  773. var obj = {};
  774. obj.tId = id;
  775. obj.argument = callback.argument;
  776. try
  777. {
  778. obj.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
  779. obj.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
  780. }
  781. catch(e){}
  782. if(callback.upload){
  783. if(!callback.scope){
  784. callback.upload(obj);
  785. }
  786. else{
  787. callback.upload.apply(callback.scope, [obj]);
  788. }
  789. }
  790. if(YAHOO.util.Event){
  791. YAHOO.util.Event.removeListener(io, "load", uploadCallback);
  792. }
  793. else if(window.detachEvent){
  794. io.detachEvent('onload', uploadCallback);
  795. }
  796. else{
  797. io.removeEventListener('load', uploadCallback, false);
  798. }
  799. setTimeout(function(){ document.body.removeChild(io); }, 100);
  800. };
  801. // Bind the onload handler to the iframe to detect the file upload response.
  802. if(YAHOO.util.Event){
  803. YAHOO.util.Event.addListener(io, "load", uploadCallback);
  804. }
  805. else if(window.attachEvent){
  806. io.attachEvent('onload', uploadCallback);
  807. }
  808. else{
  809. io.addEventListener('load', uploadCallback, false);
  810. }
  811. },
  812. /**
  813. * @description Method to terminate a transaction, if it has not reached readyState 4.
  814. * @method abort
  815. * @public
  816. * @static
  817. * @param {object} o The connection object returned by asyncRequest.
  818. * @param {object} callback User-defined callback object.
  819. * @param {string} isTimeout boolean to indicate if abort was a timeout.
  820. * @return {boolean}
  821. */
  822. abort:function(o, callback, isTimeout)
  823. {
  824. if(this.isCallInProgress(o)){
  825. o.conn.abort();
  826. window.clearInterval(this._poll[o.tId]);
  827. delete this._poll[o.tId];
  828. if(isTimeout){
  829. delete this._timeOut[o.tId];
  830. }
  831. this.handleTransactionResponse(o, callback, true);
  832. return true;
  833. }
  834. else{
  835. return false;
  836. }
  837. },
  838. /**
  839. * Public method to check if the transaction is still being processed.
  840. *
  841. * @method isCallInProgress
  842. * @public
  843. * @static
  844. * @param {object} o The connection object returned by asyncRequest
  845. * @return {boolean}
  846. */
  847. isCallInProgress:function(o)
  848. {
  849. // if the XHR object assigned to the transaction has not been dereferenced,
  850. // then check its readyState status. Otherwise, return false.
  851. if(o.conn){
  852. return o.conn.readyState != 4 && o.conn.readyState != 0;
  853. }
  854. else{
  855. //The XHR object has been destroyed.
  856. return false;
  857. }
  858. },
  859. /**
  860. * @description Dereference the XHR instance and the connection object after the transaction is completed.
  861. * @method releaseObject
  862. * @private
  863. * @static
  864. * @param {object} o The connection object
  865. * @return {void}
  866. */
  867. releaseObject:function(o)
  868. {
  869. //dereference the XHR instance.
  870. o.conn = null;
  871. //dereference the connection object.
  872. o = null;
  873. }
  874. };