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