Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

228 строки
8.7 KiB

  1. /*
  2. * jQuery Iframe Transport Plugin
  3. * https://github.com/blueimp/jQuery-File-Upload
  4. *
  5. * Copyright 2011, Sebastian Tschan
  6. * https://blueimp.net
  7. *
  8. * Licensed under the MIT license:
  9. * https://opensource.org/licenses/MIT
  10. */
  11. /* global define, require */
  12. (function (factory) {
  13. 'use strict';
  14. if (typeof define === 'function' && define.amd) {
  15. // Register as an anonymous AMD module:
  16. define(['jquery'], factory);
  17. } else if (typeof exports === 'object') {
  18. // Node/CommonJS:
  19. factory(require('jquery'));
  20. } else {
  21. // Browser globals:
  22. factory(window.jQuery);
  23. }
  24. })(function ($) {
  25. 'use strict';
  26. // Helper variable to create unique names for the transport iframes:
  27. var counter = 0,
  28. jsonAPI = $,
  29. jsonParse = 'parseJSON';
  30. if ('JSON' in window && 'parse' in JSON) {
  31. jsonAPI = JSON;
  32. jsonParse = 'parse';
  33. }
  34. // The iframe transport accepts four additional options:
  35. // options.fileInput: a jQuery collection of file input fields
  36. // options.paramName: the parameter name for the file form data,
  37. // overrides the name property of the file input field(s),
  38. // can be a string or an array of strings.
  39. // options.formData: an array of objects with name and value properties,
  40. // equivalent to the return data of .serializeArray(), e.g.:
  41. // [{name: 'a', value: 1}, {name: 'b', value: 2}]
  42. // options.initialIframeSrc: the URL of the initial iframe src,
  43. // by default set to "javascript:false;"
  44. $.ajaxTransport('iframe', function (options) {
  45. if (options.async) {
  46. // javascript:false as initial iframe src
  47. // prevents warning popups on HTTPS in IE6:
  48. // eslint-disable-next-line no-script-url
  49. var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
  50. form,
  51. iframe,
  52. addParamChar;
  53. return {
  54. send: function (_, completeCallback) {
  55. form = $('<form style="display:none;"></form>');
  56. form.attr('accept-charset', options.formAcceptCharset);
  57. addParamChar = /\?/.test(options.url) ? '&' : '?';
  58. // XDomainRequest only supports GET and POST:
  59. if (options.type === 'DELETE') {
  60. options.url = options.url + addParamChar + '_method=DELETE';
  61. options.type = 'POST';
  62. } else if (options.type === 'PUT') {
  63. options.url = options.url + addParamChar + '_method=PUT';
  64. options.type = 'POST';
  65. } else if (options.type === 'PATCH') {
  66. options.url = options.url + addParamChar + '_method=PATCH';
  67. options.type = 'POST';
  68. }
  69. // IE versions below IE8 cannot set the name property of
  70. // elements that have already been added to the DOM,
  71. // so we set the name along with the iframe HTML markup:
  72. counter += 1;
  73. iframe = $(
  74. '<iframe src="' +
  75. initialIframeSrc +
  76. '" name="iframe-transport-' +
  77. counter +
  78. '"></iframe>'
  79. ).on('load', function () {
  80. var fileInputClones,
  81. paramNames = $.isArray(options.paramName)
  82. ? options.paramName
  83. : [options.paramName];
  84. iframe.off('load').on('load', function () {
  85. var response;
  86. // Wrap in a try/catch block to catch exceptions thrown
  87. // when trying to access cross-domain iframe contents:
  88. try {
  89. response = iframe.contents();
  90. // Google Chrome and Firefox do not throw an
  91. // exception when calling iframe.contents() on
  92. // cross-domain requests, so we unify the response:
  93. if (!response.length || !response[0].firstChild) {
  94. throw new Error();
  95. }
  96. } catch (e) {
  97. response = undefined;
  98. }
  99. // The complete callback returns the
  100. // iframe content document as response object:
  101. completeCallback(200, 'success', { iframe: response });
  102. // Fix for IE endless progress bar activity bug
  103. // (happens on form submits to iframe targets):
  104. $('<iframe src="' + initialIframeSrc + '"></iframe>').appendTo(
  105. form
  106. );
  107. window.setTimeout(function () {
  108. // Removing the form in a setTimeout call
  109. // allows Chrome's developer tools to display
  110. // the response result
  111. form.remove();
  112. }, 0);
  113. });
  114. form
  115. .prop('target', iframe.prop('name'))
  116. .prop('action', options.url)
  117. .prop('method', options.type);
  118. if (options.formData) {
  119. $.each(options.formData, function (index, field) {
  120. $('<input type="hidden"/>')
  121. .prop('name', field.name)
  122. .val(field.value)
  123. .appendTo(form);
  124. });
  125. }
  126. if (
  127. options.fileInput &&
  128. options.fileInput.length &&
  129. options.type === 'POST'
  130. ) {
  131. fileInputClones = options.fileInput.clone();
  132. // Insert a clone for each file input field:
  133. options.fileInput.after(function (index) {
  134. return fileInputClones[index];
  135. });
  136. if (options.paramName) {
  137. options.fileInput.each(function (index) {
  138. $(this).prop('name', paramNames[index] || options.paramName);
  139. });
  140. }
  141. // Appending the file input fields to the hidden form
  142. // removes them from their original location:
  143. form
  144. .append(options.fileInput)
  145. .prop('enctype', 'multipart/form-data')
  146. // enctype must be set as encoding for IE:
  147. .prop('encoding', 'multipart/form-data');
  148. // Remove the HTML5 form attribute from the input(s):
  149. options.fileInput.removeAttr('form');
  150. }
  151. window.setTimeout(function () {
  152. // Submitting the form in a setTimeout call fixes an issue with
  153. // Safari 13 not triggering the iframe load event after resetting
  154. // the load event handler, see also:
  155. // https://github.com/blueimp/jQuery-File-Upload/issues/3633
  156. form.submit();
  157. // Insert the file input fields at their original location
  158. // by replacing the clones with the originals:
  159. if (fileInputClones && fileInputClones.length) {
  160. options.fileInput.each(function (index, input) {
  161. var clone = $(fileInputClones[index]);
  162. // Restore the original name and form properties:
  163. $(input)
  164. .prop('name', clone.prop('name'))
  165. .attr('form', clone.attr('form'));
  166. clone.replaceWith(input);
  167. });
  168. }
  169. }, 0);
  170. });
  171. form.append(iframe).appendTo(document.body);
  172. },
  173. abort: function () {
  174. if (iframe) {
  175. // javascript:false as iframe src aborts the request
  176. // and prevents warning popups on HTTPS in IE6.
  177. iframe.off('load').prop('src', initialIframeSrc);
  178. }
  179. if (form) {
  180. form.remove();
  181. }
  182. }
  183. };
  184. }
  185. });
  186. // The iframe transport returns the iframe content document as response.
  187. // The following adds converters from iframe to text, json, html, xml
  188. // and script.
  189. // Please note that the Content-Type for JSON responses has to be text/plain
  190. // or text/html, if the browser doesn't include application/json in the
  191. // Accept header, else IE will show a download dialog.
  192. // The Content-Type for XML responses on the other hand has to be always
  193. // application/xml or text/xml, so IE properly parses the XML response.
  194. // See also
  195. // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation
  196. $.ajaxSetup({
  197. converters: {
  198. 'iframe text': function (iframe) {
  199. return iframe && $(iframe[0].body).text();
  200. },
  201. 'iframe json': function (iframe) {
  202. return iframe && jsonAPI[jsonParse]($(iframe[0].body).text());
  203. },
  204. 'iframe html': function (iframe) {
  205. return iframe && $(iframe[0].body).html();
  206. },
  207. 'iframe xml': function (iframe) {
  208. var xmlDoc = iframe && iframe[0];
  209. return xmlDoc && $.isXMLDoc(xmlDoc)
  210. ? xmlDoc
  211. : $.parseXML(
  212. (xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) ||
  213. $(xmlDoc.body).html()
  214. );
  215. },
  216. 'iframe script': function (iframe) {
  217. return iframe && $.globalEval($(iframe[0].body).text());
  218. }
  219. }
  220. });
  221. });