files upload at form submit button with Plupload - javascript

I am using the Latest version of Plupload (2.1) - UI widget
when i click upload files, it uploads all files correctly.
but when i try to upload files with my Form submit button. it doesn't work. it just showing a little bit uploading of files and then eventually submit the forms without completing the file upload.
here is my code :
jj = jQuery.noConflict();
jj(function() {
jj("#flash_uploader_other").plupload({
runtimes: "html5,flash,silverlight,html4",
url: "/external/uploader-new/upload.php",
max_file_size: "10mb",
chunk_size: "1mb",
unique_names: true,
filters: [
{
title: "jpg,xls,csv,doc,pdf,docx,xlsx",
extensions: "jpg,xls,csv,doc,pdf,docx,xlsx"
}
],
flash_swf_url: "/external/uploader-new/js/Moxie.swf",
silverlight_xap_url: "/external/uploader-new/js/Moxie.xap"
});
// Handle the case when form was submitted before uploading has finished
jj("form").submit(function(e) {
// Files in queue upload them first
if (jj("#flash_uploader_other").plupload("getFiles").length > 0) {
// When all files are uploaded submit form
jj("#flash_uploader_other").on("complete", function() {
jj("form").submit();
});
jj("#flash_uploader_other").plupload("start");
}
});
});
Please help!!
Thanks
its working now
I replaced the following code
jj("form").submit(function(e) {
// Files in queue upload them first
if (jj("#flash_uploader_other").plupload("getFiles").length > 0) {
// When all files are uploaded submit form
jj("#flash_uploader_other").on("complete", function() {
jj("form").submit();
});
jj("#flash_uploader_other").plupload("start");
}
});
With this code :
jj("form").submit(function(e) {
var uploader = jj("#flash_uploader_other").plupload("getUploader");
// Validate number of uploaded files
if (uploader.total.uploaded == 0) {
// Files in queue upload them first
if (uploader.files.length > 0) {
// When all files are uploaded submit form
uploader.bind("UploadProgress", function() {
jj("#flash_uploader_other").on("complete", function() {
jj("form").submit();
});
});
jj("#flash_uploader_other").plupload("start");
} else {
jj("form").submit();
}
//alert('You must at least upload one file.');
e.preventDefault();
}
});

Related

jQuery Drag-and-Drop + click Image Upload

I would like to have a simple drop zone to upload image via AJAX and jQuery. I have found some plugins but they are way too customized for what's needed, and I cannot get any of them working properly.
I also would like the drop zone to be clickable, in order to manually choose a file from the OS file dialog.
I found this script, that works fine but where the drop zone is not clickable:
// ---------------------------- drop zone to upload image : '#dropfile'
$(document).on('dragenter', '#dropfile', function() {
return false;
});
$(document).on('dragover', '#dropfile', function(e){
e.preventDefault();
e.stopPropagation();
return false;
});
$(document).on('dragleave', '#dropfile', function(e) {
e.preventDefault();
e.stopPropagation();
return false;
});
$(document).on('drop', '#dropfile', function(e) {
if(e.originalEvent.dataTransfer){
if(e.originalEvent.dataTransfer.files.length) {
// Stop the propagation of the event
e.preventDefault();
e.stopPropagation();
// Main function to upload
upload(e.originalEvent.dataTransfer.files);
}
}
return false;
});
function upload(files) {
var f = files[0] ;
// Only process image files.
if (!f.type.match('image/jpeg')) {
alert(‘The file must be a jpeg image’) ;
return false ;
}
var reader = new FileReader();
// When the image is loaded, run handleReaderLoad function
reader.onload = handleReaderLoad;
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
function handleReaderLoad(evt) {
var pic = {};
pic.file = evt.target.result.split(',')[1];
var str = jQuery.param(pic);
$.ajax({
type: 'POST',
url: ‘url_to_php_script.php’,
data: str,
success: function(data) {
//do_something(data) ;
}
});
}
So I added an invisible file type input, but image data seems to be sent twice. I suppose it's due a bad event propagation with the original drop zone:
// ---------------------------- clickable drop zone with invisible file input '#inputFile'
$('#dropfile).on('click', function() {
$('input#inputFile').trigger('click');
$('input#inputFile').change(function(e) {
upload($('input#inputFile')[0].files);
});
});
I tried to add these lines but data is always sent twice:
$('#dropfile).on('click', function() {
$('input#inputFile').trigger('click');
$('input#inputFile').change(function(e) {
upload($('input#inputFile')[0].files);
// -------------- stop sending data twice ???
e.preventDefault();
e.stopPropagation();
return false;
});
});
I still don't know why data is sent twice but I found a better script here:
https://makitweb.com/drag-and-drop-file-upload-with-jquery-and-ajax/

When uploading files to dropzone from mobile, ONLY ONE file gets processed

I recently opened an issue on the Dropzone repo, but here is a summary of what happens.
If I go on the app on mobile to upload images and select Take a Photo or Video, only the last photo captured will be submitted to the server. If I take 3 photos, only the array submitted will only contain the LAST photo. The weird thing is, if I upload 3 photos from the library, it works perfectly.
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone("div#mydropzone",{
url: "<%= request.base_url %>/uploadfiles",
autoProcessQueue: false,
uploadMultiple: true,
addRemoveLinks:true,
parallelUploads:10,
init: function () {
$('#myForm').submit(function(e){
if (isFormValid()){
if(myDropzone.getQueuedFiles().length > 0){
e.preventDefault();
console.log(myDropzone.files)
document.getElementById('modal-main-text').innerText = myDropzone.files.length
myDropzone.processQueue();
}
}
else {
return false;
}
});
},
....other code...
One thing I know, is that before it hits the server... the console.log(myDropzone.files) dropzone does have the correct number of files.

Prevent parallel uploads in Jquery Form plugin

I am using Jquery Form Plugin to upload files using onchange event listener on the file upload input element to upload the file as soon as it is selected.
I want to allow only one file at a time to be uploaded and adding the rest in a queue to be uploaded once the existing upload is complete.
I tried making this happen by using a variable and setting it false in beforeSubmit and then switching it back to true once the upload is complete. However, it keeps turning true automatically.
Here is my Javascript code:
var allowUpload = true;
console.log('initial');
var options = {
beforeSubmit: beforeSubmit,
uploadProgress: OnProgress,
success: afterSuccess,
resetForm: true
};
$('#upload').change(function() {
console.log(allowUpload);
if(allowUpload)
{
console.log('onchange:' + allowUpload);
$('#uploadForm').ajaxSubmit(options);
}
return false;
});
function afterSuccess(data)
{
allowUpload = true;
console.log('aftersuccess' + allowUpload);
}
function beforeSubmit(data)
{
allowUpload = false;
console.log(allowUpload);
}

Non-ajax post using Dropzone.js

I'm wondering if there's any way to make Dropzone.js (http://dropzonejs.com) work with a standard browser POST instead of AJAX.
Some way to inject the inputs type=file in the DOM right before submit maybe?
No. You cannot manually set the value of a <input type='file'> for security reasons. When you use Javascript drag and drop features you're surpassing the file input altogether. Once a file is fetched from the user's computer the only way to submit the file to the server is via AJAX.
Workarounds: You could instead serialize the file or otherwise stringify it and append it to the form as a string, and then unserialize it on the server side.
var base64Image;
var reader = new FileReader();
reader.addEventListener("load", function () {
base64Image = reader.result;
// append the base64 encoded image to a form and submit
}, false);
reader.readAsDataURL(file);
Perhaps you're using dropzone.js because file inputs are ugly and hard to style? If that is the case, this Dropzone.js alternative may work for you. It allows you to create custom styled inputs that can be submitted with a form. It supports drag and drop too, but with drag and drop you cannot submit the form the way you want. Disclaimer: I am author of aforementioned library.
So, if I understood correctly you want to append some data (input=file) before submit your form which has dropzone activated, right?
If so, I had to do almost the same thing and I got it through listening events. If you just upload one file, you should listen to "sending" event, but if you want to enable multiple uploads you should listen to "sendingmultiple". Here is a piece of my code that I used to make this work:
Dropzone.options.myAwesomeForm = {
acceptedFiles: "image/*",
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 100,
init: function() {
var myDropzone = this;
[..some code..]
this.on("sendingmultiple", function(files, xhr, formData) {
var attaches = $("input[type=file]").filter(function (){
return this.files.length > 0;
});
var numAttaches = attaches.length;
if( numAttaches > 0 ) {
for(var i = 0; i < numAttaches; i++){
formData.append(attaches[i].name, attaches[i].files[0]);
$(attaches[i]).remove();
}
}
});
[..some more code..]
}
}
And that's it. I hope you find it helpful :)
PS: Sorry if there's any grammar mistakes but English is not my native language
For future visitors
I've added this to dropzone options:
addedfile: function (file) {
var _this = this,
attachmentsInputContainer = $('#attachment_images');
file.previewElement = Dropzone.createElement(this.options.previewTemplate);
file.previewTemplate = file.previewElement;
this.previewsContainer.appendChild(file.previewElement);
file.previewElement.querySelector("[data-dz-name]").textContent = file.name;
file.previewElement.querySelector("[data-dz-size]").innerHTML = this.filesize(file.size);
if (this.options.addRemoveLinks) {
file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\">" + this.options.dictRemoveFile + "</a>");
file._removeLink.addEventListener("click", function (e) {
e.preventDefault();
e.stopPropagation();
if (file.status === Dropzone.UPLOADING) {
return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function () {
return _this.removeFile(file);
});
} else {
if (_this.options.dictRemoveFileConfirmation) {
return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function () {
return _this.removeFile(file);
});
} else {
return _this.removeFile(file);
}
}
});
file.previewElement.appendChild(file._removeLink);
}
attachmentsInputContainer.find('input').remove();
attachmentsInputContainer.append(Dropzone.instances[0].hiddenFileInput).find('input').attr('name', 'files');
return this._updateMaxFilesReachedClass();
},
This is default implementation of dropzone's addedfile option with 3 insertions.
Declared variable attachmentsInputContainer. This is invisible block. Something like
<div id="attachment_images" style="display:none;"></div>
Here I store future input with selected images
Then in the end of function remove previously added input(if any) from block and add new
attachmentsInputContainer.find('input').remove();
attachmentsInputContainer.append(Dropzone.instances[0].hiddenFileInput).find('input').attr('name', 'files');
And now, when you send form via simple submit button, input[name="files"] with values will be send.
I've made this hack because I append files to post that maybe not created yet
This is what I used for my past projects,
function makeDroppable(element, callback) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('multiple', true);
input.style.display = 'none';
input.addEventListener('change', triggerCallback);
element.appendChild(input);
element.addEventListener('dragover', function(e) {
e.preventDefault();
e.stopPropagation();
element.classList.add('dragover');
});
element.addEventListener('dragleave', function(e) {
e.preventDefault();
e.stopPropagation();
element.classList.remove('dragover');
});
element.addEventListener('drop', function(e) {
e.preventDefault();
e.stopPropagation();
element.classList.remove('dragover');
triggerCallback(e);
});
element.addEventListener('click', function() {
input.value = null;
input.click();
});
function triggerCallback(e) {
var files;
if(e.dataTransfer) {
files = e.dataTransfer.files;
} else if(e.target) {
files = e.target.files;
}
callback.call(null, files);
}
}

FineUploader client event after all uploads are done

I implemented FineUploader and I would like to hook up my client script to an event after all files are uploaded. Is that possible?
My implementation follows. Just want to know if that's right direction.
function init() {
var uploader = new qq.FineUploader({
element: document.getElementById('button-selectfiles'),
request: {
endpoint: '/Up/UploadFile'
},
callbacks: {
onStatusChange: onFileUploadStatusChange
}
});
};
var uploads = 0;
function onFileUploadStatusChange(id, oldStatus, newStatus) {
console.log(newStatus);
if (newStatus === 'submitting') {
uploads++;
}
if (newStatus === 'upload successful' || newStatus === 'upload failed') {
uploads--;
}
if (uploads === 0) {
console.log('done');
}
}
onComplete - used for single upload file, if you are using a multiple files upload just use onAllComplete:
callbacks: {
onAllComplete: function() {
alert('done')
}
}
Your onFileUploadStatusChange function fails to check for cancelled files.
The way to verify if all files have been uploaded is via the API methods: getInProgress and getUploads. If we have 0 uploads in progress, and 0 failed uploads, then we can safely assume that all files have been uploaded. You may want to remove the check for failed uploads if you would still like to proceed if any upload has failed. We check for these conditions to be met during the onStatusChange and onComplete callbacks. The onStatusChange event should only check if the file has been cancelled because that might mean that all of the other files have completed, and thus the custom action can be completed.
Note: I've adapted my answer of 16989719 to work for non-jQuery Fine Uploader.
function init() {
var uploader;
function check_done() {
// Alert the user when all uploads are completed.
// You probably want to execute a different action though.
if (allUploadsCompleted() === true) {
window.alert('All files uploaded');
}
}
function allUploadsCompleted() {
// If and only if all of Fine Uploader's uploads are in a state of
// completion will this function fire the provided callback.
// If there are 0 uploads in progress...
if (uploader.getInProgress() === 0) {
var failedUploads = uploader.getUploads({ status: qq.status.UPLOAD_FAILED });
// ... and none have failed
if (failedUploads.length === 0) {
// They all have completed.
return true;
}
}
return false;
}
uploader = new qq.FineUploader({
element: document.getElementById('button-selectfiles'),
request: {
endpoint: '/Up/UploadFile'
},
callbacks: {
onStatusChange: function (id, oldStatus, newStatus) {
// This will check to see if a file that has been cancelled
// would equate to all uploads being 'completed'.
if (newStatus === qq.status.CANCELLED) {
check_done();
}
},
onComplete: check_done
}
});
};

Categories