Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions lib/remotipart/middleware.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Remotipart

# A middleware to look for our form parameters and
# A middleware to look for our form parameters and
# encourage Rails to respond with the requested format
class Middleware
def initialize app
Expand All @@ -16,15 +16,15 @@ def call env
end
params = env['rack.request.form_hash']

# This was using an iframe transport, and is therefore an XHR
# This is required if we're going to override the http_accept
if params and params['X-Requested-With'] == 'IFrame'
env['HTTP_X_REQUESTED_WITH'] = 'xmlhttprequest'
end

# Override the accepted format, because it isn't what we really want
if params and params['X-Http-Accept']
env['HTTP_ACCEPT'] = params['X-Http-Accept']
if params
if params['X-Requested-With'] == 'IFrame' || env['HTTP_X_REQUESTED_WITH'] == 'FormData'
params['remotipart_submitted'] = params['X-Requested-With'] || env['HTTP_X_REQUESTED_WITH']
# This was using a custom transport, and is therefore an XHR
# This is required if we're going to override the http_accept
env['HTTP_X_REQUESTED_WITH'] = 'xmlhttprequest'
end
# For iFrame transport, override the accepted format, because it isn't what we really want
env['HTTP_ACCEPT'] = params['X-Http-Accept'] if params['X-Http-Accept']
end

@app.call(env)
Expand Down
2 changes: 1 addition & 1 deletion lib/remotipart/render_overrides.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module RenderOverrides

def render *args
super
if remotipart_submitted?
if remotipart_iframe?
response.body = %{<textarea data-type=\"#{content_type}\" response-code=\"#{response.response_code}\">#{escape_once(response.body)}</textarea>}
response.content_type = Mime::HTML
end
Expand Down
5 changes: 4 additions & 1 deletion lib/remotipart/request_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ module RequestHelper
def remotipart_submitted?
params[:remotipart_submitted] ? true : false
end

def remotipart_iframe?
params[:remotipart_submitted] == 'IFrame'
end

alias :remotipart_requested? :remotipart_submitted?
end
end
5 changes: 3 additions & 2 deletions remotipart.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Gem::Specification.new do |s|

s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Greg Leppert", "Steve Schwartz"]
s.date = "2012-02-03"
s.date = "2012-04-22"
s.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 "
s.email = ["[email protected]", "[email protected]"]
s.extra_rdoc_files = [
Expand All @@ -36,12 +36,13 @@ Gem::Specification.new do |s|
"remotipart.gemspec",
"test/helper.rb",
"test/test_remotipart.rb",
"vendor/assets/javascripts/jquery.formdata-transport.js",
"vendor/assets/javascripts/jquery.iframe-transport.js",
"vendor/assets/javascripts/jquery.remotipart.js"
]
s.homepage = "http://www.alfajango.com/blog/remotipart-rails-gem/"
s.require_paths = ["lib"]
s.rubygems_version = "1.8.11"
s.rubygems_version = "1.8.21"
s.summary = "Remotipart is a Ruby on Rails gem enabling remote multipart forms (AJAX style file uploads) with jQuery."

if s.respond_to? :specification_version then
Expand Down
93 changes: 93 additions & 0 deletions vendor/assets/javascripts/jquery.formdata-transport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
(function($, undefined) {

if (typeof FormData === 'undefined') return;

// Register a prefilter that checks whether the `iframe` option is set, and
// switches to the iframe transport if it is `true`.
$.ajaxPrefilter(function(options, origOptions, jqXHR) {
if (options.formdata) return "formdata";
});

// Register an iframe transport, independent of requested data type. It will
// only activate when the "files" option has been set to a non-empty list of
// enabled file inputs.
$.ajaxTransport("formdata", function(options, origOptions, jqXHR) {
var form = null,
xhr = new XMLHttpRequest(),
formData = new FormData(),
files = $(options.files).filter(":file:enabled");

options.dataTypes.shift();

if (files.length === 0) return;
// Determine the form the file fields belong to, and make sure they all
// actually belong to the same form.
files.each(function() {
if (form !== null && this.form !== form) {
jQuery.error("All file fields must belong to the same form");
}
form = this.form;
});
form = $(form);

// Add passed-in data to the FormData object
// Note that the data must not be serialized (options.processData = false)
if (typeof(options.data) === "string" && options.data.length > 0) {
jQuery.error("data must not be serialized");
}
$.each(options.data || {}, function(name, value) {
if ($.isPlainObject(value)) {
name = value.name;
value = value.value;
}
formData.append(name,value);
});
files.each(function() {
var name = this.name;
$.each(this.files,function(){
formData.append(name,this)
})
})

// Borrowed straight from the JQuery source
// Provides a way of specifying the accepted data type similar to HTTP_ACCEPTS
accepts = options.dataTypes[ 0 ] && options.accepts[ options.dataTypes[0] ] ?
options.accepts[ options.dataTypes[0] ] + ( options.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
options.accepts[ "*" ]

return {

// The `send` function is called by jQuery when the request should be
// sent.
send: function(headers, completeCallback) {
xhr.open('POST',options.url,true);
xhr.setRequestHeader('Accept',accepts);
xhr.setRequestHeader('X-Requested-With','FormData');
xhr.onreadystatechange = function(e) {
if (xhr.readyState !== 4) return;
var status = xhr.status,
statusText = xhr.statusText.replace(/^\d+ +/,''),
responses = { text: xhr.responseText },
headers = xhr.getAllResponseHeaders();
completeCallback(status, statusText, responses, headers);
};
if (typeof xhr.upload !== 'undefined') xhr.upload.onprogress = function(e) {
var progEvent = $.Event('ajax:progress.remotipart');
progEvent.lengthComputable = e.lengthComputable;
progEvent.total = e.total;
progEvent.loaded = e.loaded;
form.trigger(progEvent);
}
else form.trigger('ajax:progress:notsupported.remotipart');
xhr.send(formData);
},

// The `abort` function is called by jQuery when the request should be
// aborted.
abort: function() {
xhr.abort();
}
};
});

})(jQuery);
6 changes: 5 additions & 1 deletion vendor/assets/javascripts/jquery.remotipart.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//= require jquery.iframe-transport.js
//= require jquery.formdata-transport.js
//= require_self

(function($) {
Expand All @@ -17,7 +18,10 @@
// delete settings.beforeSend;
delete settings.beforeSend;

settings.iframe = true;
if (typeof FormData !== 'undefined')
settings.formdata = true;
else
settings.iframe = true;
settings.files = $($.rails.fileInputSelector, form);
settings.data = form.serializeArray();
settings.processData = false;
Expand Down