PageSourceSearch

https://promans.ru/local/templates/promans/core/plain/js/jquery.iframe.transport.js?176968002310844

js promans.ru collected 2026-10-07 20:43:31 UTC 10,844 bytes, 251 lines download raw bytes

1// This [jQuery](https://jquery.com/) plugin implements an `<iframe>`
2// [transport](https://api.jquery.com/jQuery.ajax/#extending-ajax) so that
3// `$.ajax()` calls support the uploading of files using standard HTML file
4// input fields. This is done by switching the exchange from `XMLHttpRequest`
5// to a hidden `iframe` element containing a form that is submitted.
6
7// The [source for the plugin](https://github.com/cmlenz/jquery-iframe-transport)
8// is available on [Github](https://github.com/) and licensed under the [MIT
9// license](https://github.com/cmlenz/jquery-iframe-transport/blob/master/LICENSE).
10
11// ## Usage
12
13// To use this plugin, you simply add an `iframe` option with the value `true`
14// to the Ajax settings an `$.ajax()` call, and specify the file fields to
15// include in the submssion using the `files` option, which can be a selector,
16// jQuery object, or a list of DOM elements containing one or more
17// `<input type="file">` elements:
18
19//     $("#myform").submit(function() {
20//         $.ajax(this.action, {
21//             files: $(":file", this),
22//             iframe: true
23//         }).complete(function(data) {
24//             console.log(data);
25//         });
26//     });
27
28// The plugin will construct hidden `<iframe>` and `<form>` elements, add the
29// file field(s) to that form, submit the form, and process the response.
30
31// If you want to include other form fields in the form submission, include
32// them in the `data` option, and set the `processData` option to `false`:
33
34//     $("#myform").submit(function() {
35//         $.ajax(this.action, {
36//             data: $(":text", this).serializeArray(),
37//             files: $(":file", this),
38//             iframe: true,
39//             processData: false
40//         }).complete(function(data) {
41//             console.log(data);
42//         });
43//     });
44
45// ### Response Data Types
46
47// As the transport does not have access to the HTTP headers of the server
48// response, it is not as simple to make use of the automatic content type
49// detection provided by jQuery as with regular XHR. If you can't set the
50// expected response data type (for example because it may vary depending on
51// the outcome of processing by the server), you will need to employ a
52// workaround on the server side: Send back an HTML document containing just a
53// `<textarea>` element with a `data-type` attribute that specifies the MIME
54// type, and put the actual payload in the textarea:
55
56//     <textarea data-type="application/json">
57//       {"ok": true, "message": "Thanks so much"}
58//     </textarea>
59
60// The iframe transport plugin will detect this and pass the value of the
61// `data-type` attribute on to jQuery as if it was the "Content-Type" response
62// header, thereby enabling the same kind of conversions that jQuery applies
63// to regular responses. For the example above you should get a Javascript
64// object as the `data` parameter of the `complete` callback, with the
65// properties `ok: true` and `message: "Thanks so much"`.
66
67// ### Handling Server Errors
68
69// Another problem with using an `iframe` for file uploads is that it is
70// impossible for the javascript code to determine the HTTP status code of the
71// servers response. Effectively, all of the calls you make will look like they
72// are getting successful responses, and thus invoke the `done()` or
73// `complete()` callbacks. You can only communicate problems using the content
74// of the response payload. For example, consider using a JSON response such as
75// the following to indicate a problem with an uploaded file:
76
77//     <textarea data-type="application/json">
78//       {"ok": false, "message": "Please only upload reasonably sized files."}
79//     </textarea>
80
81// ### Compatibility
82
83// This plugin has primarily been tested on Safari 5 (or later), Firefox 4 (or
84// later), and Internet Explorer (all the way back to version 6). While I
85// haven't found any issues with it so far, I'm fairly sure it still doesn't
86// work around all the quirks in all different browsers. But the code is still
87// pretty simple overall, so you should be able to fix it and contribute a
88// patch :)
89
90// ## Annotated Source
91
92(function($, undefined) {
93  'use strict';
94
95  // Register a prefilter that checks whether the `iframe` option is set, and
96  // switches to the "iframe" data type if it is `true`.
97  $.ajaxPrefilter(function(options, origOptions, jqXHR) {
98    if (options.iframe) {
99      options.originalURL = options.url;
100      return 'iframe';
101    }
102  });
103
104  // Register a transport for the "iframe" data type. It will only activate
105  // when the "files" option has been set to a non-empty list of enabled file
106  // inputs.
107  $.ajaxTransport('iframe', function(options, origOptions, jqXHR) {
108    var form = null,
109        iframe = null,
110        name = 'iframe-' + $.now(),
111        files = $(options.files).filter(':file:enabled'),
112        markers = null,
113        accepts = null;
114
115    // This function gets called after a successful submission or an abortion
116    // and should revert all changes made to the page to enable the
117    // submission via this transport.
118    function cleanUp() {
119      files.each(function(i, file) {
120        var $file = $(file);
121        $file.data('clone').replaceWith($file);
122      });
123      form.remove();
124      iframe.one('load', function() {
125        iframe.remove();
126      });
127      iframe.attr('src', 'javascript:false;');
128    }
129
130    // Remove "iframe" from the data types list so that further processing is
131    // based on the content type returned by the server, without attempting an
132    // (unsupported) conversion from "iframe" to the actual type.
133    options.dataTypes.shift();
134
135    // Use the data from the original AJAX options, as it doesn't seem to be 
136    // copied over since jQuery 1.7.
137    // See https://github.com/cmlenz/jquery-iframe-transport/issues/6
138    options.data = origOptions.data;
139
140    if (files.length) {
141      form = $('<form enctype=\'multipart/form-data\' method=\'post\'></form>').
142          hide().attr({action: options.originalURL, target: name});
143
144      // If there is any additional data specified via the `data` option,
145      // we add it as hidden fields to the form. This (currently) requires
146      // the `processData` option to be set to false so that the data doesn't
147      // get serialized to a string.
148      if (typeof (options.data) === 'string' && options.data.length > 0) {
149        $.error('data must not be serialized');
150      }
151      $.each(options.data || {}, function(name, value) {
152        if ($.isPlainObject(value)) {
153          name = value.name;
154          value = value.value;
155        }
156        $('<input type=\'hidden\' />').attr({name: name, value: value}).
157            appendTo(form);
158      });
159
160      // Add a hidden `X-Requested-With` field with the value `IFrame` to the
161      // field, to help server-side code to determine that the upload happened
162      // through this transport.
163      $('<input type=\'hidden\' value=\'IFrame\' name=\'X-Requested-With\' />').
164          appendTo(form);
165
166      // Borrowed straight from the JQuery source.
167      // Provides a way of specifying the accepted data type similar to the
168      // HTTP "Accept" header
169      if (options.dataTypes[0] && options.accepts[options.dataTypes[0]]) {
170        accepts = options.accepts[options.dataTypes[0]] +
171            (options.dataTypes[0] !== '*' ? ', */*; q=0.01' : '');
172      } else {
173        accepts = options.accepts['*'];
174      }
175      $('<input type=\'hidden\' name=\'X-HTTP-Accept\'>').
176          attr('value', accepts).appendTo(form);
177
178      // Move the file fields into the hidden form, but first remember their
179      // original locations in the document by replacing them with disabled
180      // clones. This should also avoid introducing unwanted changes to the
181      // page layout during submission.
182      markers = files.after(function(idx) {
183        var $this = $(this),
184            $clone = $this.clone().prop('disabled', true);
185        $this.data('clone', $clone);
186        return $clone;
187      }).next();
188      files.appendTo(form);
189
190      return {
191
192        // The `send` function is called by jQuery when the request should be
193        // sent.
194        send: function(headers, completeCallback) {
195          iframe = $('<iframe src=\'javascript:false;\' name=\'' + name +
196              '\' id=\'' + name + '\' style=\'display:none\'></iframe>');
197
198          // The first load event gets fired after the iframe has been injected
199          // into the DOM, and is used to prepare the actual submission.
200          iframe.one('load', function() {
201
202            // The second load event gets fired when the response to the form
203            // submission is received. The implementation detects whether the
204            // actual payload is embedded in a `<textarea>` element, and
205            // prepares the required conversions to be made in that case.
206            iframe.one('load', function() {
207              var doc = this.contentWindow ? this.contentWindow.document :
208                      (this.contentDocument ? this.contentDocument : this.document),
209                  root = doc.documentElement ? doc.documentElement : doc.body,
210                  textarea = root.getElementsByTagName('textarea')[0],
211                  type = textarea && textarea.getAttribute('data-type') || null,
212                  status = textarea && textarea.getAttribute('data-status') ||
213                      200,
214                  statusText = textarea &&
215                      textarea.getAttribute('data-statusText') || 'OK',
216                  content = {
217                    html: root.innerHTML,
218                    text: type ?
219                        textarea.value :
220                        root ? (root.textContent || root.innerText) : null,
221                  };
222              cleanUp();
223              completeCallback(status, statusText, content, type ?
224                  ('Content-Type: ' + type) :
225                  null);
226            });
227
228            // Now that the load handler has been set up, submit the form.
229            form[0].submit();
230          });
231
232          // After everything has been set up correctly, the form and iframe
233          // get injected into the DOM so that the submission can be
234          // initiated.
235          $('body').append(form, iframe);
236        },
237
238        // The `abort` function is called by jQuery when the request should be
239        // aborted.
240        abort: function() {
241          if (iframe !== null) {
242            iframe.unbind('load').attr('src', 'javascript:false;');
243            cleanUp();
244          }
245        },
246
247      };
248    }
249  });
250
251})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.