jQuery file upload with paperclip, showing preview image before upload - javascript

I'm trying to accomplish like this
Trying to show preview of the images that I want to upload, but nothing is showing up. I'm looking at my log and when I try to upload, the log is spitting out stuff, mostly Image Exists (0.2ms) and Image Load (0.3ms), and showing SELECT 1 AS.... SQL syntax
This is my form.html.erb
<%= simple_form_for #photo, html: { multipart: true, id: 'bePhoto' } do |f| %>
<div class="row fileupload-buttonbar">
<div class="col-lg-7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<input type="file" name="photos[]" multiple>
</span>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel upload</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
<input type="checkbox" class="toggle">
<!-- The global file processing state -->
<span class="fileupload-process"></span>
</div>
<!-- The global progress state -->
<div class="col-lg-5 fileupload-progress fade">
<!-- The global progress bar -->
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar progress-bar-success" style="width:0%;"></div>
</div>
<!-- The extended global progress state -->
<div class="progress-extended"> </div>
</div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>
<% end %>
Then I have this javascript
$(function () {
$('#bePhoto').fileupload();
$('#bePhoto').addClass('fileupload-processing');
$.ajax({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: $('#bePhoto').fileupload('option', 'url'),
dataType: 'json',
context: $('#beTripForm')[0]
}).always(function () {
$(this).removeClass('fileupload-processing');
}).done(function (result) {
$(this).fileupload('option', 'done')
.call(this, $.Event('done'), {result: result});
});
});
I also have this
<script src="http://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script>
<script src="http://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script>
<script src="http://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
<script src="http://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script>
And this:
//= require jquery-fileupload/basic
//= require jquery-fileupload/basic-plus
I pretty much tried to mimic the sample demo, but not sure if I'm doing this correctly.

If your concern is to display the selected image before uploading and upload them during form submit I tried to write custom script for this.Please have a look and let me know.
Here I read the input file content and display them in image tag as thumbnail.It doesn't show the progress of file uploading but all the files are submitted during form submit event.
Please add a div to display the thumnail image just above the file input field
<div class="row" id="uploader-wrapper"></div>
<%= f.file_field(:photo, id: 'photo_upload_btn', multiple: true) %>
And add event listner for your file input field.
$("#photo_upload_btn").change(function () {
displayThumbnail(this);
});
Add the following Javasript code to display the Thumbnail
function displayThumbnail(input) {
for( var i = 0;i<input.files.length;i++){
if (input.files && input.files[i]) {
var reader = new FileReader();
reader.onload = function (e) {
if ($('#photo_upload_btn').valid()) {
var $newImageThumbnail = makeElement('img',{ class: "image-frame",src: e.target.result});
$('#uploader-wrapper').append($newImageThumbnail);
}
};
reader.readAsDataURL(input.files[i]);
}
}
}
function makeElement(element, options) {
var $elem = document.createElement(element);
$.each(options, function (key, value) {
$elem.setAttribute(key, value);
});
return $elem;
}
Also don't forget to style the thumbnail
.image-frame {
border: 1px dashed #333;
width: 150px;
height: 150px;
margin: 0 0 10px;
}

Related

How to reset modal contents?

The process is like this.
A user searches any words in a search form. Ajax calls with the word and gets the data, then it will be showed with the modal.
So, I tried to make modal dynamically with ajax.
But the modal contents didn't change once it called.
1) This is the function include a search form and it calls the modal.
function answer() {
//console.log('answer');
var div = document.createElement('div');
div.className = 'row';
div.innerHTML = `<!-- file form start -->
<!-- file form end -->
<label class="col-md-2 col-form-label">문의내용</label>
<!-- text form start -->
{!! Form::open([ 'route' => ['qnamembercreate', $qnaMemberData->idx], 'method' => 'post', 'files' => true, 'accept-charset' => 'utf-8','class' => 'col-md-10 col-xs-9' ])!!}
<div class="col-sm-6 offset-md-6 p-0">
<div class="input-group">
<input type="text" id="f_search" name="f_search" class="form-control">
<span class="input-group-append">
<button type="button" class="btn waves-effect waves-light btn-inverse" onclick="faq_search()">Search</button>
</span>
</div>
</div>
<input type="hidden" name="subject" value="{{ $qnaMemberData->subject }}">
<textarea id="answer_content" class="mb-0" rows="20" style="width:100%;" name="add_answer"></textarea>
<div class="form-group">
<input name="fileToUpload" type="file" class="filestyle" data-input="false" id="filestyle-1" tabindex="-1" style="display: none;">
<div class="bootstrap-filestyle input-group">
<div style="position: absolute; width: 100%; height: 35.375px; z-index: -1;"></div>
<span class="group-span-filestyle " tabindex="0">
<label for="filestyle-1" style="margin-bottom: 0;" class="btn btn-secondary btn-sm fload-right">
<input type="file" name="fileToUpload" class="filestyle-1" data-placeholder="" data-buttontext="첨부파일" data-buttonname="btn-secondary">
</label>
</span>
</div>
</div>
<button type="button" class="btn btn-danger btn-sm float-right ml-1 mt-1" onclick="history.back()">취소</button>
<button type="submit" class="btn btn-success btn-sm float-right mt-1">등록</button>
{!! Form::close() !!}
<!-- text form end -->`;
document.getElementById('replyData').appendChild(div);
document.getElementById('answer').remove();
$('#answer_content').summernote({
// placeholder: {!! json_encode($qnaMemberData->content) !!},
tabsize: 2,
height: 200,
lang: 'ko-KR',
fontNames: ['Gulim', 'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New', ],
fontNamesIgnoreCheck: ['Gulim'],
});
}
2) This is the 'faq_search' function when the user clicks the 'search' button.
function faq_search() {
var word = $('#f_search')[0].value;
//console.log(word);
$.ajax({
url : '/guidesearch',
type : 'POST',
data : {
keyword: word
},
cache : false,
success : function(data, jqXHR, textStatus) {
console.log(data);
faq_popup(data);
}
});
}
3) This is the 'faq_popup' function which is called after getting the data.
function faq_popup(data) {
var _data = data;
console.log("here", _data);
const appendedDiv = $(`
<div class="modal fade show" tabindex="-1" id="faqModal" role="dialog" style="positon:center;">
<div class="modal-dialog modal-dialog-centered">
<!-- Modal content-->
<div class="modal-content">
<div class="table-responsive">
<table class="table mb-0">
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
`);
const tbody = appendedDiv.find('tbody')[0];
_data.forEach(({ content, subject }, i) => {
//console.log(i);
const tr = tbody.appendChild(document.createElement('tr'));
tr.innerHTML = `
<th scope="row">${i + 1}</th>
<td><a style="cursor:pointer">${subject}</a></td>
`;
tr.querySelector('a').addEventListener('click', () => getContent(content));
});
$('#modal_place').append(appendedDiv);
$('#faqModal').modal('show');
}
I tried to reset the modal with this code below. But the problem is, once the modal content is cleared, the new data is not called at all.
$(document).ready(function(){
$('body').on('hidden.bs.modal', '.modal', function () {
console.log("modal closed");
$(this).find('tbody td').html("");
});
});
I really don't get it. Because I call the 'faq_popup' after the ajax got the data, the new data should be showed. But it doesn't work as I think.
What did I wrong here?
** I also tried to wipe out the whole modal-content. The modal contents doesn't show up at all.
$('body').on('hidden.bs.modal', '.modal', function () {
console.log("modal closed");
$(this).find('.modal-content').html("");
});
I found the solution. Thanks to #KaseyChang, gave me the hint.
The reason was I didn't destroy the modal correctly. The modal was added and added on itself. So I just did this.
$('body').on('hidden.bs.modal', '.modal', function () {
console.log("modal closed");
$(this).remove(); <--- here!
});
In the AJAX function you can just empty() the modal before the call is made, using beforeSend. This way it will happen sequentially:
function faq_search() {
var word = $('#f_search')[0].value;
$.ajax({
url : '/guidesearch',
type : 'POST',
data : {
keyword: word
},
cache : false,
beforeSend : function() {
$('.modal-content').empty();
},
success : function(data, jqXHR, textStatus) {
console.log(data);
faq_popup(data);
}
});
}

Magnific Pop up wont close when you press Cancel on the Modal

I am using Magnific Pop up on a project, currently I have it on a ASP MVC project as a Modal:
Modal
div id="js_DeleteNewSongsPopup" class="theme-primary ajax-form popup-basic admin-form mfp-with-anim modalPopup">
<div class="panel">
<div class="panel-heading">
<span class="panel-title">
<i class="fa fa-ban "></i>Reject Selected Song
</span>
</div>
#* Information Body *#
<div class="panel-body p25">
<div class="section row">
<div class="col-md-12 text-center">
<h3>
Are you sure you want to <b class="text-danger">reject</b> the selected Songs?
</h3>
<p>
Please note, these will be <b class="text-danger">deleted</b> and no longer accessable
</p>
</div>
</div>
</div>
#* Form Body *#
<div class="panel-footer">
<div class="text-center">
<fieldset>
<input type="button" class="btn btn-primary js_CancelForm" value="Cancel" data-bind="click: function(){ $.magnificPopup.close(); }">
<input type="button" class="btn btn-danger js_DeleteNewSongsButton" value="Delete" data-bind="click: $root.submitDeleteNewSongs">
</fieldset>
</div>
</div>
</div>
<button title="Close (Esc)" type="button" class="mfp-close">×</button>
JavaScript
/* Delete New Songs Popup*/
$(document).on("click",
".js_DeleteNewSongs",
function (e) {
e.preventDefault();
var popup = $("#js_DeleteNewSongsPopup");
$.magnificPopup.open({
removalDelay: 500, //delay removal by X to allow out-animation,
items: {
src: $(popup)
},
callbacks: {
beforeOpen: function (e) {
this.st.mainClass = 'mfp-slideUp';
},
close: function () {
}
},
midClick: true
// allow opening popup on middle mouse click. Always set it to true if you don't provide alternative source.
});
return false;
});
Any ideas as there is no console errors being reported. I am also unsure why it is working on another page, when the mark-up is identical
Try:
$('body').removeClass('panel-body p25');
Or
$('body').removeClass('theme-primary ajax-form popup-basic admin-form mfp-with-anim modalPopup');
Basically you need to remove the "modal" class.
Ended up using:
$('.js_CancelForm').on("click", function () {
$.magnificPopup.close();
});
Now the Popup closes as expected.

Converting Bootstrap 3 remote modal to Bootstrap 4 modal with parameters

So in the near future my shop is going to upgrade to Bootstrap 4 but we cannot do this until we solve the issue with using remote modals. Here is an example of how we load our modals. The reason we use remote modals is because the modal-body is dynamic and may use different file based on the url. I have heard that using jQuery("#newsModal").on("load",..) is an alternative but how could I do this? I found this but I am not sure how my anchor would look and how to build the url to load the remote data.
Global PHP include file:
<div id="NewsModal" class="modal fade" tabindex="-1" role="dialog" data-
ajaxload="true" aria-labelledby="newsLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="newsLabel"></h3>
</div>
<div class="noscroll-modal-body">
<div class="loading">
<span class="caption">Loading...</span>
<img src="/images/loading.gif" alt="loading">
</div>
</div>
<div class="modal-footer caption">
<button class="btn btn-right default modal-close" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
modal_news.php file:
<form id="newsForm">
<div id="hth_err_msg" class="alert alert-danger display-hide col-lg-12 col-md-12 col-sm-12 col-xs-12">
You have some errors. Please check below.
</div>
<div id="hth_ok_msg" class="alert alert-success display-hide col-lg-12 col-md-12 col-sm-12 col-xs-12">
✔ Ready
</div>
<!-- details //-->
</form>
Here is how we trigger the modals :
<a href="#newsModal" id="modal_sbmt" data-toggle="modal" data-target="#newsModal"
onclick="remote='modal_news.php?USER=yardpenalty&PKEY=54&FUNCTION=*GENERAL'; remote_target='#NewsModal .noscroll-modal-body'">
<span class="label label-icon label-info">
<i class="fa fa-bullhorn"></i>
</span>
Promotional Ordering
</a>
I think I need to do something like this when building anchor dynamically:
a) Replace paramters with data-attrs
b) Use the event invoker to get the data-attrs using event.target.id
Thanks to Tieson T. and this post I was able to effectively pass parameters to the remote modal using this technique except if you have multiple modals
I have also included some helpful techniques inside this example as to how you may pass parameters to the remote modal.
bootstrap_modal4.php:
<div class="portlet-body">
Add Attendee <i class="fa fa-plus"></i>
</div>
<!-- BEGIN Food Show Attendee Add/Edit/Delete Modal -->
<div id="attendee" class="modal fade" tabindex="-1" role="dialog" data-ajaxload="true" aria-labelledby="atnLabel" aria-hidden="true">
<form id="signupForm" method="post">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<label id="atnLabel" class="h3"></label><br>
<label id="evtLabel" class="h6"></label>
</div>
<div class="modal-body">
<div class="loading"><span class="caption">Loading...</span><img src="/images/loading.gif" alt="loading"></div>
</div>
<div class="modal-footer">
<span class="caption">
<button type="button" id="add_btn" class="btn btn-success add-attendee hidden">Add Attendee <i class="fa fa-plus"></i></button>
<button type="button" id="edit_btn" class="btn btn-info edit-attendee hidden">Update Attendee <i class="fa fa-save"></i></button>
<button type="button" id="del_btn" class="btn btn-danger edit-attendee hidden">Delete Attendee <i class="fa fa-minus"></i></button>
<button class="btn default modal-close" data-dismiss="modal" aria-hidden="true">Cancel</button>
</span>
</div>
</div>
</div>
</form>
</div>
<script>
jQuery(document).ready(function() {
EventHandlers();
});
function EventHandlers(){
$('#attendee').on('show.bs.modal', function (e) {
e.stopImmediatePropagation();
if($(this).attr('id') === "attendee"){
// Determines modal's data display based on its data-attr
var $invoker = $(e.relatedTarget);
var fscode = $invoker.attr('data-fscode');
console.log(fscode);
// Add Attendee
if($invoker.attr('data-atnid') === "add"){
$("#atnLabel").text("Add New Attendee");
$(".add-attendee").removeClass("hidden");
}
else{ //edit/delete attendee
$("#atnLabel").text("Attendee Maintenance");
$(".edit-attendee").removeClass("hidden");
}
//insert hidden inputs
//add input values for post
var hiddenInput = '<INPUT TYPE=HIDDEN NAME=FSCODE VALUE="' + fscode + '"/>';
$("#signupForm").append(hiddenInput);
}
});
$('#attendee').on('hidden.bs.modal', function (e) {
$(".edit-attendee").addClass("hidden");
$(".add-attendee").addClass("hidden");
$("#signupForm input[type='hidden']").remove();
});
// BOOTSTRAP 4 REMOTE MODAL ALTERNATIVE FOR BOOTSTRAP 3v-
$('#add-attendee').on('click', function(e){
$($(this).data("target")+' .modal-body').load($(this).data("remote"));
$("#attendee").modal('show');
});
}
</script>
bootstrap_remote_modal4.php:
<form id="signupForm">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
Hello World!
</div>
</form>
<script>
$(document).ready(function(){
console.log('<?php echo $_GET["USERNAME"]?>'); //passed through url
});
</script>
NOTE: I am having problems with event propagation during the show.bs.modal event which I have a global show.bs.modal that is propagating up to this event handler due to multiple modals so if you have multiple modals make sure to handle them correctly.
Here is a screen shot of the results which clearly show propagation is taking place but the parameter passing techniques are working.
You might find it easier to use something like Bootbox.js, which can be used to dynamically create Bootstrap modals.
Given what you've shown, it would work something like:
trigger modal
with
$(function(){
$('.show-modal').on('click', function(e){
e.preventDefault();
var url = $(this).attr('href');
$.get(url)
.done(function(response, status, jqxhr) {
bootbox.dialog({
title: 'Your Title Here',
message: response
});
});
});
});
This assumes response is an HTML fragment.
Bootbox hasn't officially been confirmed to work with Bootstrap 4, but I haven't run into any problems with it yet (modals seem to be one of the few components that don't have updated markup in BS4).
Disclaimer: I am currently a contributor to Bootbox (mainly updating the documentation and triaging issues).
If you must use only the Bootstrap modal, you're actually after load(). You would probably do something like:
$(function(){
$('.show-modal').on('click', function(e){
e.preventDefault();
var url = $(this).attr('href');
var dialog = $('#NewsModal').clone();
dialog.load(url, function(){
dialog.modal('show');
});
});
});

How to add input box to Dropzone.js and sent the value to another API endpoint?

Currently I'm using the bootstrap theme config of dropzone.js, e.g. http://www.dropzonejs.com/bootstrap.html. What I want to achieve here is, add one input box to let the user input custom pic title, and another td in the table to show the response info(e.g. full link to the uploaded pic). After uploading done, send the pic title and pic link to another API endpoint to save them.
Tried to work with listening on addedFile and success but with no luck...The preview template is almost the same as in the docs. Really not skillful in HTML and Javascript. :(
<div class="table table-striped files" id="previews">
<div id="template" class="file-row">
<!-- This is used as the file preview template -->
<div>
<span class="preview"><img data-dz-thumbnail /></span>
</div>
<div>
<p class="name" data-dz-name></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
<div>
<p class="title">
<input type="text" name="title" id="title" placeholder="Input pic title or comment here!">
</p>
</div>
<div>
<!-- URL returned should be here? -->
<p id="fpurl" class="error text-danger"></p>
</div>
<div>
<p class="size" data-dz-size></p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress></div>
</div>
</div>
<div>
<button class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
<button data-dz-remove class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button data-dz-remove class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</div>
</div>
</div>
JS code below:
var previewNode = document.querySelector("#template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
var myDropzone = new Dropzone(document.body, {
url: "http://upload/file/url",
paramName: "fpfile",
thumbnailWidth: 80,
thumbnailHeight: 80,
headers: {"Cache-Control": null},
parallelUploads: 20,
previewTemplate: previewTemplate,
autoQueue: false, // Make sure the files aren't queued until manually added
previewsContainer: "#previews", // Define the container to display the previews
});
myDropzone.on("addedfile", function(file) {
// Hookup the start button
file.previewElement.querySelector(".start").onclick = function() { myDropzone.enqueueFile(file); };
});
// Update the total progress bar
myDropzone.on("totaluploadprogress", function(progress) {
document.querySelector("#total-progress .progress-bar").style.width = progress + "%";
});
myDropzone.on("success", function(file, response) {
var j = $.parseJSON(response);
var responseurl = $.parseJSON(j).url;
var fname = file.name;
// alert(file.name);
});
myDropzone.on("sending", function(file, xhr, data) {
// Auth info
data.append("Authorization", "Secret code here");
// Show the total progress bar when upload starts
document.querySelector("#total-progress").style.opacity = "1";
// And disable the start button
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
// Hide the total progress bar when nothing's uploading anymore
myDropzone.on("queuecomplete", function(progress) {
document.querySelector("#total-progress").style.opacity = "0";
});
// Setup the buttons for all transfers
// The "add files" button doesn't need to be setup because the config
// `clickable` has already been specified.
document.querySelector("#actions .start").onclick = function() {
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
};
document.querySelector("#actions .cancel").onclick = function() {
myDropzone.removeAllFiles(true);
};

Dropezone MVC5 Add extra parameter on Upload

I am using dropzone to upload files to my server without any issues, i would like to add extra parameters such a meta data.
Any ideas on how to do this?
Code Below and just using controller in normal fashion
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>Select</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
</a>
</div>
</div>
<div class="ibox-content">
<form id="my-awesome-dropzone" class="dropzone" action="#Url.Action(" FileUploadHandler ", "Controller ")" method="post" enctype="multipart/form-data">
<div class="dropzone-previews"></div>
<button type="submit" class="btn btn-primary pull-right">Submit your application</button>
</form>
<div>
<div class="m text-right">test</div>
</div>
</div>
</div>
</div>
</div>
`
< script type = "text/javascript" >
$(document).ready(function() {
Dropzone.options.myAwesomeDropzone = {
autoProcessQueue: false,
parallelUploads: 1,
maxFiles: 1,
maxFilesize: 2000,
paramName: "test,123",
acceptedFiles: ".zip",
// Dropzone settings
init: function() {
var myDropzone = this;
this.element.querySelector("button[type=submit]").addEventListener("click", function(e) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
//Get All information to submit to server
var appName = "";
var typeOfApp = 1;
var commandLine = "";
var osType = 1;
});
this.on("sending", function(file, xhr, data) {
data.append("filetype", "avataruploadtype");
});
}
}
});
`
The way you have it set up, you're just submitting the form, so one easy approach is to just add inputs (or hidden fields) to the form and handle the multipart form data on the server.
See here for detail:
https://github.com/enyo/dropzone/wiki/Combine-normal-form-with-Dropzone

Categories

Resources