mxXmlRequest.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /**
  2. * Copyright (c) 2006-2020, JGraph Ltd
  3. * Copyright (c) 2006-2020, draw.io AG
  4. */
  5. /**
  6. * Class: mxXmlRequest
  7. *
  8. * XML HTTP request wrapper. See also: <mxUtils.get>, <mxUtils.post> and
  9. * <mxUtils.load>. This class provides a cross-browser abstraction for Ajax
  10. * requests.
  11. *
  12. * Encoding:
  13. *
  14. * For encoding parameter values, the built-in encodeURIComponent JavaScript
  15. * method must be used. For automatic encoding of post data in <mxEditor> the
  16. * <mxEditor.escapePostData> switch can be set to true (default). The encoding
  17. * will be carried out using the conte type of the page. That is, the page
  18. * containting the editor should contain a meta tag in the header, eg.
  19. * <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  20. *
  21. * Example:
  22. *
  23. * (code)
  24. * var onload = function(req)
  25. * {
  26. * mxUtils.alert(req.getDocumentElement());
  27. * }
  28. *
  29. * var onerror = function(req)
  30. * {
  31. * mxUtils.alert('Error');
  32. * }
  33. * new mxXmlRequest(url, 'key=value').send(onload, onerror);
  34. * (end)
  35. *
  36. * Sends an asynchronous POST request to the specified URL.
  37. *
  38. * Example:
  39. *
  40. * (code)
  41. * var req = new mxXmlRequest(url, 'key=value', 'POST', false);
  42. * req.send();
  43. * mxUtils.alert(req.getDocumentElement());
  44. * (end)
  45. *
  46. * Sends a synchronous POST request to the specified URL.
  47. *
  48. * Example:
  49. *
  50. * (code)
  51. * var encoder = new mxCodec();
  52. * var result = encoder.encode(graph.getModel());
  53. * var xml = encodeURIComponent(mxUtils.getXml(result));
  54. * new mxXmlRequest(url, 'xml='+xml).send();
  55. * (end)
  56. *
  57. * Sends an encoded graph model to the specified URL using xml as the
  58. * parameter name. The parameter can then be retrieved in C# as follows:
  59. *
  60. * (code)
  61. * string xml = HttpUtility.UrlDecode(context.Request.Params["xml"]);
  62. * (end)
  63. *
  64. * Or in Java as follows:
  65. *
  66. * (code)
  67. * String xml = URLDecoder.decode(request.getParameter("xml"), "UTF-8").replace("\n", "&#xa;");
  68. * (end)
  69. *
  70. * Note that the linefeeds should only be replaced if the XML is
  71. * processed in Java, for example when creating an image.
  72. *
  73. * Constructor: mxXmlRequest
  74. *
  75. * Constructs an XML HTTP request.
  76. *
  77. * Parameters:
  78. *
  79. * url - Target URL of the request.
  80. * params - Form encoded parameters to send with a POST request.
  81. * method - String that specifies the request method. Possible values are
  82. * POST and GET. Default is POST.
  83. * async - Boolean specifying if an asynchronous request should be used.
  84. * Default is true.
  85. * username - String specifying the username to be used for the request.
  86. * password - String specifying the password to be used for the request.
  87. */
  88. function mxXmlRequest(url, params, method, async, username, password)
  89. {
  90. this.url = url;
  91. this.params = params;
  92. this.method = method || 'POST';
  93. this.async = (async != null) ? async : true;
  94. this.username = username;
  95. this.password = password;
  96. };
  97. /**
  98. * Variable: url
  99. *
  100. * Holds the target URL of the request.
  101. */
  102. mxXmlRequest.prototype.url = null;
  103. /**
  104. * Variable: params
  105. *
  106. * Holds the form encoded data for the POST request.
  107. */
  108. mxXmlRequest.prototype.params = null;
  109. /**
  110. * Variable: method
  111. *
  112. * Specifies the request method. Possible values are POST and GET. Default
  113. * is POST.
  114. */
  115. mxXmlRequest.prototype.method = null;
  116. /**
  117. * Variable: async
  118. *
  119. * Boolean indicating if the request is asynchronous.
  120. */
  121. mxXmlRequest.prototype.async = null;
  122. /**
  123. * Variable: binary
  124. *
  125. * Boolean indicating if the request is binary. This option is ignored in IE.
  126. * In all other browsers the requested mime type is set to
  127. * text/plain; charset=x-user-defined. Default is false.
  128. */
  129. mxXmlRequest.prototype.binary = false;
  130. /**
  131. * Variable: withCredentials
  132. *
  133. * Specifies if withCredentials should be used in HTML5-compliant browsers. Default is
  134. * false.
  135. */
  136. mxXmlRequest.prototype.withCredentials = false;
  137. /**
  138. * Variable: username
  139. *
  140. * Specifies the username to be used for authentication.
  141. */
  142. mxXmlRequest.prototype.username = null;
  143. /**
  144. * Variable: password
  145. *
  146. * Specifies the password to be used for authentication.
  147. */
  148. mxXmlRequest.prototype.password = null;
  149. /**
  150. * Variable: request
  151. *
  152. * Holds the inner, browser-specific request object.
  153. */
  154. mxXmlRequest.prototype.request = null;
  155. /**
  156. * Variable: decodeSimulateValues
  157. *
  158. * Specifies if request values should be decoded as URIs before setting the
  159. * textarea value in <simulate>. Defaults to false for backwards compatibility,
  160. * to avoid another decode on the server this should be set to true.
  161. */
  162. mxXmlRequest.prototype.decodeSimulateValues = false;
  163. /**
  164. * Function: isBinary
  165. *
  166. * Returns <binary>.
  167. */
  168. mxXmlRequest.prototype.isBinary = function()
  169. {
  170. return this.binary;
  171. };
  172. /**
  173. * Function: setBinary
  174. *
  175. * Sets <binary>.
  176. */
  177. mxXmlRequest.prototype.setBinary = function(value)
  178. {
  179. this.binary = value;
  180. };
  181. /**
  182. * Function: getText
  183. *
  184. * Returns the response as a string.
  185. */
  186. mxXmlRequest.prototype.getText = function()
  187. {
  188. return this.request.responseText;
  189. };
  190. /**
  191. * Function: isReady
  192. *
  193. * Returns true if the response is ready.
  194. */
  195. mxXmlRequest.prototype.isReady = function()
  196. {
  197. return this.request.readyState == 4;
  198. };
  199. /**
  200. * Function: getDocumentElement
  201. *
  202. * Returns the document element of the response XML document.
  203. */
  204. mxXmlRequest.prototype.getDocumentElement = function()
  205. {
  206. var doc = this.getXml();
  207. if (doc != null)
  208. {
  209. return doc.documentElement;
  210. }
  211. return null;
  212. };
  213. /**
  214. * Function: getXml
  215. *
  216. * Returns the response as an XML document. Use <getDocumentElement> to get
  217. * the document element of the XML document.
  218. */
  219. mxXmlRequest.prototype.getXml = function()
  220. {
  221. var xml = this.request.responseXML;
  222. // Handles missing response headers in IE, the first condition handles
  223. // the case where responseXML is there, but using its nodes leads to
  224. // type errors in the mxCellCodec when putting the nodes into a new
  225. // document. This happens in IE9 standards mode and with XML user
  226. // objects only, as they are used directly as values in cells.
  227. if (document.documentMode >= 9 || xml == null || xml.documentElement == null)
  228. {
  229. xml = mxUtils.parseXml(this.request.responseText);
  230. }
  231. return xml;
  232. };
  233. /**
  234. * Function: getStatus
  235. *
  236. * Returns the status as a number, eg. 404 for "Not found" or 200 for "OK".
  237. * Note: The NS_ERROR_NOT_AVAILABLE for invalid responses cannot be cought.
  238. */
  239. mxXmlRequest.prototype.getStatus = function()
  240. {
  241. return (this.request != null) ? this.request.status : null;
  242. };
  243. /**
  244. * Function: create
  245. *
  246. * Creates and returns the inner <request> object.
  247. */
  248. mxXmlRequest.prototype.create = function()
  249. {
  250. if (window.XMLHttpRequest)
  251. {
  252. return function()
  253. {
  254. var req = new XMLHttpRequest();
  255. // TODO: Check for overrideMimeType required here?
  256. if (this.isBinary() && req.overrideMimeType)
  257. {
  258. req.overrideMimeType('text/plain; charset=x-user-defined');
  259. }
  260. return req;
  261. };
  262. }
  263. else if (typeof(ActiveXObject) != 'undefined')
  264. {
  265. return function()
  266. {
  267. // TODO: Implement binary option
  268. return new ActiveXObject('Microsoft.XMLHTTP');
  269. };
  270. }
  271. }();
  272. /**
  273. * Function: send
  274. *
  275. * Send the <request> to the target URL using the specified functions to
  276. * process the response asychronously.
  277. *
  278. * Note: Due to technical limitations, onerror is currently ignored.
  279. *
  280. * Parameters:
  281. *
  282. * onload - Function to be invoked if a successful response was received.
  283. * onerror - Function to be called on any error. Unused in this implementation, intended for overriden function.
  284. * timeout - Optional timeout in ms before calling ontimeout.
  285. * ontimeout - Optional function to execute on timeout.
  286. */
  287. mxXmlRequest.prototype.send = function(onload, onerror, timeout, ontimeout)
  288. {
  289. this.request = this.create();
  290. if (this.request != null)
  291. {
  292. if (onload != null)
  293. {
  294. this.request.onreadystatechange = mxUtils.bind(this, function()
  295. {
  296. if (this.isReady())
  297. {
  298. onload(this);
  299. this.request.onreadystatechange = null;
  300. }
  301. });
  302. }
  303. this.request.open(this.method, this.url, this.async,
  304. this.username, this.password);
  305. this.setRequestHeaders(this.request, this.params);
  306. if (window.XMLHttpRequest && this.withCredentials)
  307. {
  308. this.request.withCredentials = 'true';
  309. }
  310. if (!mxClient.IS_QUIRKS && (document.documentMode == null || document.documentMode > 9) &&
  311. window.XMLHttpRequest && timeout != null && ontimeout != null)
  312. {
  313. this.request.timeout = timeout;
  314. this.request.ontimeout = ontimeout;
  315. }
  316. this.request.send(this.params);
  317. }
  318. };
  319. /**
  320. * Function: setRequestHeaders
  321. *
  322. * Sets the headers for the given request and parameters. This sets the
  323. * content-type to application/x-www-form-urlencoded if any params exist.
  324. *
  325. * Example:
  326. *
  327. * (code)
  328. * request.setRequestHeaders = function(request, params)
  329. * {
  330. * if (params != null)
  331. * {
  332. * request.setRequestHeader('Content-Type',
  333. * 'multipart/form-data');
  334. * request.setRequestHeader('Content-Length',
  335. * params.length);
  336. * }
  337. * };
  338. * (end)
  339. *
  340. * Use the code above before calling <send> if you require a
  341. * multipart/form-data request.
  342. */
  343. mxXmlRequest.prototype.setRequestHeaders = function(request, params)
  344. {
  345. if (params != null)
  346. {
  347. request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  348. }
  349. };
  350. /**
  351. * Function: simulate
  352. *
  353. * Creates and posts a request to the given target URL using a dynamically
  354. * created form inside the given document.
  355. *
  356. * Parameters:
  357. *
  358. * docs - Document that contains the form element.
  359. * target - Target to send the form result to.
  360. */
  361. mxXmlRequest.prototype.simulate = function(doc, target)
  362. {
  363. doc = doc || document;
  364. var old = null;
  365. if (doc == document)
  366. {
  367. old = window.onbeforeunload;
  368. window.onbeforeunload = null;
  369. }
  370. var form = doc.createElement('form');
  371. form.setAttribute('method', this.method);
  372. form.setAttribute('action', this.url);
  373. if (target != null)
  374. {
  375. form.setAttribute('target', target);
  376. }
  377. form.style.display = 'none';
  378. form.style.visibility = 'hidden';
  379. var pars = (this.params.indexOf('&') > 0) ?
  380. this.params.split('&') :
  381. this.params.split();
  382. // Adds the parameters as textareas to the form
  383. for (var i=0; i<pars.length; i++)
  384. {
  385. var pos = pars[i].indexOf('=');
  386. if (pos > 0)
  387. {
  388. var name = pars[i].substring(0, pos);
  389. var value = pars[i].substring(pos+1);
  390. if (this.decodeSimulateValues)
  391. {
  392. value = decodeURIComponent(value);
  393. }
  394. var textarea = doc.createElement('textarea');
  395. textarea.setAttribute('wrap', 'off');
  396. textarea.setAttribute('name', name);
  397. mxUtils.write(textarea, value);
  398. form.appendChild(textarea);
  399. }
  400. }
  401. doc.body.appendChild(form);
  402. form.submit();
  403. if (form.parentNode != null)
  404. {
  405. form.parentNode.removeChild(form);
  406. }
  407. if (old != null)
  408. {
  409. window.onbeforeunload = old;
  410. }
  411. };
  412. __mxOutput.mxXmlRequest = typeof mxXmlRequest !== 'undefined' ? mxXmlRequest : undefined;