remotipart 1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CONTRIBUTING.md +53 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +20 -0
- data/History.rdoc +45 -0
- data/README.rdoc +7 -7
- data/Rakefile +6 -11
- data/lib/remotipart/middleware.rb +12 -15
- data/lib/remotipart/rails.rb +1 -1
- data/lib/remotipart/rails/version.rb +2 -2
- data/lib/remotipart/render_overrides.rb +14 -6
- data/remotipart.gemspec +36 -41
- data/vendor/assets/javascripts/jquery.iframe-transport.js +99 -97
- data/vendor/assets/javascripts/jquery.remotipart.js +24 -5
- metadata +55 -60
- data/.gitignore +0 -21
- data/test/helper.rb +0 -10
- data/test/test_remotipart.rb +0 -7
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
## Note on Patches/Pull Requests
|
2
|
+
|
3
|
+
* Fork the project.
|
4
|
+
* Make your feature addition or bug fix.
|
5
|
+
* Add tests for it. This is important so I don't break it in a
|
6
|
+
future version unintentionally.
|
7
|
+
* Commit, do not mess with rakefile, version, or history.
|
8
|
+
(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)
|
9
|
+
* Send me a pull request. Bonus points for topic branches.
|
10
|
+
|
11
|
+
## Tests
|
12
|
+
|
13
|
+
Because of the nature of AJAX file uploads and certain browser restrictions, we could not simply create unit tests (using qunit or jasmine)
|
14
|
+
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
|
15
|
+
upload input using javascript). So, instead we created a demo Rails app using remotipart with all remotipart functionality tested using RSpec and Capybara.
|
16
|
+
|
17
|
+
* [Demo Rails App with
|
18
|
+
Tests](https://github.com/JangoSteve/Rails-jQuery-Demo/tree/remotipart)
|
19
|
+
* [Tests](https://github.com/JangoSteve/Rails-jQuery-Demo/blob/remotipart/spec/features/comments_spec.rb)
|
20
|
+
|
21
|
+
To run tests:
|
22
|
+
|
23
|
+
Clone the remotipart branch of the demo app
|
24
|
+
|
25
|
+
```
|
26
|
+
git clone -b remotipart git://github.com/JangoSteve/Rails-jQuery-Demo.git
|
27
|
+
```
|
28
|
+
|
29
|
+
Install the dependencies
|
30
|
+
|
31
|
+
```
|
32
|
+
bundle install
|
33
|
+
```
|
34
|
+
|
35
|
+
Run the tests
|
36
|
+
|
37
|
+
```
|
38
|
+
bundle exec rspec spec/
|
39
|
+
```
|
40
|
+
|
41
|
+
If you need to test your own changes to remotipart, just update the Gemfile with your own fork/branch of remotipart:
|
42
|
+
|
43
|
+
```
|
44
|
+
gem 'remotipart', :git => 'git://github.com/MY_FORK/remotipart.git', :branch => 'MY_BRANCH'
|
45
|
+
```
|
46
|
+
|
47
|
+
To save time, you can also just bundle remotipart from your current
|
48
|
+
local machine / filesystem without having to commit your changes
|
49
|
+
or push them remotely:
|
50
|
+
|
51
|
+
```
|
52
|
+
gem 'remotipart', :path => '../remotipart'
|
53
|
+
```
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
git (1.2.5)
|
5
|
+
jeweler (1.8.4)
|
6
|
+
bundler (~> 1.0)
|
7
|
+
git (>= 1.2.5)
|
8
|
+
rake
|
9
|
+
rdoc
|
10
|
+
json (1.7.6)
|
11
|
+
rake (10.0.3)
|
12
|
+
rdoc (3.12)
|
13
|
+
json (~> 1.4)
|
14
|
+
|
15
|
+
PLATFORMS
|
16
|
+
ruby
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
jeweler
|
20
|
+
rake
|
data/History.rdoc
CHANGED
@@ -1,5 +1,50 @@
|
|
1
1
|
= History
|
2
2
|
|
3
|
+
=== 1.2.1 / 2013-07-07
|
4
|
+
|
5
|
+
* Added automatic authenticity_token detection and appending to iframe submission.
|
6
|
+
|
7
|
+
=== 1.2.0 / 2013-07-06
|
8
|
+
|
9
|
+
* Removed support for older jquery-ujs and jquery < 1.7.
|
10
|
+
* Fixed json (and other type) parsing issues, only html_escape HTML responses.
|
11
|
+
|
12
|
+
=== 1.1.1 / 2013-07-05
|
13
|
+
|
14
|
+
* Fixed issue with GET params not being available in middleware.
|
15
|
+
* Fixed issue with clicked submit button not being submitted via remotipart ajax.
|
16
|
+
* Fixed issue with HTML not being escaped correctly.
|
17
|
+
* Fixed issue with iframe-transport on jQuery 1.10.x.
|
18
|
+
* Fixed compatibility issue with Rails 4.
|
19
|
+
|
20
|
+
=== 1.1.0 / 2013-07-04
|
21
|
+
|
22
|
+
* Updated to latest iframe-transport.
|
23
|
+
* Added status-text to js response.
|
24
|
+
|
25
|
+
=== 1.0.5 / 2013-02-09
|
26
|
+
|
27
|
+
* Fixed gem dependency info.
|
28
|
+
|
29
|
+
=== 1.0.4 / 2013-02-09
|
30
|
+
|
31
|
+
* Fixed render override compatibility with other gems that override render (e.g. wicked_pdf)
|
32
|
+
|
33
|
+
=== 1.0.3 / 2013-02-08
|
34
|
+
|
35
|
+
* Fixed for jquery-rails v2.2.x (i.e. jQuery v1.9.x)
|
36
|
+
|
37
|
+
=== 1.0.2 / 2012-02-03
|
38
|
+
|
39
|
+
* Minor Enhancements
|
40
|
+
* Fixed rendering when JS response contains `textarea` tag
|
41
|
+
|
42
|
+
=== 1.0.1 / 2011-11-27
|
43
|
+
|
44
|
+
* Minor Enhancements
|
45
|
+
* Added support for non-post methods from Rails's `_method` hidden input.
|
46
|
+
* Fixed IE form submit-bubbling support for jquery 1.7
|
47
|
+
|
3
48
|
=== 1.0 / 2011-08-26
|
4
49
|
|
5
50
|
* New Features
|
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
= Remotipart
|
1
|
+
= Remotipart: Rails jQuery File Upload
|
2
2
|
|
3
|
-
Remotipart is a Ruby on Rails gem enabling AJAX file uploads with jQuery in Rails 3
|
3
|
+
Remotipart is a Ruby on Rails gem enabling AJAX file uploads with jQuery in Rails 3 and Rails 4 remote forms.
|
4
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/]
|
@@ -8,12 +8,12 @@ This gem augments the native Rails jQuery remote form functionality enabling asy
|
|
8
8
|
|
9
9
|
== Dependencies
|
10
10
|
|
11
|
-
* {Rails 3}[http://github.com/rails/rails]
|
12
|
-
* {The jquery-rails gem}[http://rubygems.org/gems/jquery-rails], which
|
11
|
+
* {Rails 3 or Rails 4}[http://github.com/rails/rails]
|
12
|
+
* {The jquery-rails gem}[http://rubygems.org/gems/jquery-rails] (included in Rails 3 and Rails 4 by default), which installs {jQuery}[http://jquery.com] and the {Rails jQuery driver (jquery-ujs)}[https://github.com/rails/jquery-ujs]
|
13
13
|
|
14
14
|
== Installation
|
15
15
|
|
16
|
-
<b>Your app should be using jquery-rails gem
|
16
|
+
<b>Your app should be using jquery-rails gem v2.3.0 or above.</b>
|
17
17
|
|
18
18
|
If you're using an old version of the jquery-rails gem,
|
19
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].
|
@@ -23,7 +23,7 @@ make sure you have a supported jquery-ujs (rails.js or jquery_ujs.js) version fr
|
|
23
23
|
|
24
24
|
* Add this line to your GEMFILE (use the appropriate version from the compatibilty chart if needed)
|
25
25
|
|
26
|
-
gem 'remotipart', '~> 1.
|
26
|
+
gem 'remotipart', '~> 1.2'
|
27
27
|
|
28
28
|
* And run
|
29
29
|
|
@@ -139,4 +139,4 @@ Thank you to {Adam Kerr}[https://github.com/ajrkerr] for helping move over to th
|
|
139
139
|
|
140
140
|
== Copyright
|
141
141
|
|
142
|
-
Copyright (c)
|
142
|
+
Copyright (c) 2013 {Steve Schwartz}[https://github.com/JangoSteve], {Greg Leppert}[https://github.com/leppert]. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -6,18 +6,17 @@ begin
|
|
6
6
|
require 'jeweler'
|
7
7
|
Jeweler::Tasks.new do |gem|
|
8
8
|
gem.name = "remotipart"
|
9
|
-
gem.summary = %Q{Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with
|
10
|
-
gem.description = %Q{Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with
|
9
|
+
gem.summary = %Q{Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with jquery-rails.}
|
10
|
+
gem.description = %Q{Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with jquery-rails.
|
11
11
|
This gem augments the native Rails 3 jQuery-UJS remote form function enabling asynchronous file uploads with little to no modification to your application.
|
12
12
|
}
|
13
13
|
gem.email = %w{greg@formasfunction.com steve@alfajango.com}
|
14
|
-
gem.homepage = "http://
|
14
|
+
gem.homepage = "http://opensource.alfajango.com/remotipart/"
|
15
15
|
gem.authors = ["Greg Leppert", "Steve Schwartz"]
|
16
|
-
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
17
16
|
gem.version = Remotipart::Rails::VERSION
|
18
17
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
18
|
end
|
20
|
-
Jeweler::
|
19
|
+
Jeweler::RubygemsDotOrgTasks.new
|
21
20
|
rescue LoadError
|
22
21
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
23
22
|
end
|
@@ -42,12 +41,8 @@ rescue LoadError
|
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
45
|
-
task
|
46
|
-
|
47
|
-
task :default => :test
|
48
|
-
|
49
|
-
require 'rake/rdoctask'
|
50
|
-
require 'lib/remotipart/rails/version'
|
44
|
+
require 'rdoc/task'
|
45
|
+
require File.expand_path('../lib/remotipart/rails/version', __FILE__)
|
51
46
|
Rake::RDocTask.new do |rdoc|
|
52
47
|
version = Remotipart::Rails::VERSION
|
53
48
|
|
@@ -8,23 +8,20 @@ module Remotipart
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def call env
|
11
|
-
#
|
12
|
-
|
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']
|
11
|
+
# Get request params
|
12
|
+
params = Rack::Request.new(env).params
|
18
13
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
14
|
+
if params
|
15
|
+
# This was using an iframe transport, and is therefore an XHR
|
16
|
+
# This is required if we're going to override the http_accept
|
17
|
+
if params['X-Requested-With'] == 'IFrame'
|
18
|
+
env['HTTP_X_REQUESTED_WITH'] = 'xmlhttprequest'
|
19
|
+
end
|
24
20
|
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
# Override the accepted format, because it isn't what we really want
|
22
|
+
if params['X-Http-Accept']
|
23
|
+
env['HTTP_ACCEPT'] = params['X-Http-Accept']
|
24
|
+
end
|
28
25
|
end
|
29
26
|
|
30
27
|
@app.call(env)
|
data/lib/remotipart/rails.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
module Remotipart
|
2
|
-
|
3
|
-
#
|
4
|
-
# as expected by iframe-transport
|
2
|
+
# Responder used to automagically wrap any non-xml replies in a text-area
|
3
|
+
# as expected by iframe-transport.
|
5
4
|
module RenderOverrides
|
6
|
-
|
7
|
-
|
5
|
+
include ERB::Util
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.class_eval do
|
9
|
+
alias_method_chain :render, :remotipart
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def render_with_remotipart *args
|
14
|
+
render_without_remotipart *args
|
8
15
|
if remotipart_submitted?
|
9
|
-
response.
|
16
|
+
textarea_body = response.content_type == 'text/html' ? html_escape(response.body) : response.body
|
17
|
+
response.body = %{<textarea data-type=\"#{response.content_type}\" data-status=\"#{response.response_code}\" data-statusText=\"#{response.message}\">#{textarea_body}</textarea>}
|
10
18
|
response.content_type = Mime::HTML
|
11
19
|
end
|
12
20
|
response_body
|
data/remotipart.gemspec
CHANGED
@@ -1,68 +1,63 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "1.
|
7
|
+
s.name = "remotipart"
|
8
|
+
s.version = "1.2.1"
|
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"]
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
This gem augments the native Rails 3 jQuery-UJS remote form function enabling asynchronous file uploads with little to no modification to your application.
|
15
|
-
}
|
12
|
+
s.date = "2013-07-08"
|
13
|
+
s.description = "Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with jquery-rails.\n This gem augments the native Rails 3 jQuery-UJS remote form function enabling asynchronous file uploads with little to no modification to your application.\n "
|
16
14
|
s.email = ["greg@formasfunction.com", "steve@alfajango.com"]
|
17
15
|
s.extra_rdoc_files = [
|
18
16
|
"LICENSE",
|
19
|
-
|
17
|
+
"README.rdoc"
|
20
18
|
]
|
21
19
|
s.files = [
|
22
20
|
".document",
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
21
|
+
"CONTRIBUTING.md",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
24
|
+
"History.rdoc",
|
25
|
+
"LICENSE",
|
26
|
+
"README.rdoc",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION_COMPATIBILITY.rdoc",
|
29
|
+
"lib/generators/remotipart/install/install_generator.rb",
|
30
|
+
"lib/remotipart.rb",
|
31
|
+
"lib/remotipart/middleware.rb",
|
32
|
+
"lib/remotipart/rails.rb",
|
33
|
+
"lib/remotipart/rails/engine.rb",
|
34
|
+
"lib/remotipart/rails/railtie.rb",
|
35
|
+
"lib/remotipart/rails/version.rb",
|
36
|
+
"lib/remotipart/render_overrides.rb",
|
37
|
+
"lib/remotipart/request_helper.rb",
|
38
|
+
"lib/remotipart/view_helper.rb",
|
39
|
+
"remotipart.gemspec",
|
40
|
+
"vendor/assets/javascripts/jquery.iframe-transport.js",
|
41
|
+
"vendor/assets/javascripts/jquery.remotipart.js"
|
44
42
|
]
|
45
|
-
s.homepage =
|
46
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
43
|
+
s.homepage = "http://opensource.alfajango.com/remotipart/"
|
47
44
|
s.require_paths = ["lib"]
|
48
|
-
s.rubygems_version =
|
49
|
-
s.summary =
|
50
|
-
s.test_files = [
|
51
|
-
"test/helper.rb",
|
52
|
-
"test/test_remotipart.rb"
|
53
|
-
]
|
45
|
+
s.rubygems_version = "1.8.15"
|
46
|
+
s.summary = "Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with jquery-rails."
|
54
47
|
|
55
48
|
if s.respond_to? :specification_version then
|
56
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
57
49
|
s.specification_version = 3
|
58
50
|
|
59
51
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
60
|
-
s.add_development_dependency(%q<
|
52
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
53
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
61
54
|
else
|
62
|
-
s.add_dependency(%q<
|
55
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
56
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
63
57
|
end
|
64
58
|
else
|
65
|
-
s.add_dependency(%q<
|
59
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
60
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
66
61
|
end
|
67
62
|
end
|
68
63
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
// This [jQuery](http://jquery.com/) plugin implements an `<iframe>`
|
2
2
|
// [transport](http://api.jquery.com/extending-ajax/#Transports) so that
|
3
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
|
-
// a hidden `iframe` element containing a form that is submitted.
|
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
6
|
|
7
7
|
// The [source for the plugin](http://github.com/cmlenz/jquery-iframe-transport)
|
8
8
|
// is available on [Github](http://github.com/) and dual licensed under the MIT
|
@@ -10,7 +10,7 @@
|
|
10
10
|
|
11
11
|
// ## Usage
|
12
12
|
|
13
|
-
// To use this plugin, you simply add
|
13
|
+
// To use this plugin, you simply add an `iframe` option with the value `true`
|
14
14
|
// to the Ajax settings an `$.ajax()` call, and specify the file fields to
|
15
15
|
// include in the submssion using the `files` option, which can be a selector,
|
16
16
|
// jQuery object, or a list of DOM elements containing one or more
|
@@ -25,12 +25,11 @@
|
|
25
25
|
// });
|
26
26
|
// });
|
27
27
|
|
28
|
-
// The plugin will construct
|
29
|
-
//
|
30
|
-
// explicitly included, submit that form, and process the response.
|
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.
|
31
30
|
|
32
|
-
// If you want to include other form fields in the form submission, include
|
33
|
-
// in the `data` option, and set the `processData` option to `false`:
|
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`:
|
34
33
|
|
35
34
|
// $("#myform").submit(function() {
|
36
35
|
// $.ajax(this.action, {
|
@@ -43,123 +42,115 @@
|
|
43
42
|
// });
|
44
43
|
// });
|
45
44
|
|
46
|
-
// ###
|
45
|
+
// ### Response Data Types
|
47
46
|
|
48
|
-
//
|
49
|
-
//
|
50
|
-
//
|
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
|
51
54
|
// type, and put the actual payload in the textarea:
|
52
55
|
|
53
56
|
// <textarea data-type="application/json">
|
54
57
|
// {"ok": true, "message": "Thanks so much"}
|
55
58
|
// </textarea>
|
56
59
|
|
57
|
-
// The iframe transport plugin will detect this and
|
58
|
-
//
|
59
|
-
//
|
60
|
-
//
|
61
|
-
// `
|
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 determine communicate problems using
|
74
|
+
// the content of the response payload. For example, consider using a JSON
|
75
|
+
// response such as 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>
|
62
80
|
|
63
81
|
// ### Compatibility
|
64
82
|
|
65
|
-
// This plugin has primarily been tested on Safari 5, Firefox 4
|
66
|
-
// Explorer all the way back to version 6. While I
|
67
|
-
// it so far, I'm fairly sure it still doesn't
|
68
|
-
// different browsers. But the code is still
|
69
|
-
// should be able to fix it and contribute a
|
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 :)
|
70
89
|
|
71
90
|
// ## Annotated Source
|
72
91
|
|
73
92
|
(function($, undefined) {
|
93
|
+
"use strict";
|
74
94
|
|
75
95
|
// Register a prefilter that checks whether the `iframe` option is set, and
|
76
|
-
// switches to the iframe
|
96
|
+
// switches to the "iframe" data type if it is `true`.
|
77
97
|
$.ajaxPrefilter(function(options, origOptions, jqXHR) {
|
78
98
|
if (options.iframe) {
|
79
99
|
return "iframe";
|
80
100
|
}
|
81
101
|
});
|
82
102
|
|
83
|
-
// Register
|
84
|
-
//
|
85
|
-
//
|
103
|
+
// Register a transport for the "iframe" data type. It will only activate
|
104
|
+
// when the "files" option has been set to a non-empty list of enabled file
|
105
|
+
// inputs.
|
86
106
|
$.ajaxTransport("iframe", function(options, origOptions, jqXHR) {
|
87
107
|
var form = null,
|
88
108
|
iframe = null,
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
disabledFields = [],
|
94
|
-
files = $(options.files).filter(":file:enabled");
|
109
|
+
name = "iframe-" + $.now(),
|
110
|
+
files = $(options.files).filter(":file:enabled"),
|
111
|
+
markers = null,
|
112
|
+
accepts;
|
95
113
|
|
96
114
|
// This function gets called after a successful submission or an abortion
|
97
115
|
// and should revert all changes made to the page to enable the
|
98
116
|
// submission via this transport.
|
99
117
|
function cleanUp() {
|
100
|
-
|
101
|
-
|
102
|
-
});
|
103
|
-
|
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();
|
118
|
+
markers.prop('disabled', false);
|
119
|
+
form.remove();
|
120
|
+
iframe.bind("load", function() { iframe.remove(); });
|
121
|
+
iframe.attr("src", "javascript:false;");
|
110
122
|
}
|
111
123
|
|
112
124
|
// Remove "iframe" from the data types list so that further processing is
|
113
125
|
// based on the content type returned by the server, without attempting an
|
114
126
|
// (unsupported) conversion from "iframe" to the actual type.
|
115
127
|
options.dataTypes.shift();
|
116
|
-
|
128
|
+
|
117
129
|
if (files.length) {
|
118
|
-
|
119
|
-
|
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
|
-
});
|
130
|
+
form = $("<form enctype='multipart/form-data' method='post'></form>").
|
131
|
+
hide().attr({action: options.url, target: name});
|
141
132
|
|
142
133
|
// If there is any additional data specified via the `data` option,
|
143
134
|
// we add it as hidden fields to the form. This (currently) requires
|
144
135
|
// the `processData` option to be set to false so that the data doesn't
|
145
136
|
// get serialized to a string.
|
146
137
|
if (typeof(options.data) === "string" && options.data.length > 0) {
|
147
|
-
|
138
|
+
$.error("data must not be serialized");
|
148
139
|
}
|
149
140
|
$.each(options.data || {}, function(name, value) {
|
150
141
|
if ($.isPlainObject(value)) {
|
151
142
|
name = value.name;
|
152
143
|
value = value.value;
|
153
144
|
}
|
154
|
-
|
155
|
-
|
145
|
+
$("<input type='hidden' />").attr({name: name, value: value}).
|
146
|
+
appendTo(form);
|
156
147
|
});
|
157
148
|
|
158
149
|
// Add a hidden `X-Requested-With` field with the value `IFrame` to the
|
159
150
|
// field, to help server-side code to determine that the upload happened
|
160
151
|
// through this transport.
|
161
|
-
|
162
|
-
|
152
|
+
$("<input type='hidden' value='IFrame' name='X-Requested-With' />").
|
153
|
+
appendTo(form);
|
163
154
|
|
164
155
|
// Borrowed straight from the JQuery source
|
165
156
|
// Provides a way of specifying the accepted data type similar to HTTP_ACCEPTS
|
@@ -167,17 +158,26 @@
|
|
167
158
|
options.accepts[ options.dataTypes[0] ] + ( options.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
|
168
159
|
options.accepts[ "*" ]
|
169
160
|
|
170
|
-
|
171
|
-
.attr("value", accepts).appendTo(form)
|
161
|
+
$("<input type='hidden' name='X-Http-Accept'>")
|
162
|
+
.attr("value", accepts).appendTo(form);
|
163
|
+
|
164
|
+
// Move the file fields into the hidden form, but first remember their
|
165
|
+
// original locations in the document by replacing them with disabled
|
166
|
+
// clones. This should also avoid introducing unwanted changes to the
|
167
|
+
// page layout during submission.
|
168
|
+
markers = files.after(function(idx) {
|
169
|
+
return $(this).clone().prop("disabled", true);
|
170
|
+
}).next();
|
171
|
+
files.appendTo(form);
|
172
172
|
|
173
173
|
return {
|
174
174
|
|
175
175
|
// The `send` function is called by jQuery when the request should be
|
176
176
|
// sent.
|
177
177
|
send: function(headers, completeCallback) {
|
178
|
-
iframe = $("<iframe src='javascript:false;' name='
|
179
|
-
+ "' style='display:none'></iframe>");
|
180
|
-
|
178
|
+
iframe = $("<iframe src='javascript:false;' name='" + name +
|
179
|
+
"' id='" + name + "' style='display:none'></iframe>");
|
180
|
+
|
181
181
|
// The first load event gets fired after the iframe has been injected
|
182
182
|
// into the DOM, and is used to prepare the actual submission.
|
183
183
|
iframe.bind("load", function() {
|
@@ -187,34 +187,36 @@
|
|
187
187
|
// actual payload is embedded in a `<textarea>` element, and
|
188
188
|
// prepares the required conversions to be made in that case.
|
189
189
|
iframe.unbind("load").bind("load", function() {
|
190
|
-
|
191
190
|
var doc = this.contentWindow ? this.contentWindow.document :
|
192
191
|
(this.contentDocument ? this.contentDocument : this.document),
|
193
192
|
root = doc.documentElement ? doc.documentElement : doc.body,
|
194
193
|
textarea = root.getElementsByTagName("textarea")[0],
|
195
|
-
type = textarea
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
194
|
+
type = textarea && textarea.getAttribute("data-type") || null,
|
195
|
+
status = textarea && textarea.getAttribute("data-status") || 200,
|
196
|
+
statusText = textarea && textarea.getAttribute("data-statusText") || "OK",
|
197
|
+
content = {
|
198
|
+
html: root.innerHTML,
|
199
|
+
text: type ?
|
200
|
+
textarea.value :
|
201
|
+
root ? (root.textContent || root.innerText) : null
|
202
|
+
};
|
203
|
+
cleanUp();
|
204
|
+
if (!jqXHR.responseText) {
|
205
|
+
jqXHR.responseText = content.text;
|
206
|
+
}
|
207
|
+
completeCallback(status, statusText, content, type ?
|
208
|
+
("Content-Type: " + type) :
|
209
|
+
null);
|
205
210
|
});
|
206
|
-
|
207
|
-
// Now that the load handler has been set up,
|
208
|
-
|
209
|
-
form.attr("action", options.url)
|
210
|
-
.attr("target", iframe.attr("name"))
|
211
|
-
.attr("enctype", "multipart/form-data")
|
212
|
-
.get(0).submit();
|
211
|
+
|
212
|
+
// Now that the load handler has been set up, submit the form.
|
213
|
+
form[0].submit();
|
213
214
|
});
|
214
215
|
|
215
|
-
// After everything has been set up correctly, the iframe
|
216
|
-
// injected into the DOM so that the submission can be
|
217
|
-
|
216
|
+
// After everything has been set up correctly, the form and iframe
|
217
|
+
// get injected into the DOM so that the submission can be
|
218
|
+
// initiated.
|
219
|
+
$("body").append(form, iframe);
|
218
220
|
},
|
219
221
|
|
220
222
|
// The `abort` function is called by jQuery when the request should be
|
@@ -8,6 +8,12 @@
|
|
8
8
|
$.remotipart = remotipart = {
|
9
9
|
|
10
10
|
setup: function(form) {
|
11
|
+
// Preserve form.data('ujs:submit-button') before it gets nulled by $.ajax.handleRemote
|
12
|
+
var button = form.data('ujs:submit-button'),
|
13
|
+
csrfParam = $('meta[name="csrf-param"]').attr('content'),
|
14
|
+
csrfToken = $('meta[name="csrf-token"]').attr('content'),
|
15
|
+
csrfInput = form.find('input[name="' + csrfParam + '"]').length;
|
16
|
+
|
11
17
|
form
|
12
18
|
// Allow setup part of $.rails.handleRemote to setup remote settings before canceling default remote handler
|
13
19
|
// This is required in order to change the remote settings using the form details
|
@@ -20,16 +26,33 @@
|
|
20
26
|
settings.iframe = true;
|
21
27
|
settings.files = $($.rails.fileInputSelector, form);
|
22
28
|
settings.data = form.serializeArray();
|
29
|
+
|
30
|
+
// Insert the name/value of the clicked submit button, if any
|
31
|
+
if (button)
|
32
|
+
settings.data.push(button);
|
33
|
+
|
34
|
+
// jQuery 1.9 serializeArray() contains input:file entries
|
35
|
+
// so exclude them from settings.data, otherwise files will not be sent
|
36
|
+
settings.files.each(function(i, file){
|
37
|
+
for (var j = settings.data.length - 1; j >= 0; j--)
|
38
|
+
if (settings.data[j].name == file.name)
|
39
|
+
settings.data.splice(j, 1);
|
40
|
+
})
|
41
|
+
|
23
42
|
settings.processData = false;
|
24
43
|
|
25
44
|
// Modify some settings to integrate JS request with rails helpers and middleware
|
26
45
|
if (settings.dataType === undefined) { settings.dataType = 'script *'; }
|
27
46
|
settings.data.push({name: 'remotipart_submitted', value: true});
|
47
|
+
if (csrfToken && csrfParam && !csrfInput) {
|
48
|
+
settings.data.push({name: csrfParam, value: csrfToken});
|
49
|
+
}
|
28
50
|
|
29
51
|
// Allow remotipartSubmit to be cancelled if needed
|
30
52
|
if ($.rails.fire(form, 'ajax:remotipartSubmit', [xhr, settings])) {
|
31
53
|
// Second verse, same as the first
|
32
54
|
$.rails.ajax(settings);
|
55
|
+
setTimeout(function(){ $.rails.disableFormElements(form); }, 20);
|
33
56
|
}
|
34
57
|
|
35
58
|
//Run cleanup
|
@@ -51,15 +74,11 @@
|
|
51
74
|
}
|
52
75
|
};
|
53
76
|
|
54
|
-
$(
|
77
|
+
$(document).on('ajax:aborted:file', 'form', function(){
|
55
78
|
var form = $(this);
|
56
79
|
|
57
80
|
remotipart.setup(form);
|
58
81
|
|
59
|
-
// If browser does not support submit bubbling, then this live-binding will be called before direct
|
60
|
-
// bindings. Therefore, we should directly call any direct bindings before remotely submitting form.
|
61
|
-
if (!$.support.submitBubbles && $.rails.callFormSubmitBindings(form) === false) return $.rails.stopEverything(e);
|
62
|
-
|
63
82
|
// Manually call jquery-ujs remote call so that it can setup form and settings as usual,
|
64
83
|
// and trigger the `ajax:beforeSend` callback to which remotipart binds functionality.
|
65
84
|
$.rails.handleRemote(form);
|
metadata
CHANGED
@@ -1,51 +1,56 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: remotipart
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
version: "1.0"
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.1
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Greg Leppert
|
13
9
|
- Steve Schwartz
|
14
10
|
autorequire:
|
15
11
|
bindir: bin
|
16
12
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
date: 2013-07-08 00:00:00.000000000Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
requirement: &70170920954340 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
23
24
|
prerelease: false
|
24
|
-
|
25
|
+
version_requirements: *70170920954340
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: jeweler
|
28
|
+
requirement: &70170920953080 !ruby/object:Gem::Requirement
|
25
29
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
33
34
|
type: :development
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70170920953080
|
37
|
+
description: ! "Remotipart is a Ruby on Rails gem enabling remote multipart forms
|
38
|
+
(AJAX style file uploads) with jquery-rails.\n This gem augments the native Rails
|
39
|
+
3 jQuery-UJS remote form function enabling asynchronous file uploads with little
|
40
|
+
to no modification to your application.\n "
|
41
|
+
email:
|
37
42
|
- greg@formasfunction.com
|
38
43
|
- steve@alfajango.com
|
39
44
|
executables: []
|
40
|
-
|
41
45
|
extensions: []
|
42
|
-
|
43
|
-
extra_rdoc_files:
|
46
|
+
extra_rdoc_files:
|
44
47
|
- LICENSE
|
45
48
|
- README.rdoc
|
46
|
-
files:
|
49
|
+
files:
|
47
50
|
- .document
|
48
|
-
- .
|
51
|
+
- CONTRIBUTING.md
|
52
|
+
- Gemfile
|
53
|
+
- Gemfile.lock
|
49
54
|
- History.rdoc
|
50
55
|
- LICENSE
|
51
56
|
- README.rdoc
|
@@ -62,44 +67,34 @@ files:
|
|
62
67
|
- lib/remotipart/request_helper.rb
|
63
68
|
- lib/remotipart/view_helper.rb
|
64
69
|
- remotipart.gemspec
|
65
|
-
- test/helper.rb
|
66
|
-
- test/test_remotipart.rb
|
67
70
|
- vendor/assets/javascripts/jquery.iframe-transport.js
|
68
71
|
- vendor/assets/javascripts/jquery.remotipart.js
|
69
|
-
|
70
|
-
homepage: http://www.alfajango.com/blog/remotipart-rails-gem/
|
72
|
+
homepage: http://opensource.alfajango.com/remotipart/
|
71
73
|
licenses: []
|
72
|
-
|
73
74
|
post_install_message:
|
74
|
-
rdoc_options:
|
75
|
-
|
76
|
-
require_paths:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
77
|
- lib
|
78
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
79
|
none: false
|
80
|
-
requirements:
|
81
|
-
- -
|
82
|
-
- !ruby/object:Gem::Version
|
83
|
-
|
84
|
-
segments:
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
segments:
|
85
85
|
- 0
|
86
|
-
|
87
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
hash: -3061483236240277448
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
88
|
none: false
|
89
|
-
requirements:
|
90
|
-
- -
|
91
|
-
- !ruby/object:Gem::Version
|
92
|
-
|
93
|
-
segments:
|
94
|
-
- 0
|
95
|
-
version: "0"
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
96
93
|
requirements: []
|
97
|
-
|
98
94
|
rubyforge_project:
|
99
|
-
rubygems_version: 1.
|
95
|
+
rubygems_version: 1.8.15
|
100
96
|
signing_key:
|
101
97
|
specification_version: 3
|
102
|
-
summary: Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style
|
103
|
-
|
104
|
-
|
105
|
-
- test/test_remotipart.rb
|
98
|
+
summary: Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style
|
99
|
+
file uploads) with jquery-rails.
|
100
|
+
test_files: []
|
data/.gitignore
DELETED
data/test/helper.rb
DELETED