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 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
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development do
4
+ gem 'rake'
5
+ gem 'jeweler'
6
+ # This conflicts with jeweler gemspec generation,
7
+ # causes dependencies to be added to gemspec recursively
8
+ #gemspec
9
+ end
10
+
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.0 and Rails 3.1 remote forms.
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 really just installs {jQuery}[http://jquery.com] and the {Rails jQuery driver (jquery-ujs)}[https://github.com/rails/jquery-ujs]
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 v1.0.12 or above.</b>
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.0'
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) 2011 {Steve Schwartz}[https://github.com/JangoSteve], {Greg Leppert}[https://github.com/leppert]. See LICENSE for details.
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 jQuery.}
10
- gem.description = %Q{Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with jQuery.
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://www.alfajango.com/blog/remotipart-rails-gem/"
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::GemcutterTasks.new
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 :test => :check_dependencies
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
- # 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']
11
+ # Get request params
12
+ params = Rack::Request.new(env).params
18
13
 
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
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
- # 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']
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)
@@ -1,6 +1,6 @@
1
1
  module Remotipart
2
2
  module Rails
3
- if ::Rails.version < "3.1"
3
+ if ::Rails.version.to_s < "3.1"
4
4
  require 'remotipart/rails/railtie'
5
5
  else
6
6
  require 'remotipart/rails/engine'
@@ -1,6 +1,6 @@
1
1
  module Remotipart
2
2
  module Rails
3
- VERSION = "1.0"
4
- IFRAMETRANSPORT_VERSION = "07.05.2011"
3
+ VERSION = "1.2.1"
4
+ IFRAMETRANSPORT_VERSION = "02.06.2013"
5
5
  end
6
6
  end
@@ -1,12 +1,20 @@
1
1
  module Remotipart
2
-
3
- #Responder used to automagically wrap any non-xml replies in a text-area
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
- def render *args
7
- super
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.body = %{<textarea data-type=\"#{content_type}\">#{response.body}</textarea>}
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 the gemspec command
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 = %q{remotipart}
8
- s.version = "1.0"
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 = %q{2011-08-26}
13
- s.description = %q{Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with jQuery.
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
- "README.rdoc"
17
+ "README.rdoc"
20
18
  ]
21
19
  s.files = [
22
20
  ".document",
23
- ".gitignore",
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
- "test/helper.rb",
41
- "test/test_remotipart.rb",
42
- "vendor/assets/javascripts/jquery.iframe-transport.js",
43
- "vendor/assets/javascripts/jquery.remotipart.js"
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 = %q{http://www.alfajango.com/blog/remotipart-rails-gem/}
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 = %q{1.3.7}
49
- s.summary = %q{Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with jQuery.}
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<thoughtbot-shoulda>, [">= 0"])
52
+ s.add_development_dependency(%q<rake>, [">= 0"])
53
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
61
54
  else
62
- s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
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<thoughtbot-shoulda>, [">= 0"])
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` to
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 a `iframe` option with the value `true`
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 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.
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 them
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
- // ### The Server Side
45
+ // ### Response Data Types
47
46
 
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
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 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"`.
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, 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 :)
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 transport if it is `true`.
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 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.
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
- origAction = null,
90
- origTarget = null,
91
- origEnctype = null,
92
- addedFields = [],
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
- $(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();
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
- // 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
- });
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
- jQuery.error("data must not be serialized");
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
- addedFields.push($("<input type='hidden'>").attr("name", name)
155
- .attr("value", value).appendTo(form));
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
- addedFields.push($("<input type='hidden' name='X-Requested-With'>")
162
- .attr("value", "IFrame").appendTo(form));
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
- addedFields.push($("<input type='hidden' name='X-Http-Accept'>")
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='iframe-" + $.now()
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 ? 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);
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, 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();
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 gets
216
- // injected into the DOM so that the submission can be initiated.
217
- iframe.insertAfter(form);
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
- $('form').live('ajax:aborted:file', function(){
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
- hash: 15
5
- prerelease: false
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
- date: 2011-08-26 00:00:00 -04:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: thoughtbot-shoulda
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
- requirement: &id001 !ruby/object:Gem::Requirement
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
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
33
34
  type: :development
34
- version_requirements: *id001
35
- description: "Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with jQuery.\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 "
36
- email:
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
- - .gitignore
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
- has_rdoc: true
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
- - --charset=UTF-8
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
- hash: 3
84
- segments:
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ segments:
85
85
  - 0
86
- version: "0"
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
- hash: 3
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.3.7
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 file uploads) with jQuery.
103
- test_files:
104
- - test/helper.rb
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
@@ -1,21 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC
data/test/helper.rb DELETED
@@ -1,10 +0,0 @@
1
- require 'rubygems'
2
- require 'test/unit'
3
- require 'shoulda'
4
-
5
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
- $LOAD_PATH.unshift(File.dirname(__FILE__))
7
- require 'remotipart'
8
-
9
- class Test::Unit::TestCase
10
- end
@@ -1,7 +0,0 @@
1
- require 'helper'
2
-
3
- class TestRemotipart < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
6
- end
7
- end