remotipart 0.4.2 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +8 -1
- data/README.rdoc +55 -33
- data/lib/generators/remotipart/install/install_generator.rb +4 -4
- data/lib/remotipart/middleware.rb +33 -0
- data/lib/remotipart/rails/engine.rb +5 -0
- data/lib/remotipart/rails/railtie.rb +6 -1
- data/lib/remotipart/rails/version.rb +2 -2
- data/lib/remotipart/render_overrides.rb +15 -0
- data/lib/remotipart/request_helper.rb +1 -0
- data/lib/remotipart/view_helper.rb +3 -7
- data/lib/remotipart.rb +2 -0
- data/remotipart.gemspec +4 -2
- data/vendor/assets/javascripts/jquery.iframe-transport.js +233 -0
- data/vendor/assets/javascripts/jquery.remotipart.js +25 -40
- metadata +6 -5
- data/vendor/assets/javascripts/jquery.form.js +0 -911
data/History.rdoc
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
= History
|
2
2
|
|
3
|
-
=== 0
|
3
|
+
=== 1.0 / 2011-08-26
|
4
|
+
|
5
|
+
* New Features
|
6
|
+
* New dependency on simpler jquery.iframe-transport.js (no more form.js)
|
7
|
+
* New Rack middleware, making `remotipart_response` block obsolete in js.erb responses
|
8
|
+
* Better support for all requested ajax data-types
|
9
|
+
|
10
|
+
=== 0.4.2 / 2011-08-26
|
4
11
|
|
5
12
|
* Minor Enhancements
|
6
13
|
* Updated to jquery.form.js v2.84
|
data/README.rdoc
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
= Remotipart
|
2
2
|
|
3
|
-
Remotipart is a Ruby on Rails gem enabling
|
4
|
-
This gem augments the native Rails jQuery remote form
|
3
|
+
Remotipart is a Ruby on Rails gem enabling AJAX file uploads with jQuery in Rails 3.0 and Rails 3.1 remote forms.
|
4
|
+
This gem augments the native Rails jQuery remote form functionality enabling asynchronous file uploads with little to no modification to your application.
|
5
5
|
|
6
|
-
{
|
6
|
+
* {Homepage and Demos}[http://www.alfajango.com/blog/remotipart-rails-gem/]
|
7
|
+
* {How AJAX File Uploads Work}[http://www.alfajango.com/blog/ajax-file-uploads-with-the-iframe-method/]
|
7
8
|
|
8
9
|
== Dependencies
|
9
10
|
|
@@ -12,24 +13,33 @@ This gem augments the native Rails jQuery remote form function enabling asynchro
|
|
12
13
|
|
13
14
|
== Installation
|
14
15
|
|
15
|
-
<b>
|
16
|
-
|
16
|
+
<b>Your app should be using jquery-rails gem v1.0.12 or above.</b>
|
17
|
+
|
18
|
+
If you're using an old version of the jquery-rails gem,
|
19
|
+
make sure you have a supported jquery-ujs (rails.js or jquery_ujs.js) version from {VERSION_COMPATIBILITY}[https://github.com/JangoSteve/remotipart/blob/master/VERSION_COMPATIBILITY.rdoc].
|
17
20
|
|
18
21
|
[1.]
|
19
22
|
Install the Remotipart gem
|
20
23
|
|
21
|
-
* Add this line to your GEMFILE (
|
24
|
+
* Add this line to your GEMFILE (use the appropriate version from the compatibilty chart if needed)
|
22
25
|
|
23
|
-
gem 'remotipart', '~> 0
|
26
|
+
gem 'remotipart', '~> 1.0'
|
24
27
|
|
25
28
|
* And run
|
26
29
|
|
27
30
|
bundle install
|
28
31
|
|
32
|
+
=== Rails 3.1
|
33
|
+
|
34
|
+
[2.]
|
35
|
+
The necessary js files will automatically be added to the asset pipeline, so add the following to app/assets/javascripts/application.js (right after <tt>//= require jquery_ujs</tt>):
|
36
|
+
|
37
|
+
//= require jquery.remotipart
|
38
|
+
|
29
39
|
=== Rails 3.0
|
30
40
|
|
31
41
|
[2.]
|
32
|
-
Run the Remotipart install generator to add jquery.
|
42
|
+
Run the Remotipart install generator to add jquery.iframe-transport.js and jquery.remotipart.js to public/javascripts/
|
33
43
|
|
34
44
|
rails g remotipart:install
|
35
45
|
|
@@ -38,28 +48,12 @@ make sure you have a supported jquery-ujs (rails.js or jquery_ujs.js) version fr
|
|
38
48
|
|
39
49
|
<%= javascript_include_tag :defaults %>
|
40
50
|
|
41
|
-
=== Rails 3.1
|
42
|
-
|
43
|
-
[2.]
|
44
|
-
The necessary js files will automatically be added to the asset pipeline, so add the following to app/assets/javascripts/application.js (right after <tt>//= require jquery_ujs</tt>):
|
45
|
-
|
46
|
-
//= require jquery.form
|
47
|
-
//= require jquery.remotipart
|
48
|
-
|
49
51
|
== Usage
|
50
52
|
|
51
53
|
* For multipart / forms with file inputs, set your form_for to remote as you would for a normal ajax form:
|
52
54
|
:remote => true
|
53
55
|
* When Javascript is enabled in the user's browser, the form, including the file, will be submitted asynchronously to your controller with:
|
54
56
|
:format == 'js'
|
55
|
-
* In the JS response template for your controller action, wrap all of your response code in one remotipart_response block:
|
56
|
-
<%= remotipart_response do %> All Javascript response code goes here <% end %>
|
57
|
-
* The options available to the text_area_tag[http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-text_area_tag] can be passed to remotipart_response for further control over the response. For instance:
|
58
|
-
<%= remotipart_response({:escape => false}) do %> All Javascript response code goes here <% end %>
|
59
|
-
* Anything inside the +remotipart_response+ block will be rendered normally, unless the request actually did come from a remotipart-submitted form. So <tt>js.erb</tt> responses can be shared between remotipart and non-remotipart forms.
|
60
|
-
<%= remotipart_response do %>
|
61
|
-
// do stuff here
|
62
|
-
<% end %>
|
63
57
|
* If you need to determine if a particular request was made via a remotipart-enabled form...
|
64
58
|
* from your Rails controller or view:
|
65
59
|
|
@@ -93,14 +87,12 @@ sample_controller.rb
|
|
93
87
|
end
|
94
88
|
|
95
89
|
create.js.erb
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
alert('submitted via native jquery-ujs')
|
103
|
-
<% end %>
|
90
|
+
// Display a Javascript alert
|
91
|
+
alert('success!');
|
92
|
+
<% if remotipart_submitted? %>
|
93
|
+
alert('submitted via remotipart')
|
94
|
+
<% else %>
|
95
|
+
alert('submitted via native jquery-ujs')
|
104
96
|
<% end %>
|
105
97
|
|
106
98
|
== Note on Patches/Pull Requests
|
@@ -115,6 +107,36 @@ create.js.erb
|
|
115
107
|
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
116
108
|
* Send me a pull request. Bonus points for topic branches.
|
117
109
|
|
110
|
+
== Tests
|
111
|
+
|
112
|
+
Because of the nature of AJAX file uploads and certain browser restrictions, we could not simply create unit tests (using qunit or jasmine)
|
113
|
+
to test the file upload functionality of remotipart (since the browsers running those test suites won't allow us to set the target of a file
|
114
|
+
upload input using javascript). So, instead we created a demo Rails app using remotipart with all remotipart functionality tested using RSpec and Capybara.
|
115
|
+
|
116
|
+
* {Demo Rails App with Tests}[https://github.com/JangoSteve/Rails-jQuery-Demo/tree/remotipart]
|
117
|
+
* {Tests}[https://github.com/JangoSteve/Rails-jQuery-Demo/blob/remotipart/spec/integration/comments_spec.rb]
|
118
|
+
|
119
|
+
To run tests:
|
120
|
+
|
121
|
+
Clone the remotipart branch of the demo app
|
122
|
+
git clone -b remotipart git://github.com/JangoSteve/Rails-jQuery-Demo.git
|
123
|
+
|
124
|
+
Install the dependencies
|
125
|
+
bundle install
|
126
|
+
|
127
|
+
Run the tests
|
128
|
+
bundle exec rspec spec/
|
129
|
+
|
130
|
+
If you need to test your own changes to remotipart, just update the Gemfile with your own fork/branch of remotipart:
|
131
|
+
|
132
|
+
gem 'remotipart', :git => 'git://github.com/MY_FORK/remotipart.git', :branch => 'MY_BRANCH'
|
133
|
+
|
134
|
+
== Special Thanks
|
135
|
+
|
136
|
+
Thank you to Greg Leppert for writing the original version of this gem and providing inspiration for the gem in its current incarnation.
|
137
|
+
|
138
|
+
Thank you to {Adam Kerr}[https://github.com/ajrkerr] for helping move over to the simpler jQuery 1.6-compatible iframe-transport.js and for helping write the rack middleware, making remotipart even easier to use in Rails.
|
139
|
+
|
118
140
|
== Copyright
|
119
141
|
|
120
|
-
Copyright (c) 2011
|
142
|
+
Copyright (c) 2011 {Steve Schwartz}[https://github.com/JangoSteve], {Greg Leppert}[https://github.com/leppert]. See LICENSE for details.
|
@@ -4,12 +4,12 @@ module Remotipart
|
|
4
4
|
module Generators
|
5
5
|
class InstallGenerator < ::Rails::Generators::Base
|
6
6
|
|
7
|
-
desc "This generator installs
|
7
|
+
desc "This generator installs IframeTransport.js #{Remotipart::Rails::IFRAMETRANSPORT_VERSION} and Remotipart #{Remotipart::Rails::VERSION}"
|
8
8
|
source_root File.expand_path('../../../../../vendor/assets/javascripts', __FILE__)
|
9
9
|
|
10
|
-
def
|
11
|
-
say_status "copying", "
|
12
|
-
copy_file "jquery.
|
10
|
+
def install_iframe_transport
|
11
|
+
say_status "copying", "IframeTransport.js #{Remotipart::Rails::IFRAMETRANSPORT_VERSION}", :green
|
12
|
+
copy_file "jquery.iframe-transport.js", "public/javascripts/jquery.iframe-transport.js"
|
13
13
|
end
|
14
14
|
|
15
15
|
def install_remotipart
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Remotipart
|
2
|
+
|
3
|
+
# A middleware to look for our form parameters and
|
4
|
+
# encourage Rails to respond with the requested format
|
5
|
+
class Middleware
|
6
|
+
def initialize app
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call env
|
11
|
+
# For some reason, in Rails 3.0, `env['rack.request.form_hash']`
|
12
|
+
# isn't populated unless we manually initialize a new Rack::Request
|
13
|
+
# and call the `POST` method on it
|
14
|
+
if ::Rails.version < "3.1"
|
15
|
+
Rack::Request.new(env).POST
|
16
|
+
end
|
17
|
+
params = env['rack.request.form_hash']
|
18
|
+
|
19
|
+
# This was using an iframe transport, and is therefore an XHR
|
20
|
+
# This is required if we're going to override the http_accept
|
21
|
+
if params and params['X-Requested-With'] == 'IFrame'
|
22
|
+
env['HTTP_X_REQUESTED_WITH'] = 'xmlhttprequest'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Override the accepted format, because it isn't what we really want
|
26
|
+
if params and params['X-Http-Accept']
|
27
|
+
env['HTTP_ACCEPT'] = params['X-Http-Accept']
|
28
|
+
end
|
29
|
+
|
30
|
+
@app.call(env)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -10,6 +10,11 @@ module Remotipart
|
|
10
10
|
|
11
11
|
initializer "remotipart.controller_helper" do
|
12
12
|
ActionController::Base.send :include, RequestHelper
|
13
|
+
ActionController::Base.send :include, RenderOverrides
|
14
|
+
end
|
15
|
+
|
16
|
+
initializer "remotipart.include_middelware" do
|
17
|
+
config.app_middleware.insert_after ActionDispatch::ParamsParser, Middleware
|
13
18
|
end
|
14
19
|
end
|
15
20
|
|
@@ -5,7 +5,7 @@ module Remotipart
|
|
5
5
|
class Railtie < ::Rails::Railtie
|
6
6
|
config.before_configuration do
|
7
7
|
# Files to be added to :defaults
|
8
|
-
FILES = ['jquery.
|
8
|
+
FILES = ['jquery.iframe-transport', 'jquery.remotipart']
|
9
9
|
|
10
10
|
# Figure out where rails.js (aka jquery_ujs.js if install by jquery-rails gem) is
|
11
11
|
# in the :defaults array
|
@@ -29,6 +29,11 @@ module Remotipart
|
|
29
29
|
|
30
30
|
initializer "remotipart.controller_helper" do
|
31
31
|
ActionController::Base.send :include, RequestHelper
|
32
|
+
ActionController::Base.send :include, RenderOverrides
|
33
|
+
end
|
34
|
+
|
35
|
+
initializer "remotipart.include_middelware" do
|
36
|
+
config.app_middleware.insert_after ActionDispatch::ParamsParser, Middleware
|
32
37
|
end
|
33
38
|
end
|
34
39
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Remotipart
|
2
|
+
|
3
|
+
#Responder used to automagically wrap any non-xml replies in a text-area
|
4
|
+
# as expected by iframe-transport
|
5
|
+
module RenderOverrides
|
6
|
+
def render *args
|
7
|
+
super
|
8
|
+
if remotipart_submitted?
|
9
|
+
response.body = %{<textarea data-type=\"#{content_type}\">#{response.body}</textarea>}
|
10
|
+
response.content_type = Mime::HTML
|
11
|
+
end
|
12
|
+
response_body
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,13 +1,9 @@
|
|
1
1
|
module Remotipart
|
2
2
|
module ViewHelper
|
3
|
+
#No longer used
|
4
|
+
#Retrained to prevent issues while updating
|
3
5
|
def remotipart_response(options = {}, &block)
|
4
|
-
|
5
|
-
if remotipart_submitted?
|
6
|
-
response.content_type = Mime::HTML
|
7
|
-
text_area_tag('remotipart_response', String.new(content), options)
|
8
|
-
else
|
9
|
-
content
|
10
|
-
end
|
6
|
+
with_output_buffer(&block)
|
11
7
|
end
|
12
8
|
end
|
13
9
|
end
|
data/lib/remotipart.rb
CHANGED
data/remotipart.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{remotipart}
|
8
|
-
s.version = "0
|
8
|
+
s.version = "1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Greg Leppert", "Steve Schwartz"]
|
@@ -28,16 +28,18 @@ Gem::Specification.new do |s|
|
|
28
28
|
"VERSION_COMPATIBILITY.rdoc",
|
29
29
|
"lib/generators/remotipart/install/install_generator.rb",
|
30
30
|
"lib/remotipart.rb",
|
31
|
+
"lib/remotipart/middleware.rb",
|
31
32
|
"lib/remotipart/rails.rb",
|
32
33
|
"lib/remotipart/rails/engine.rb",
|
33
34
|
"lib/remotipart/rails/railtie.rb",
|
34
35
|
"lib/remotipart/rails/version.rb",
|
36
|
+
"lib/remotipart/render_overrides.rb",
|
35
37
|
"lib/remotipart/request_helper.rb",
|
36
38
|
"lib/remotipart/view_helper.rb",
|
37
39
|
"remotipart.gemspec",
|
38
40
|
"test/helper.rb",
|
39
41
|
"test/test_remotipart.rb",
|
40
|
-
"vendor/assets/javascripts/jquery.
|
42
|
+
"vendor/assets/javascripts/jquery.iframe-transport.js",
|
41
43
|
"vendor/assets/javascripts/jquery.remotipart.js"
|
42
44
|
]
|
43
45
|
s.homepage = %q{http://www.alfajango.com/blog/remotipart-rails-gem/}
|
@@ -0,0 +1,233 @@
|
|
1
|
+
// This [jQuery](http://jquery.com/) plugin implements an `<iframe>`
|
2
|
+
// [transport](http://api.jquery.com/extending-ajax/#Transports) 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` to
|
5
|
+
// a hidden `iframe` element containing a form that is submitted.
|
6
|
+
|
7
|
+
// The [source for the plugin](http://github.com/cmlenz/jquery-iframe-transport)
|
8
|
+
// is available on [Github](http://github.com/) and dual licensed under the MIT
|
9
|
+
// or GPL Version 2 licenses.
|
10
|
+
|
11
|
+
// ## Usage
|
12
|
+
|
13
|
+
// To use this plugin, you simply add a `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 a hidden `<iframe>` element containing a copy of
|
29
|
+
// the form the file field belongs to, will disable any form fields not
|
30
|
+
// explicitly included, submit that form, and process the response.
|
31
|
+
|
32
|
+
// If you want to include other form fields in the form submission, include them
|
33
|
+
// in the `data` option, and set the `processData` option to `false`:
|
34
|
+
|
35
|
+
// $("#myform").submit(function() {
|
36
|
+
// $.ajax(this.action, {
|
37
|
+
// data: $(":text", this).serializeArray(),
|
38
|
+
// files: $(":file", this),
|
39
|
+
// iframe: true,
|
40
|
+
// processData: false
|
41
|
+
// }).complete(function(data) {
|
42
|
+
// console.log(data);
|
43
|
+
// });
|
44
|
+
// });
|
45
|
+
|
46
|
+
// ### The Server Side
|
47
|
+
|
48
|
+
// If the response is not HTML or XML, you (unfortunately) need to apply some
|
49
|
+
// trickery on the server side. To send back a JSON payload, send back an HTML
|
50
|
+
// `<textarea>` element with a `data-type` attribute that contains the MIME
|
51
|
+
// type, and put the actual payload in the textarea:
|
52
|
+
|
53
|
+
// <textarea data-type="application/json">
|
54
|
+
// {"ok": true, "message": "Thanks so much"}
|
55
|
+
// </textarea>
|
56
|
+
|
57
|
+
// The iframe transport plugin will detect this and attempt to apply the same
|
58
|
+
// conversions that jQuery applies to regular responses. That means for the
|
59
|
+
// example above you should get a Javascript object as the `data` parameter of
|
60
|
+
// the `complete` callback, with the properties `ok: true` and
|
61
|
+
// `message: "Thanks so much"`.
|
62
|
+
|
63
|
+
// ### Compatibility
|
64
|
+
|
65
|
+
// This plugin has primarily been tested on Safari 5, Firefox 4, and Internet
|
66
|
+
// Explorer all the way back to version 6. While I haven't found any issues with
|
67
|
+
// it so far, I'm fairly sure it still doesn't work around all the quirks in all
|
68
|
+
// different browsers. But the code is still pretty simple overall, so you
|
69
|
+
// should be able to fix it and contribute a patch :)
|
70
|
+
|
71
|
+
// ## Annotated Source
|
72
|
+
|
73
|
+
(function($, undefined) {
|
74
|
+
|
75
|
+
// Register a prefilter that checks whether the `iframe` option is set, and
|
76
|
+
// switches to the iframe transport if it is `true`.
|
77
|
+
$.ajaxPrefilter(function(options, origOptions, jqXHR) {
|
78
|
+
if (options.iframe) {
|
79
|
+
return "iframe";
|
80
|
+
}
|
81
|
+
});
|
82
|
+
|
83
|
+
// Register an iframe transport, independent of requested data type. It will
|
84
|
+
// only activate when the "files" option has been set to a non-empty list of
|
85
|
+
// enabled file inputs.
|
86
|
+
$.ajaxTransport("iframe", function(options, origOptions, jqXHR) {
|
87
|
+
var form = null,
|
88
|
+
iframe = null,
|
89
|
+
origAction = null,
|
90
|
+
origTarget = null,
|
91
|
+
origEnctype = null,
|
92
|
+
addedFields = [],
|
93
|
+
disabledFields = [],
|
94
|
+
files = $(options.files).filter(":file:enabled");
|
95
|
+
|
96
|
+
// This function gets called after a successful submission or an abortion
|
97
|
+
// and should revert all changes made to the page to enable the
|
98
|
+
// submission via this transport.
|
99
|
+
function cleanUp() {
|
100
|
+
$(addedFields).each(function() {
|
101
|
+
this.remove();
|
102
|
+
});
|
103
|
+
$(disabledFields).each(function() {
|
104
|
+
this.disabled = false;
|
105
|
+
});
|
106
|
+
form.attr("action", origAction || "")
|
107
|
+
.attr("target", origTarget || "")
|
108
|
+
.attr("enctype", origEnctype || "");
|
109
|
+
iframe.attr("src", "javascript:false;").remove();
|
110
|
+
}
|
111
|
+
|
112
|
+
// Remove "iframe" from the data types list so that further processing is
|
113
|
+
// based on the content type returned by the server, without attempting an
|
114
|
+
// (unsupported) conversion from "iframe" to the actual type.
|
115
|
+
options.dataTypes.shift();
|
116
|
+
|
117
|
+
if (files.length) {
|
118
|
+
// Determine the form the file fields belong to, and make sure they all
|
119
|
+
// actually belong to the same form.
|
120
|
+
files.each(function() {
|
121
|
+
if (form !== null && this.form !== form) {
|
122
|
+
jQuery.error("All file fields must belong to the same form");
|
123
|
+
}
|
124
|
+
form = this.form;
|
125
|
+
});
|
126
|
+
form = $(form);
|
127
|
+
|
128
|
+
// Store the original form attributes that we'll be replacing temporarily.
|
129
|
+
origAction = form.attr("action");
|
130
|
+
origTarget = form.attr("target");
|
131
|
+
origEnctype = form.attr("enctype");
|
132
|
+
|
133
|
+
// We need to disable all other inputs in the form so that they don't get
|
134
|
+
// included in the submitted data unexpectedly.
|
135
|
+
form.find(":input:not(:submit)").each(function() {
|
136
|
+
if (!this.disabled && (this.type != "file" || files.index(this) < 0)) {
|
137
|
+
this.disabled = true;
|
138
|
+
disabledFields.push(this);
|
139
|
+
}
|
140
|
+
});
|
141
|
+
|
142
|
+
// If there is any additional data specified via the `data` option,
|
143
|
+
// we add it as hidden fields to the form. This (currently) requires
|
144
|
+
// the `processData` option to be set to false so that the data doesn't
|
145
|
+
// get serialized to a string.
|
146
|
+
if (typeof(options.data) === "string" && options.data.length > 0) {
|
147
|
+
jQuery.error("data must not be serialized");
|
148
|
+
}
|
149
|
+
$.each(options.data || {}, function(name, value) {
|
150
|
+
if ($.isPlainObject(value)) {
|
151
|
+
name = value.name;
|
152
|
+
value = value.value;
|
153
|
+
}
|
154
|
+
addedFields.push($("<input type='hidden'>").attr("name", name)
|
155
|
+
.attr("value", value).appendTo(form));
|
156
|
+
});
|
157
|
+
|
158
|
+
// Add a hidden `X-Requested-With` field with the value `IFrame` to the
|
159
|
+
// field, to help server-side code to determine that the upload happened
|
160
|
+
// through this transport.
|
161
|
+
addedFields.push($("<input type='hidden' name='X-Requested-With'>")
|
162
|
+
.attr("value", "IFrame").appendTo(form));
|
163
|
+
|
164
|
+
// Borrowed straight from the JQuery source
|
165
|
+
// Provides a way of specifying the accepted data type similar to HTTP_ACCEPTS
|
166
|
+
accepts = options.dataTypes[ 0 ] && options.accepts[ options.dataTypes[0] ] ?
|
167
|
+
options.accepts[ options.dataTypes[0] ] + ( options.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
|
168
|
+
options.accepts[ "*" ]
|
169
|
+
|
170
|
+
addedFields.push($("<input type='hidden' name='X-Http-Accept'>")
|
171
|
+
.attr("value", accepts).appendTo(form));
|
172
|
+
|
173
|
+
return {
|
174
|
+
|
175
|
+
// The `send` function is called by jQuery when the request should be
|
176
|
+
// sent.
|
177
|
+
send: function(headers, completeCallback) {
|
178
|
+
iframe = $("<iframe src='javascript:false;' name='iframe-" + $.now()
|
179
|
+
+ "' style='display:none'></iframe>");
|
180
|
+
|
181
|
+
// The first load event gets fired after the iframe has been injected
|
182
|
+
// into the DOM, and is used to prepare the actual submission.
|
183
|
+
iframe.bind("load", function() {
|
184
|
+
|
185
|
+
// The second load event gets fired when the response to the form
|
186
|
+
// submission is received. The implementation detects whether the
|
187
|
+
// actual payload is embedded in a `<textarea>` element, and
|
188
|
+
// prepares the required conversions to be made in that case.
|
189
|
+
iframe.unbind("load").bind("load", function() {
|
190
|
+
|
191
|
+
var doc = this.contentWindow ? this.contentWindow.document :
|
192
|
+
(this.contentDocument ? this.contentDocument : this.document),
|
193
|
+
root = doc.documentElement ? doc.documentElement : doc.body,
|
194
|
+
textarea = root.getElementsByTagName("textarea")[0],
|
195
|
+
type = textarea ? textarea.getAttribute("data-type") : null;
|
196
|
+
|
197
|
+
var status = 200,
|
198
|
+
statusText = "OK",
|
199
|
+
responses = { text: type ? textarea.value : root ? root.innerHTML : null },
|
200
|
+
headers = "Content-Type: " + (type || "text/html")
|
201
|
+
|
202
|
+
completeCallback(status, statusText, responses, headers);
|
203
|
+
|
204
|
+
setTimeout(cleanUp, 50);
|
205
|
+
});
|
206
|
+
|
207
|
+
// Now that the load handler has been set up, reconfigure and
|
208
|
+
// submit the form.
|
209
|
+
form.attr("action", options.url)
|
210
|
+
.attr("target", iframe.attr("name"))
|
211
|
+
.attr("enctype", "multipart/form-data")
|
212
|
+
.get(0).submit();
|
213
|
+
});
|
214
|
+
|
215
|
+
// After everything has been set up correctly, the iframe gets
|
216
|
+
// injected into the DOM so that the submission can be initiated.
|
217
|
+
iframe.insertAfter(form);
|
218
|
+
},
|
219
|
+
|
220
|
+
// The `abort` function is called by jQuery when the request should be
|
221
|
+
// aborted.
|
222
|
+
abort: function() {
|
223
|
+
if (iframe !== null) {
|
224
|
+
iframe.unbind("load").attr("src", "javascript:false;");
|
225
|
+
cleanUp();
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
};
|
230
|
+
}
|
231
|
+
});
|
232
|
+
|
233
|
+
})(jQuery);
|