From ad369321f1789bbcbd4724db52b79188eddb0954 Mon Sep 17 00:00:00 2001 From: Andrew Narkewicz Date: Wed, 10 Apr 2013 01:51:19 -0700 Subject: [PATCH 1/3] Got working with nested forms --- .../javascripts/s3_direct_upload.js.coffee | 48 ++++++++++--------- lib/s3_direct_upload/form_helper.rb | 36 ++++++++++++-- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/app/assets/javascripts/s3_direct_upload.js.coffee b/app/assets/javascripts/s3_direct_upload.js.coffee index 05858d8..b945b89 100644 --- a/app/assets/javascripts/s3_direct_upload.js.coffee +++ b/app/assets/javascripts/s3_direct_upload.js.coffee @@ -12,7 +12,7 @@ $.fn.S3Uploader = (options) -> return this - $uploadForm = this + $uploaderElement = this settings = path: '' @@ -32,8 +32,9 @@ $.fn.S3Uploader = (options) -> form.submit() for form in forms_for_submit false - setUploadForm = -> - $uploadForm.fileupload + setUploadElement = -> + $uploaderElement.fileupload + url: settings.url if settings.url add: (e, data) -> file = data.files[0] @@ -42,14 +43,14 @@ $.fn.S3Uploader = (options) -> unless settings.before_add and not settings.before_add(file) current_files.push data data.context = $($.trim(tmpl("template-upload", file))) if $('#template-upload').length > 0 - $(data.context).appendTo(settings.progress_bar_target || $uploadForm) + $(data.context).appendTo(settings.progress_bar_target || $uploaderElement) if settings.click_submit_target forms_for_submit.push data else data.submit() start: (e) -> - $uploadForm.trigger("s3_uploads_start", [e]) + $uploaderElement.trigger("s3_uploads_start", [e]) progress: (e, data) -> if data.context @@ -57,35 +58,35 @@ $.fn.S3Uploader = (options) -> data.context.find('.bar').css('width', progress + '%') done: (e, data) -> - content = build_content_object $uploadForm, data.files[0], data.result + content = build_content_object $uploaderElement, data.files[0], data.result - to = $uploadForm.data('callback-url') + to = $uploaderElement.data('callback-url') if to - content[$uploadForm.data('callback-param')] = content.url + content[$uploaderElement.data('callback-param')] = content.url $.ajax - type: $uploadForm.data('callback-method') + type: $uploaderElement.data('callback-method') url: to data: content - beforeSend: ( xhr, settings ) -> $uploadForm.trigger( 'ajax:beforeSend', [xhr, settings] ) - complete: ( xhr, status ) -> $uploadForm.trigger( 'ajax:complete', [xhr, status] ) - success: ( data, status, xhr ) -> $uploadForm.trigger( 'ajax:success', [data, status, xhr] ) - error: ( xhr, status, error ) -> $uploadForm.trigger( 'ajax:error', [xhr, status, error] ) + beforeSend: ( xhr, settings ) -> $uploaderElement.trigger( 'ajax:beforeSend', [xhr, settings] ) + complete: ( xhr, status ) -> $uploaderElement.trigger( 'ajax:complete', [xhr, status] ) + success: ( data, status, xhr ) -> $uploaderElement.trigger( 'ajax:success', [data, status, xhr] ) + error: ( xhr, status, error ) -> $uploaderElement.trigger( 'ajax:error', [xhr, status, error] ) # $.post(to, content) data.context.remove() if data.context && settings.remove_completed_progress_bar # remove progress bar - $uploadForm.trigger("s3_upload_complete", [content]) + $uploaderElement.trigger("s3_upload_complete", [content]) current_files.splice($.inArray(data, current_files), 1) # remove that element from the array - $uploadForm.trigger("s3_uploads_complete", [content]) unless current_files.length + $uploaderElement.trigger("s3_uploads_complete", [content]) unless current_files.length fail: (e, data) -> - content = build_content_object $uploadForm, data.files[0], data.result + content = build_content_object $uploaderElement, data.files[0], data.result content.error_thrown = data.errorThrown data.context.remove() if data.context && settings.remove_failed_progress_bar # remove progress bar - $uploadForm.trigger("s3_upload_failed", [content]) + $uploaderElement.trigger("s3_upload_failed", [content]) formData: (form) -> data = form.serializeArray() @@ -101,26 +102,27 @@ $.fn.S3Uploader = (options) -> data[1].value = settings.path + key data - build_content_object = ($uploadForm, file, result) -> + build_content_object = ($uploaderElement, file, result) -> content = {} if result # Use the S3 response to set the URL to avoid character encodings bugs content.url = $(result).find("Location").text() content.filepath = $('').attr('href', content.url)[0].pathname - else # IE <= 9 return a null result object so we use the file object instead - domain = $uploadForm.attr('action') - content.filepath = settings.path + $uploadForm.find('input[name=key]').val().replace('/${filename}', '') - content.url = domain + content.filepath + '/' + encodeURIComponent(file.name) + #else # IE <= 9 return a null result object so we use the file object instead + #domain = $uploaderElement.attr('action') + #content.filepath = settings.path + $uploaderElement.find('input[name=key]').val().replace('/${filename}', '') + #content.url = domain + content.filepath + '/' + encodeURIComponent(file.name) content.filename = file.name content.filesize = file.size if 'size' of file content.filetype = file.type if 'type' of file content.unique_id = file.unique_id if 'unique_id' of file content = $.extend content, settings.additional_data if settings.additional_data + content = $.extend content, $('.s3upload_hidden_fields').serializeArray() content #public methods @initialize = -> - setUploadForm() + setUploadElement() this @path = (new_path) -> diff --git a/lib/s3_direct_upload/form_helper.rb b/lib/s3_direct_upload/form_helper.rb index 0cde2d1..e4bdc91 100644 --- a/lib/s3_direct_upload/form_helper.rb +++ b/lib/s3_direct_upload/form_helper.rb @@ -9,6 +9,18 @@ def s3_uploader_form(options = {}, &block) end end + def s3_uploader_hidden_fields(options = {}, &block) + uploader = S3Uploader.new(options) + uploader.fields.map do |name, value| + hidden_field_tag(name, value, :class => "s3upload_hidden_fields") + end.join.html_safe + end + + def s3_uploader_field(options = {}) + uploader = S3Uploader.new(options) + file_field_tag(:file, uploader.field_options).html_safe + end + class S3Uploader def initialize(options) @key_starts_with = options[:key_starts_with] || "uploads/" @@ -31,19 +43,33 @@ def initialize(options) def form_options { - id: @options[:id], - class: @options[:class], method: "post", authenticity_token: false, multipart: true, + }.merge(field_options) + end + + def field_options + form_data_options.merge(form_preset_options) + end + + def form_data_options + { data: { - callback_url: @options[:callback_url], - callback_method: @options[:callback_method], - callback_param: @options[:callback_param] + callback_url: @options[:callback_url], + callback_method: @options[:callback_method], + callback_param: @options[:callback_param] }.reverse_merge(@options[:data] || {}) } end + def form_preset_options + { + id: @options[:id], + class: @options[:class], + } + end + def fields { :key => @options[:key] || key, From 82f28310766170fd7171bdb9c26a11eaf11d691d Mon Sep 17 00:00:00 2001 From: Andrew Narkewicz Date: Wed, 10 Apr 2013 10:19:30 -0700 Subject: [PATCH 2/3] Fix upload from fields to have utf8 and make s3_progress_bar_target accept a function --- app/assets/javascripts/s3_direct_upload.js.coffee | 6 +++--- lib/s3_direct_upload/form_helper.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/s3_direct_upload.js.coffee b/app/assets/javascripts/s3_direct_upload.js.coffee index b945b89..21acf47 100644 --- a/app/assets/javascripts/s3_direct_upload.js.coffee +++ b/app/assets/javascripts/s3_direct_upload.js.coffee @@ -43,7 +43,7 @@ $.fn.S3Uploader = (options) -> unless settings.before_add and not settings.before_add(file) current_files.push data data.context = $($.trim(tmpl("template-upload", file))) if $('#template-upload').length > 0 - $(data.context).appendTo(settings.progress_bar_target || $uploaderElement) + $(data.context).appendTo(settings.progress_bar_target($(this)) || $uploaderElement) if settings.click_submit_target forms_for_submit.push data else @@ -89,7 +89,8 @@ $.fn.S3Uploader = (options) -> $uploaderElement.trigger("s3_upload_failed", [content]) formData: (form) -> - data = form.serializeArray() + data = $('.s3upload_hidden_fields').serializeArray() + #data = form.serializeArray() fileType = "" if "type" of @files[0] fileType = @files[0].type @@ -117,7 +118,6 @@ $.fn.S3Uploader = (options) -> content.filetype = file.type if 'type' of file content.unique_id = file.unique_id if 'unique_id' of file content = $.extend content, settings.additional_data if settings.additional_data - content = $.extend content, $('.s3upload_hidden_fields').serializeArray() content #public methods diff --git a/lib/s3_direct_upload/form_helper.rb b/lib/s3_direct_upload/form_helper.rb index e4bdc91..36f6f03 100644 --- a/lib/s3_direct_upload/form_helper.rb +++ b/lib/s3_direct_upload/form_helper.rb @@ -11,7 +11,7 @@ def s3_uploader_form(options = {}, &block) def s3_uploader_hidden_fields(options = {}, &block) uploader = S3Uploader.new(options) - uploader.fields.map do |name, value| + {:utf8 => ""}.merge(uploader.fields).map do |name, value| hidden_field_tag(name, value, :class => "s3upload_hidden_fields") end.join.html_safe end From 5508065060fc0a0d58f1180582f60addfae2eb1c Mon Sep 17 00:00:00 2001 From: Andrew Narkewicz Date: Thu, 11 Apr 2013 00:33:20 -0700 Subject: [PATCH 3/3] Use same hidden fields for aws inputs for input or form and make ajax callbacks fire --- app/assets/javascripts/s3_direct_upload.js.coffee | 12 +++++------- lib/s3_direct_upload/form_helper.rb | 5 ++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/s3_direct_upload.js.coffee b/app/assets/javascripts/s3_direct_upload.js.coffee index 21acf47..3f62b4e 100644 --- a/app/assets/javascripts/s3_direct_upload.js.coffee +++ b/app/assets/javascripts/s3_direct_upload.js.coffee @@ -64,16 +64,15 @@ $.fn.S3Uploader = (options) -> if to content[$uploaderElement.data('callback-param')] = content.url + element = $(this) $.ajax type: $uploaderElement.data('callback-method') url: to data: content - beforeSend: ( xhr, settings ) -> $uploaderElement.trigger( 'ajax:beforeSend', [xhr, settings] ) - complete: ( xhr, status ) -> $uploaderElement.trigger( 'ajax:complete', [xhr, status] ) - success: ( data, status, xhr ) -> $uploaderElement.trigger( 'ajax:success', [data, status, xhr] ) - error: ( xhr, status, error ) -> $uploaderElement.trigger( 'ajax:error', [xhr, status, error] ) - - # $.post(to, content) + beforeSend: ( xhr, settings ) -> element.trigger( 'ajax:beforeSend', [xhr, settings] ) + complete: ( xhr, status ) -> element.trigger( 'ajax:complete', [xhr, status] ) + success: ( data, status, xhr ) -> element.trigger( 'ajax:success', [data, status, xhr] ) + error: ( xhr, status, error ) -> element.trigger( 'ajax:error', [xhr, status, error] ) data.context.remove() if data.context && settings.remove_completed_progress_bar # remove progress bar $uploaderElement.trigger("s3_upload_complete", [content]) @@ -90,7 +89,6 @@ $.fn.S3Uploader = (options) -> formData: (form) -> data = $('.s3upload_hidden_fields').serializeArray() - #data = form.serializeArray() fileType = "" if "type" of @files[0] fileType = @files[0].type diff --git a/lib/s3_direct_upload/form_helper.rb b/lib/s3_direct_upload/form_helper.rb index 36f6f03..e5ea92c 100644 --- a/lib/s3_direct_upload/form_helper.rb +++ b/lib/s3_direct_upload/form_helper.rb @@ -4,14 +4,14 @@ def s3_uploader_form(options = {}, &block) uploader = S3Uploader.new(options) form_tag(uploader.url, uploader.form_options) do uploader.fields.map do |name, value| - hidden_field_tag(name, value) + hidden_field_tag(name, value, :class => "s3upload_hidden_fields") end.join.html_safe + capture(&block) end end def s3_uploader_hidden_fields(options = {}, &block) uploader = S3Uploader.new(options) - {:utf8 => ""}.merge(uploader.fields).map do |name, value| + (uploader.fields).map do |name, value| hidden_field_tag(name, value, :class => "s3upload_hidden_fields") end.join.html_safe end @@ -98,7 +98,6 @@ def policy_data { expiration: @options[:expiration], conditions: [ - ["starts-with", "$utf8", ""], ["starts-with", "$key", @options[:key_starts_with]], ["starts-with", "$x-requested-with", ""], ["content-length-range", 0, @options[:max_file_size]],