Rails + Carrierwave + Jquery Fileupload +simple form - ruby-on-rails

I want to make a simple form to upload an audio file. And i want to show a progress bar of the file uploading when the user submits the file. I only want to submit one file at a time.
My _upload.html.erb:
<%= form_for Sound.new do |f| %>
<%= f.file_field :fichier, name: 'sound[fichier]', :required => true %><br />
<%= f.text_field :title, :placeholder => 'Titre', :size => 10, :required => true %><br />
<%= f.submit 'Envoyer' %>
<%end%>
<div class="progress"><div class="bar" style="width: 0%;"></div></div>
My Js file:
$('#new_sound').submit(function() {
$('#new_sound').fileupload({
dataType: 'json',
progress: function (e, data){
var progress = parseInt(data.loaded / data.total * 100, 10);
$('.bar').css('width', progress + '%');
},
});
});
EDIT: (I realize that i forgot my question) Actually it's not really a question it's just i don't get why it didn't work. With this js: it works but i want to wait until the user hits submit before the file is uploaded.
$(function () {
$('#new_sound').fileupload({
dataType: 'json',
add: function (e, data){
data.submit();
},
progress: function (e, data){
var progress = parseInt(data.loaded / data.total * 100, 10);
$('.bar').css('width', progress + '%');
},
});
});

In your first snippet you are binding the submit function on your form that I'm assuming has an id of #new-sound.
Update your second snippet to reflect that. Should look something like this.
$('#new_sound').submit(function() {
$('#new_sound').fileupload({
dataType: 'json',
add: function (e, data){
data.submit();
},
progress: function (e, data){
var progress = parseInt(data.loaded / data.total * 100, 10);
$('.bar').css('width', progress + '%');
},
});
});

Related

Unable to reset/update options on jQuery Chosen in rails app

I'm developing a rails 5.1 app. I'm using chosen javascript plugin in my app for making the select-boxes more user friendly.
In one of my viewpage, I have 2 chosen select boxes. one for project and other for tasks. Requirement is to load only the associated tasks on change of project select box.
My View
<div class="form-group pad-right-one">
<%= f.collection_select :task_project_id_eq, #projects.order(:number), :id, :project_with_number, { include_blank: 'Project' }, {class: 'chosen-select', onchange: "populateTaskFieldWithOptions()"} %>
</div>
<div class="form-group pad-right-one">
<%= f.collection_select :task_id_eq, #tasks.order(:project_id, :number), :id, :task_with_number, { include_blank: 'Task' }, {class: 'chosen-select'} %>
</div>
Js Code
Ajax call that I'm making is a success and I'm getting all the values.
function populateTaskFieldWithOptions(){
let projectId = $("#q_task_project_id_eq").val();
$.ajax({
type: "POST",
url: "/mail/getTasks",
data: {project: projectId},
success:
function(result){
console.log("---Ajax Success----");
document.getElementById('q_task_id_eq').selectedIndex = -1;
var newOption = $('<option value="1">test</option>');
$('#q_task_id_eq').append(newOption);
$('#q_task_id_eq').trigger("chosen:updated");
// Other options I tried ...
//$('#q_task_id_eq').trigger("liszt:updated");
//$('#q_task_id_eq').val(' ').trigger('liszt:updated');
//$('#q_task_id_eq').val(' ').trigger('chosen:updated');
},
error:
function(jqXHR, textStatus, errorThrown){
console.log("---Ajax Error----")
console.error('AJAX Error: ' + textStatus + errorThrown);
}
})
};
I'm not able to reset or update the chosen dropdown.
Any help is really appreciated. Thanks in advance.
$(".chosen-select").chosen("destroy");

How to get uploaded file path from Carrierwave in jquery in Rails

Im using Carrierwave on Rails to handle file upload.
It's working well and I want to make new feature on my app to display uploaded file with jquery (kind of preview uploaded file)
Therefore, I have to pass uploaded file url to the script
Unfortunately, I have no idea how to do it.
File upload model
class OrderFile < ActiveRecord::Base
belongs_to :order
validates :file, presence: true
mount_uploader :file, StLuploaderUploader
end
Form to upload new file
<%= form_for OrderFile.new, html: { multipart: true }, :url => url_for(:controller => 'order_files', :action => 'create') do |f| %>
<%= f.file_field :file, class: "form-control" %>
<% end %>
jquery File Upload call
jQuery(function() {
return $('#new_order_file').fileupload({
autoUpload: true,
add: function(e, data) {
var file, types;
types = /(\.|\/)(png|jpg|)$/i;
file = data.files[0];
if (types.test(file.type) || types.test(file.name)) {
data.context = $(tmpl("template-upload", file));
$('.CO-file_upload_progress').append(data.context);
data.submit();
} else {
return alert("Not supporting");
}
},
progress: function(e, data) {
var progress;
if (data.context) {
progress = parseInt(data.loaded / data.total * 100, 10);
return data.context.find('.bar').css('width', progress + '%');
}
},
done: function(e, data) {
$.each(data.files, function(index, file) {
prepare_file(file); // passing file to the function
});
}
});
});
Function to preview file
function prepare_file(file) {
loaded(file.url, "model-preview"); // I need an absolute path to the uploaded file to be passed here - file.url is not working
};

Rails Amazon S3 direct upload with JQuery File Uploader

I have spent days now trying to make this work. I am getting this error
OPTIONS https://bucketname.s3.oregon.amazonaws.com/ net::ERR_NAME_RESOLUTION_FAILED
I am using Version 43.0.2357.130 Ubuntu 14.04 (64-bit)
Gemfile:
gem "jquery-fileupload-rails"
gem 'aws-sdk'
application.js (after jquery):
//= require jquery-fileupload/basic
application.css:
*= require jquery.fileupload
*= require jquery.fileupload-ui
I have a model called uploads that I have generated scaffolds for like this:
rails generate scaffold Upload upload_url:string
uploads_controller.rb:
def new
#s3_direct_post = Aws::S3::PresignedPost.new(Aws::Credentials.new(ENV['AWS_S3_ACCESS_KEY_ID'], ENV['AWS_S3_SECRET_ACCESS_KEY']),
"Oregon", ENV['AWS_S3_BUCKET'], {
key: '/uploads/object/test.test',
content_length_range: 0..999999999,
acl: 'public-read',
success_action_status: "201",
})
#upload = Upload.new
end
_form.html.erb (for uploads):
<%= form_for(#upload, html: { class: "directUpload" }) do |f| %>
......
<div class="field">
<%= f.label :upload_url %><br>
<%= f.file_field :upload_url %>
</div>
......
<%= content_tag "div", id: "upload_data", data: {url: #s3_direct_post.url, form_data: #s3_direct_post.fields } do %>
<% end %>
application.js (in the end):
$( document ).ready(function() {
$(function() {
$('.directUpload').find("input:file").each(function(i, elem) {
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
fileInput.after(barContainer);
fileInput.fileupload({
fileInput: fileInput,
url: $('#upload_data').data('url'),
type: 'POST',
autoUpload: true,
formData: $('#upload_data').data('form-data'),
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
replaceFileInput: false,
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
submitButton.prop('disabled', true);
progressBar.
css('background', 'green').
css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
submitButton.prop('disabled', false);
progressBar.text("Uploading done");
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
// create hidden field
var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
form.append(input);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
}
});
});
});
});
Seriously What can I do to fix this?
My guess is that you have misconfigured your bucket name / route. The error comes from Amazon, warning you there is no DNS route to https://bucketname.s3.oregon.amazonaws.com/.
It seems to me you need to set the actual bucketname to your bucket name, and also drop oregon from the url. Given that your bucket is named aymansalah, the url will be: https://aymansalah.s3.amazonaws.com/
Review Aws::Credentials documentation and check your environment variables to achieve that URL.
I found the problem. Thanks a lot to felixbuenemann a collaborator in jquery-fileupload-rails
Although that is what I see in the properties (it says Region: Oregon), I have to use "us-west-2" according to this Amazon region documentation
uploads_controller.rb is now:
def new
#s3_direct_post = Aws::S3::PresignedPost.new(Aws::Credentials.new(ENV['AWS_S3_ACCESS_KEY_ID'], ENV['AWS_S3_SECRET_ACCESS_KEY']),
"us-west-2", ENV['AWS_S3_BUCKET'], {
key: '/uploads/object/test.test',
content_length_range: 0..999999999,
acl: 'public-read',
success_action_status: "201",
})
#upload = Upload.new
end

Rails 3 remote form not triggering callback

I have a remote form that is populated by jQuery with an AJAX request. Then, I am binding this form to an AJAX callback but the callback is not being triggered.
var msgSuccess=function(evt, data, status, xhr){
alert('ok!!!');
console.log(evt);
console.log(data);
console.log(status);
console.log(xhr);
}
var bindMsg = function() { // BIND IT TO THE CALLBACKS
$("#composeMsgPopup")
.live('ajax:beforeSend', loadingCallback)
.live('ajax:success', msgSuccess)
.live('ajax:error', failureCallback)
.live('ajax:complete',completeCallback);
}
$.ajax({ // GETTING THE FORM CODE
url: link,
type: "get",
success: function(response, textStatus, jqXHR) {
ans=response;
$("#popup_content").html(ans);
$("#popup").bPopup();
bindMsg();
},
error: function(jqXHR, textStatus, errorThrown) {
failureCallback(errorThrown, textStatus, jqXHR);
},
complete: function(jqXHR, textStatus) {
completeCallback("", jqXHR, textStatus);
},
beforeSend: loadingCallback
});
The code for the form:
<%= form_for(:conversation, :remote => true,
:url=> {:controller=>:conversations,:action=>:create},
:html=>{:id => 'composeMsgPopup' }) do |f| %>
<div id="founder-name" class="field"><b>Recipient: <%= #user.name %></b></div>
<div class="field">
<%= f.label :subject,"Subject" %>
<%= f.text_field :subject,:class=>"composeMsgField" %>
</div>
<div class="field">
<%= f.label :content,"Message Content" %>
<%= f.text_area :content,:class=>"composeMsgField" %>
</div>
<%= f.hidden_field :to_user, :value => #user.id %>
<%= f.submit "Send", :class=>"submitbt",:id=>'sendMessage' %>
<% end % >
I have tried to bind with bind() or on() but it does not work. The code is executed but when I submit the form the callback is not executed.
ok i found a solution.
the remote form not triggering the callback for unknown reason, so what i did is change the
submit button behaviour:
<%= f.button :submit, "Update",:class=>"submitbt",:id=>"submitnewpass",:onclick=>"return false;" %>
and bind the button to manually submit the form
var action=$('#composeMsgPopup')[0].action; // action url
$("#sendMessage").click(function() { // bind submit button
$.ajax({
type: "POST",
url: action,
data: $("#submitnewpass").serialize(), // serializes the form's elements.
success: function(data)
{
// do my stuff
},
error: failureCallback,
beforeSend: loadingCallback,
complete: completeCallback
});
return false;
});

Why isn't this "ajax:success" event firing?

I have a view with several "Invite" buttons like this:
<div class = "fbinvite_form" id = "<%= friend[:identifier] %>" name = "fb">
<div class = "btn btn-small">
Invite
</div>
</div>
When one of these buttons are clicked an AJAX function is called (invite_friend) :
$('.fbinvite_form').click(function() {
invite_friend();
});
Here's invite_friend (some values are hard-coded as I debug):
function invite_friend() {
$.post('/groups/7/invitations',
{
"recipient_email": "facebook#meetcody.com",
"commit" : "fb",
"fb" : "fb"
},
function(response) {
});
}
Here's the relevant line that is returned from the controller:
render :json => {
:url => signup_with_token_url(#invitation.token),
:id => #invitation.id
},
:status => :created
I can confirm that this json is being rendered correctly. At this point I'm expecting an ajax:success event to fire. I have the following code at the top of my page:
$('.fbinvite_form').bind("ajax:success", function(evt, data, status, xhr) {
...
});
But it's not firing. Any clue what might be going wrong or how to better troubleshoot (I'm a bit of a noob)?
Additional Context
I wanted to add a little bit more as it might help. I had originally built this to work with a form and it worked fine. For some performance reasons I decided to switch to buttons with AJAX. Here's the original form:
<%= form_for([#group, #invitation], :remote => true, :html => { :'data-type' => 'html', :class => 'fbinvite_form', :id => friend[:identifier]}) do |f| %>
<%= f.hidden_field :recipient_email, :value => "facebook#meetcody.com" %>
<div class = "fbinvite btn_list_right" id = "<%= friend[:identifier] %>">
<%= f.submit "Invite", :class => "btn btn-medium btn-primary", :name => "fb" %>
</div>
<% end %>
This has since been replace with all the code you see above the controller snippet.
UPDATE 1
Per Vince's suggestion I have moved the "ajax:success" code into the success function. Here is the original "ajax:success" function:
$('.fbinvite_form').bind("ajax:success", function(evt, data, status, xhr){
var fb_id = $(this).attr('id');
var response = eval("(" + xhr.responseText + ")");
var link_url = response.url;
var id = response.id;
var inv_url = <%= raw('"' + group_url(#group) + '/invitations/"') %> + id;
var picture_url = "https://www.example.com.com/assets/cody_130by130.png";
var desc = <%= raw('"' + first_name(current_user) + " is working with Cody on fitness. Join " + genderizer(current_user, "his") + " group to start tracking your workouts. Cody and the other group members will keep you motivated!" + '"') %>;
send_invite(fb_id, link_url, picture_url, desc, inv_url); return false;
});
And here is what I've done to move the code into the success function. The issue is that I don't seem to have access to "xhr"
$.ajax({
type: "POST",
url: "/groups/7/invitations",
data: {recipient_email: "facebook#meetcody.com", commit : "fb", fb : "fb" },
dataType: "json",
success: function(evt, data, status, xhr) {
var fb_id = $(this).attr('id');
var response = eval("(" + xhr.responseText + ")");
var link_url = response.url;
var id = response.id;
var inv_url = <%= raw('"' + group_url(#group) + '/invitations/"') %> + id;
var picture_url = "https://www.meetcody.com/assets/cody_130by130.png";
var desc = <%= raw('"' + first_name(current_user) + " is working with Cody on fitness. Join " + genderizer(current_user, "his") + " group to start tracking your workouts. Cody and the other group members will keep you motivated!" + '"') %>;
send_invite(fb_id, link_url, picture_url, desc, inv_url); return false;
}
});
Add error handler like this and log the error, this should help diagnose the issue.
error: function(xhr, status, error) {
console.log(error);
}
EDIT
Sorry you need to use .ajax instead of .post.
$.ajax({
type: "POST",
url: "/groups/7/invitations",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
},
error(xhr, status, error) {
console.log(error);
}
});

Resources