remotipart 1.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
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