PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/framework/source/class/qx/io/remote/transport/XmlHttp.js

http://github.com/qooxdoo/qooxdoo
JavaScript | 1016 lines | 544 code | 172 blank | 300 comment | 92 complexity | 1ec2ec06482e1ef137122aa18229db33 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-3.0, MIT
  1. /* ************************************************************************
  2. qooxdoo - the new era of web development
  3. http://qooxdoo.org
  4. Copyright:
  5. 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
  6. 2006 Derrell Lipman
  7. License:
  8. MIT: https://opensource.org/licenses/MIT
  9. See the LICENSE file in the project's top-level directory for details.
  10. Authors:
  11. * Sebastian Werner (wpbasti)
  12. * Andreas Ecker (ecker)
  13. * Derrell Lipman (derrell)
  14. ************************************************************************ */
  15. /**
  16. * Transports requests to a server using the native XmlHttpRequest object.
  17. *
  18. * This class should not be used directly by client programmers.
  19. */
  20. qx.Class.define("qx.io.remote.transport.XmlHttp",
  21. {
  22. extend : qx.io.remote.transport.Abstract,
  23. implement: [ qx.core.IDisposable ],
  24. /*
  25. *****************************************************************************
  26. STATICS
  27. *****************************************************************************
  28. */
  29. statics :
  30. {
  31. /**
  32. * Capabilities of this transport type.
  33. *
  34. * @internal
  35. */
  36. handles :
  37. {
  38. synchronous : true,
  39. asynchronous : true,
  40. crossDomain : false,
  41. fileUpload : false,
  42. programmaticFormFields : false,
  43. responseTypes : [ "text/plain", "text/javascript", "application/json", "application/xml", "text/html" ]
  44. },
  45. /**
  46. * Return a new XMLHttpRequest object suitable for the client browser.
  47. *
  48. * @return {Object} native XMLHttpRequest object
  49. * @signature function()
  50. */
  51. createRequestObject : qx.core.Environment.select("engine.name",
  52. {
  53. "default" : function() {
  54. return new XMLHttpRequest;
  55. },
  56. // IE7's native XmlHttp does not care about trusted zones. To make this
  57. // work in the localhost scenario, you can use the following registry setting:
  58. //
  59. // [HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\
  60. // FeatureControl\FEATURE_XMLHTTP_RESPECT_ZONEPOLICY]
  61. // "Iexplore.exe"=dword:00000001
  62. //
  63. // Generally it seems that the ActiveXObject is more stable. jQuery
  64. // seems to use it always. We prefer the ActiveXObject for the moment, but allow
  65. // fallback to XMLHTTP if ActiveX is disabled.
  66. "mshtml" : function()
  67. {
  68. if (window.ActiveXObject && qx.xml.Document.XMLHTTP) {
  69. return new ActiveXObject(qx.xml.Document.XMLHTTP);
  70. }
  71. if (window.XMLHttpRequest) {
  72. return new XMLHttpRequest;
  73. }
  74. }
  75. }),
  76. /**
  77. * Whether the transport type is supported by the client.
  78. *
  79. * @return {Boolean} supported or not
  80. */
  81. isSupported : function() {
  82. return !!this.createRequestObject();
  83. },
  84. /** The timeout for Xhr requests */
  85. __timeout: 0,
  86. /**
  87. * Sets the timeout for requests
  88. * @deprecated {6.0} This method is deprecated from the start because synchronous I/O itself is deprecated
  89. * in the W3C spec {@link https://xhr.spec.whatwg.org/} and timeouts are indicative of synchronous I/O and/or
  90. * other server issues. However, this API is still supported by many browsers and this API is useful
  91. * for code which has not made the transition to asynchronous I/O
  92. */
  93. setTimeout: function(timeout) {
  94. this.__timeout = timeout;
  95. },
  96. /**
  97. * Returns the timeout for requests
  98. */
  99. getTimeout: function() {
  100. return this.__timeout;
  101. }
  102. },
  103. /*
  104. *****************************************************************************
  105. PROPERTIES
  106. *****************************************************************************
  107. */
  108. properties :
  109. {
  110. /**
  111. * If true and the responseType property is set to "application/json", getResponseContent() will
  112. * return a Javascript map containing the JSON contents, i. e. the result qx.lang.Json.parse().
  113. * If false, the raw string data will be returned and the parsing must be done manually.
  114. * This is useful for special JSON dialects / extensions which are not supported by
  115. * qx.lang.Json.
  116. */
  117. parseJson :
  118. {
  119. check : "Boolean",
  120. init : true
  121. }
  122. },
  123. /*
  124. *****************************************************************************
  125. MEMBERS
  126. *****************************************************************************
  127. */
  128. members :
  129. {
  130. /*
  131. ---------------------------------------------------------------------------
  132. CORE METHODS
  133. ---------------------------------------------------------------------------
  134. */
  135. __localRequest : false,
  136. __lastReadyState : 0,
  137. __request : null,
  138. /**
  139. * Returns the native request object
  140. *
  141. * @return {Object} native XmlHTTPRequest object
  142. */
  143. getRequest : function()
  144. {
  145. if (this.__request === null)
  146. {
  147. this.__request = qx.io.remote.transport.XmlHttp.createRequestObject();
  148. this.__request.onreadystatechange = qx.lang.Function.bind(this._onreadystatechange, this);
  149. }
  150. return this.__request;
  151. },
  152. /*
  153. ---------------------------------------------------------------------------
  154. USER METHODS
  155. ---------------------------------------------------------------------------
  156. */
  157. /**
  158. * Implementation for sending the request
  159. *
  160. */
  161. send : function()
  162. {
  163. this.__lastReadyState = 0;
  164. var vRequest = this.getRequest();
  165. var vMethod = this.getMethod();
  166. var vAsynchronous = this.getAsynchronous();
  167. var vUrl = this.getUrl();
  168. // --------------------------------------
  169. // Local handling
  170. // --------------------------------------
  171. var vLocalRequest = (window.location.protocol === "file:" && !(/^http(s){0,1}\:/.test(vUrl)));
  172. this.__localRequest = vLocalRequest;
  173. // --------------------------------------
  174. // Adding URL parameters
  175. // --------------------------------------
  176. var vParameters = this.getParameters(false);
  177. var vParametersList = [];
  178. for (var vId in vParameters)
  179. {
  180. var value = vParameters[vId];
  181. if (value instanceof Array)
  182. {
  183. for (var i=0; i<value.length; i++) {
  184. vParametersList.push(encodeURIComponent(vId) + "=" + encodeURIComponent(value[i]));
  185. }
  186. }
  187. else
  188. {
  189. vParametersList.push(encodeURIComponent(vId) + "=" + encodeURIComponent(value));
  190. }
  191. }
  192. if (vParametersList.length > 0) {
  193. vUrl += (vUrl.indexOf("?") >= 0 ? "&" : "?") + vParametersList.join("&");
  194. }
  195. // --------------------------------------------------------
  196. // Adding data parameters (if no data is already present)
  197. // --------------------------------------------------------
  198. if (this.getData() === null)
  199. {
  200. var vParameters = this.getParameters(true);
  201. var vParametersList = [];
  202. for (var vId in vParameters)
  203. {
  204. var value = vParameters[vId];
  205. if (value instanceof Array)
  206. {
  207. for (var i=0; i<value.length; i++)
  208. {
  209. vParametersList.push(encodeURIComponent(vId) +
  210. "=" +
  211. encodeURIComponent(value[i]));
  212. }
  213. }
  214. else
  215. {
  216. vParametersList.push(encodeURIComponent(vId) +
  217. "=" +
  218. encodeURIComponent(value));
  219. }
  220. }
  221. if (vParametersList.length > 0)
  222. {
  223. this.setData(vParametersList.join("&"));
  224. }
  225. }
  226. var encode64 = function(input)
  227. {
  228. var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  229. var output = "";
  230. var chr1, chr2, chr3;
  231. var enc1, enc2, enc3, enc4;
  232. var i = 0;
  233. do
  234. {
  235. chr1 = input.charCodeAt(i++);
  236. chr2 = input.charCodeAt(i++);
  237. chr3 = input.charCodeAt(i++);
  238. enc1 = chr1 >> 2;
  239. enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
  240. enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
  241. enc4 = chr3 & 63;
  242. if (isNaN(chr2)) {
  243. enc3 = enc4 = 64;
  244. } else if (isNaN(chr3)) {
  245. enc4 = 64;
  246. }
  247. output += keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
  248. }
  249. while (i < input.length);
  250. return output;
  251. };
  252. // --------------------------------------
  253. // Opening connection
  254. // --------------------------------------
  255. try
  256. {
  257. if (this.getUsername())
  258. {
  259. if (this.getUseBasicHttpAuth())
  260. {
  261. vRequest.open(vMethod, vUrl, vAsynchronous);
  262. vRequest.setRequestHeader('Authorization', 'Basic ' + encode64(this.getUsername() + ':' + this.getPassword()));
  263. }
  264. else
  265. {
  266. vRequest.open(vMethod, vUrl, vAsynchronous, this.getUsername(), this.getPassword());
  267. }
  268. }
  269. else
  270. {
  271. vRequest.open(vMethod, vUrl, vAsynchronous);
  272. }
  273. }
  274. catch(ex)
  275. {
  276. this.error("Failed with exception: " + ex);
  277. this.failed();
  278. return;
  279. }
  280. // Apply timeout
  281. var timeout = qx.io.remote.transport.XmlHttp.getTimeout();
  282. if (timeout && vAsynchronous) {
  283. vRequest.timeout = timeout;
  284. }
  285. // --------------------------------------
  286. // Applying request header
  287. // --------------------------------------
  288. // Removed adding a referer header as this is not allowed anymore on most
  289. // browsers
  290. // See issue https://github.com/qooxdoo/qooxdoo/issues/9298
  291. var vRequestHeaders = this.getRequestHeaders();
  292. for (var vId in vRequestHeaders) {
  293. vRequest.setRequestHeader(vId, vRequestHeaders[vId]);
  294. }
  295. // --------------------------------------
  296. // Sending data
  297. // --------------------------------------
  298. try {
  299. if (qx.core.Environment.get("qx.debug"))
  300. {
  301. if (qx.core.Environment.get("qx.debug.io.remote.data"))
  302. {
  303. this.debug("Request: " + this.getData());
  304. }
  305. }
  306. // IE9 executes the call synchronous when the call is to file protocol
  307. // See [BUG #4762] for details
  308. if (
  309. vLocalRequest && vAsynchronous &&
  310. qx.core.Environment.get("engine.name") == "mshtml" &&
  311. (qx.core.Environment.get("engine.version") == 9 &&
  312. qx.core.Environment.get("browser.documentmode") == 9)
  313. ) {
  314. qx.event.Timer.once(function() {
  315. vRequest.send(this.getData());
  316. }, this, 0);
  317. } else {
  318. vRequest.send(this.getData());
  319. }
  320. }
  321. catch(ex)
  322. {
  323. if (vLocalRequest) {
  324. this.failedLocally();
  325. }
  326. else
  327. {
  328. this.error("Failed to send data to URL '" + vUrl + "': " + ex, "send");
  329. this.failed();
  330. }
  331. return;
  332. }
  333. // --------------------------------------
  334. // Readystate for sync requests
  335. // --------------------------------------
  336. if (!vAsynchronous) {
  337. this._onreadystatechange();
  338. }
  339. },
  340. /**
  341. * Force the transport into the failed state ("failed").
  342. *
  343. * This method should be used only if the requests URI was local
  344. * access. I.e. it started with "file://".
  345. *
  346. */
  347. failedLocally : function()
  348. {
  349. if (this.getState() === "failed") {
  350. return;
  351. }
  352. // should only occur on "file://" access
  353. this.warn("Could not load from file: " + this.getUrl());
  354. this.failed();
  355. },
  356. /*
  357. ---------------------------------------------------------------------------
  358. EVENT HANDLER
  359. ---------------------------------------------------------------------------
  360. */
  361. /**
  362. * Listener method for change of the "readystate".
  363. * Sets the internal state and informs the transport layer.
  364. *
  365. * @signature function(e)
  366. * @param e {Event} native event
  367. */
  368. _onreadystatechange : qx.event.GlobalError.observeMethod(function(e)
  369. {
  370. // Ignoring already stopped requests
  371. switch(this.getState())
  372. {
  373. case "completed":
  374. case "aborted":
  375. case "failed":
  376. case "timeout":
  377. if (qx.core.Environment.get("qx.debug"))
  378. {
  379. if (qx.core.Environment.get("qx.debug.io.remote")) {
  380. this.warn("Ignore Ready State Change");
  381. }
  382. }
  383. return;
  384. }
  385. // Checking status code
  386. var vReadyState = this.getReadyState();
  387. if (vReadyState == 4)
  388. {
  389. // The status code is only meaningful when we reach ready state 4.
  390. // (Important for Opera since it goes through other states before
  391. // reaching 4, and the status code is not valid before 4 is reached.)
  392. if (!qx.io.remote.Exchange.wasSuccessful(this.getStatusCode(), vReadyState, this.__localRequest)) {
  393. // Fix for bug #2272
  394. // The IE doesn't set the state to 'sending' even though the send method
  395. // is called. This only occurs if the server (which is called) goes
  396. // down or a network failure occurs.
  397. if (this.getState() === "configured") {
  398. this.setState("sending");
  399. }
  400. this.failed();
  401. return;
  402. }
  403. }
  404. // Sometimes the xhr call skips the send state
  405. if (vReadyState == 3 && this.__lastReadyState == 1) {
  406. this.setState(qx.io.remote.Exchange._nativeMap[++this.__lastReadyState]);
  407. }
  408. // Updating internal state
  409. while (this.__lastReadyState < vReadyState) {
  410. this.setState(qx.io.remote.Exchange._nativeMap[++this.__lastReadyState]);
  411. }
  412. }),
  413. /*
  414. ---------------------------------------------------------------------------
  415. READY STATE
  416. ---------------------------------------------------------------------------
  417. */
  418. /**
  419. * Get the ready state of this transports request.
  420. *
  421. * For qx.io.remote.transport.XmlHttp, ready state is a number between 1 to 4.
  422. *
  423. * @return {Integer} ready state number
  424. */
  425. getReadyState : function()
  426. {
  427. var vReadyState = null;
  428. try {
  429. vReadyState = this.getRequest().readyState;
  430. } catch(ex) {}
  431. return vReadyState;
  432. },
  433. /*
  434. ---------------------------------------------------------------------------
  435. REQUEST HEADER SUPPORT
  436. ---------------------------------------------------------------------------
  437. */
  438. /**
  439. * Set a request header to this transports request.
  440. *
  441. * @param vLabel {String} Request header name
  442. * @param vValue {var} Request header value
  443. */
  444. setRequestHeader : function(vLabel, vValue) {
  445. this.getRequestHeaders()[vLabel] = vValue;
  446. },
  447. /*
  448. ---------------------------------------------------------------------------
  449. RESPONSE HEADER SUPPORT
  450. ---------------------------------------------------------------------------
  451. */
  452. /**
  453. * Returns a specific header provided by the server upon sending a request,
  454. * with header name determined by the argument headerName.
  455. *
  456. * Only available at readyState 3 and 4 universally and in readyState 2
  457. * in Gecko.
  458. *
  459. * Please note: Some servers/proxies (such as Selenium RC) will capitalize
  460. * response header names. This is in accordance with RFC 2616[1], which
  461. * states that HTTP 1.1 header names are case-insensitive, so your
  462. * application should be case-agnostic when dealing with response headers.
  463. *
  464. * [1]<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2">RFC 2616: HTTP Message Headers</a>
  465. *
  466. * @param vLabel {String} Response header name
  467. * @return {String|null} Response header value
  468. */
  469. getResponseHeader : function(vLabel)
  470. {
  471. var vResponseHeader = null;
  472. try {
  473. vResponseHeader = this.getRequest().getResponseHeader(vLabel) || null;
  474. } catch(ex) {}
  475. return vResponseHeader;
  476. },
  477. /**
  478. * Returns all response headers of the request.
  479. *
  480. * @return {var} response headers
  481. */
  482. getStringResponseHeaders : function()
  483. {
  484. var vSourceHeader = null;
  485. try
  486. {
  487. var vLoadHeader = this.getRequest().getAllResponseHeaders();
  488. if (vLoadHeader) {
  489. vSourceHeader = vLoadHeader;
  490. }
  491. }
  492. catch(ex) {}
  493. return vSourceHeader;
  494. },
  495. /**
  496. * Provides a hash of all response headers.
  497. *
  498. * @return {var} hash of all response headers
  499. */
  500. getResponseHeaders : function()
  501. {
  502. var vSourceHeader = this.getStringResponseHeaders();
  503. var vHeader = {};
  504. if (vSourceHeader)
  505. {
  506. var vValues = vSourceHeader.split(/[\r\n]+/g);
  507. for (var i=0, l=vValues.length; i<l; i++)
  508. {
  509. var vPair = vValues[i].match(/^([^:]+)\s*:\s*(.+)$/i);
  510. if (vPair) {
  511. vHeader[vPair[1]] = vPair[2];
  512. }
  513. }
  514. }
  515. return vHeader;
  516. },
  517. /*
  518. ---------------------------------------------------------------------------
  519. STATUS SUPPORT
  520. ---------------------------------------------------------------------------
  521. */
  522. /**
  523. * Returns the current status code of the request if available or -1 if not.
  524. *
  525. * @return {Integer} current status code
  526. */
  527. getStatusCode : function()
  528. {
  529. var vStatusCode = -1;
  530. try {
  531. vStatusCode = this.getRequest().status;
  532. // [BUG #4476]
  533. // IE sometimes tells 1223 when it should be 204
  534. if (vStatusCode === 1223) {
  535. vStatusCode = 204;
  536. }
  537. } catch(ex) {}
  538. return vStatusCode;
  539. },
  540. /**
  541. * Provides the status text for the current request if available and null
  542. * otherwise.
  543. *
  544. * @return {String} current status code text
  545. */
  546. getStatusText : function()
  547. {
  548. var vStatusText = "";
  549. try {
  550. vStatusText = this.getRequest().statusText;
  551. } catch(ex) {}
  552. return vStatusText;
  553. },
  554. /*
  555. ---------------------------------------------------------------------------
  556. RESPONSE DATA SUPPORT
  557. ---------------------------------------------------------------------------
  558. */
  559. /**
  560. * Provides the response text from the request when available and null
  561. * otherwise. By passing true as the "partial" parameter of this method,
  562. * incomplete data will be made available to the caller.
  563. *
  564. * @return {String} Content of the response as string
  565. */
  566. getResponseText : function()
  567. {
  568. var vResponseText = null;
  569. try
  570. {
  571. vResponseText = this.getRequest().responseText;
  572. }
  573. catch(ex)
  574. {
  575. vResponseText = null;
  576. }
  577. return vResponseText;
  578. },
  579. /**
  580. * Provides the XML provided by the response if any and null otherwise. By
  581. * passing true as the "partial" parameter of this method, incomplete data will
  582. * be made available to the caller.
  583. *
  584. * @return {String} Content of the response as XML
  585. * @throws {Error} If an error within the response occurs.
  586. */
  587. getResponseXml : function()
  588. {
  589. var vResponseXML = null;
  590. var vStatus = this.getStatusCode();
  591. var vReadyState = this.getReadyState();
  592. if (qx.io.remote.Exchange.wasSuccessful(vStatus, vReadyState, this.__localRequest))
  593. {
  594. try {
  595. vResponseXML = this.getRequest().responseXML;
  596. } catch(ex) {}
  597. }
  598. // Typical behaviour on file:// on mshtml
  599. // Could we check this with something like: /^file\:/.test(path); ?
  600. // No browser check here, because it doesn't seem to break other browsers
  601. // * test for this.req.responseXML's objecthood added by *
  602. // * FRM, 20050816 *
  603. if (typeof vResponseXML == "object" && vResponseXML != null)
  604. {
  605. if (!vResponseXML.documentElement)
  606. {
  607. // Clear xml file declaration, this breaks non unicode files (like ones with Umlauts)
  608. var s = String(this.getRequest().responseText).replace(/<\?xml[^\?]*\?>/, "");
  609. vResponseXML.loadXML(s);
  610. }
  611. // Re-check if fixed...
  612. if (!vResponseXML.documentElement) {
  613. throw new Error("Missing Document Element!");
  614. }
  615. if (vResponseXML.documentElement.tagName == "parseerror") {
  616. throw new Error("XML-File is not well-formed!");
  617. }
  618. }
  619. else
  620. {
  621. throw new Error("Response was not a valid xml document [" + this.getRequest().responseText + "]");
  622. }
  623. return vResponseXML;
  624. },
  625. /**
  626. * Returns the length of the content as fetched thus far
  627. *
  628. * @return {Integer} Length of the response text.
  629. */
  630. getFetchedLength : function()
  631. {
  632. var vText = this.getResponseText();
  633. return typeof vText == "string" ? vText.length : 0;
  634. },
  635. /**
  636. * Returns the content of the response
  637. *
  638. * @return {null | String} Response content if available
  639. */
  640. getResponseContent : function()
  641. {
  642. var state = this.getState();
  643. if (state !== "completed" && state != "failed")
  644. {
  645. if (qx.core.Environment.get("qx.debug"))
  646. {
  647. if (qx.core.Environment.get("qx.debug.io.remote")) {
  648. this.warn("Transfer not complete or failed, ignoring content!");
  649. }
  650. }
  651. return null;
  652. }
  653. if (qx.core.Environment.get("qx.debug"))
  654. {
  655. if (qx.core.Environment.get("qx.debug.io.remote")) {
  656. this.debug("Returning content for responseType: " + this.getResponseType());
  657. }
  658. }
  659. var vText = this.getResponseText();
  660. if (state == "failed")
  661. {
  662. if (qx.core.Environment.get("qx.debug"))
  663. {
  664. if (qx.core.Environment.get("qx.debug.io.remote.data"))
  665. {
  666. this.debug("Failed: " + vText);
  667. }
  668. }
  669. return vText;
  670. }
  671. switch(this.getResponseType())
  672. {
  673. case "text/plain":
  674. case "text/html":
  675. if (qx.core.Environment.get("qx.debug"))
  676. {
  677. if (qx.core.Environment.get("qx.debug.io.remote.data"))
  678. {
  679. this.debug("Response: " + vText);
  680. }
  681. }
  682. return vText;
  683. case "application/json":
  684. if (qx.core.Environment.get("qx.debug"))
  685. {
  686. if (qx.core.Environment.get("qx.debug.io.remote.data"))
  687. {
  688. this.debug("Response: " + vText);
  689. }
  690. }
  691. try {
  692. if (vText && vText.length > 0)
  693. {
  694. var ret;
  695. if (this.getParseJson()){
  696. ret = qx.lang.Json.parse(vText);
  697. ret = (ret === 0 ? 0 : (ret || null));
  698. } else {
  699. ret = vText;
  700. }
  701. return ret;
  702. }
  703. else
  704. {
  705. return null;
  706. }
  707. }
  708. catch(ex)
  709. {
  710. this.error("Could not execute json: [" + vText + "]", ex);
  711. return "<pre>Could not execute json: \n" + vText + "\n</pre>";
  712. }
  713. case "text/javascript":
  714. if (qx.core.Environment.get("qx.debug"))
  715. {
  716. if (qx.core.Environment.get("qx.debug.io.remote.data"))
  717. {
  718. this.debug("Response: " + vText);
  719. }
  720. }
  721. try {
  722. if(vText && vText.length > 0)
  723. {
  724. var ret = window.eval(vText);
  725. return (ret === 0 ? 0 : (ret || null));
  726. }
  727. else
  728. {
  729. return null;
  730. }
  731. } catch(ex) {
  732. this.error("Could not execute javascript: [" + vText + "]", ex);
  733. return null;
  734. }
  735. case "application/xml":
  736. vText = this.getResponseXml();
  737. if (qx.core.Environment.get("qx.debug"))
  738. {
  739. if (qx.core.Environment.get("qx.debug.io.remote.data"))
  740. {
  741. this.debug("Response: " + vText);
  742. }
  743. }
  744. return (vText === 0 ? 0 : (vText || null));
  745. default:
  746. this.warn("No valid responseType specified (" + this.getResponseType() + ")!");
  747. return null;
  748. }
  749. },
  750. /*
  751. ---------------------------------------------------------------------------
  752. APPLY ROUTINES
  753. ---------------------------------------------------------------------------
  754. */
  755. /**
  756. * Apply method for the "state" property.
  757. * Fires an event for each state value to inform the listeners.
  758. *
  759. * @param value {var} Current value
  760. * @param old {var} Previous value
  761. */
  762. _applyState : function(value, old)
  763. {
  764. if (qx.core.Environment.get("qx.debug"))
  765. {
  766. if (qx.core.Environment.get("qx.debug.io.remote")) {
  767. this.debug("State: " + value);
  768. }
  769. }
  770. switch(value)
  771. {
  772. case "created":
  773. this.fireEvent("created");
  774. break;
  775. case "configured":
  776. this.fireEvent("configured");
  777. break;
  778. case "sending":
  779. this.fireEvent("sending");
  780. break;
  781. case "receiving":
  782. this.fireEvent("receiving");
  783. break;
  784. case "completed":
  785. this.fireEvent("completed");
  786. break;
  787. case "failed":
  788. this.fireEvent("failed");
  789. break;
  790. case "aborted":
  791. this.getRequest().abort();
  792. this.fireEvent("aborted");
  793. break;
  794. case "timeout":
  795. this.getRequest().abort();
  796. this.fireEvent("timeout");
  797. break;
  798. }
  799. }
  800. },
  801. /*
  802. *****************************************************************************
  803. DEFER
  804. *****************************************************************************
  805. */
  806. defer : function()
  807. {
  808. // basic registration to qx.io.remote.Exchange
  809. // the real availability check (activeX stuff and so on) follows at the first real request
  810. qx.io.remote.Exchange.registerType(qx.io.remote.transport.XmlHttp, "qx.io.remote.transport.XmlHttp");
  811. },
  812. /*
  813. *****************************************************************************
  814. DESTRUCTOR
  815. *****************************************************************************
  816. */
  817. destruct : function()
  818. {
  819. var vRequest = this.getRequest();
  820. if (vRequest)
  821. {
  822. // Clean up state change handler
  823. // Note that for IE the proper way to do this is to set it to a
  824. // dummy function, not null (Google on "onreadystatechange dummy IE unhook")
  825. // http://groups.google.com/group/Google-Web-Toolkit-Contributors/browse_thread/thread/7e7ee67c191a6324
  826. vRequest.onreadystatechange = (function() {});
  827. // Aborting
  828. switch(vRequest.readyState)
  829. {
  830. case 1:
  831. case 2:
  832. case 3:
  833. vRequest.abort();
  834. }
  835. }
  836. this.__request = null;
  837. }
  838. });