754676f7201831af1f6327413c57390e5c3eef54.svn-base 29 KB

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