processQueue() is not working in multiple uploads - javascript

I use dropzone.js for uploading image. I use this code
init: function() {
var submitButton = document.querySelector("#submit-all")
myDropzone = this; // closure
submitButton.addEventListener("click", function() {
var e = document.getElementById("test");
var strUser = e.options[e.selectedIndex].value;
if (strUser == 0) {
alert("First name must be filled out");
return false;
}
else
{
myDropzone.processQueue(); // Tell Dropzone to process all queued files.
}
});
}
But My processQueue upload only two image.But if i using auto process then all file uploaded.
I am trying to use this in my processquee function
while (i < parallelUploads) {
if (!queuedFiles.length) {
return;
}
this.processFile(queuedFiles.shift());
i++;
}

Try to set options of your dropzone.js:
parallelUploads: 30,
uploadMultiple: true
in parallelUploads you can set a different value from 1 and higher.
Good day to you.

Related

How to check if there is an image added to the dropzone?

I have this sample:
link
CODE HTML:
<div class="dropzone dz-clickable" id="myDrop">
<div class="dz-default dz-message" data-dz-message="">
<span>Upload or drag patient photo here</span>
</div>
</div>
CODE JS:
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone("div#myDrop", {
addRemoveLinks: true,
url: "#",
maxFiles:1,
init: function() {
this.on("maxfilesexceeded", function(file) {
alert("You are not allowed to chose more than 1 file!");
this.removeFile(file);
});
}
});
var fileName = $('#profilePicture').val();
var mockFile = { name: fileName, size: 12345 };
myDropzone.options.addedfile.call(myDropzone, mockFile);
myDropzone.options.thumbnail.call(myDropzone, mockFile, "https://lh3.googleusercontent.com/-eubcS91wUNg/AAAAAAAAAAI/AAAAAAAAAL0/iE1Hduvbbqc/photo.jpg?sz=104");
What I want to do is to check if there is already a loaded image.
For example:
if(is an image loaded from the first?)
{
alert("you have already image, delete it first");
}else{
alert("you can upload image now");
}
Basically they do not want the user can put another picture if there is already loaded.
As you can see in my example, the first load an image ... if you want to load another one, allowed us (I do not want it).
Is there any way this can be restricted?
Thanks in advance!
DropZone provides the methods enable() and disable(), which you can use to control the usage of it.
You can use the drop or addedFile events to call this function:
init: function() {
this.on("addedFile", function(file) {
// do what you want with the added file
this.disable(); // disable the dropzone to prevent more files
});
}
Works for me , if the image is already uploaded in the dropzone , it does not allow me to add more .
this.on("addedfile", function (file) {
/*
Valid only in the dropzone . If a repetitive document shows ALERT and the previous item will disappear.(Sorry my English).
*/
if (this.files.length) {
var i, len, pre;
for (i = 0, len = this.files.length; i < len - 1; i++) {
if (this.files[i].name == file.name && this.files[i].size == file.size && this.files[i].lastModifiedDate.toString() == file.lastModifiedDate.toString()) {
alert("You have already image, delete it first")
return (pre = file.previewElement) != null ? pre.parentNode.removeChild(file.previewElement) : void 0;
}
}
}
});

Dropzone.js when removing a mock file created on page load, the default add files message shows

There is a previous unanswered question about this here but no code or answer was provided. I'm hoping providing some code you'll be able to help me out.
Removing any existing file from Dropzone shows dictDefaultMessage
When I load the page I'm adding mock files to the dropzone. When I click remove on one of those files, the default add image text displays in the dropzone even though there are still files present. How does dropzone keep track of the number of files in the drop zone. I've tried directly modifying the myDropzone.files.length property to match the number of mock files but it breaks the dropzone as I've said in the other question. Here is my code for dropzone.
var jsphotos = '#jsphotos';
var mockFiles = [];
Dropzone.autoDiscover = false;
var fileList = new Array;
var fileListCounter = 0;
var photoDropzone = new Dropzone('#photoDropzone', {
url: 'importphotos.cshtml',
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 5, // MB
method: 'post',
acceptedFiles: 'image/jpeg,image/pjpeg',
dictInvalidFileType: 'Files uploaded must be type .jpg or .jpeg',
init: function () {
this.on("addedfile", function (file) {
// remove size
file.previewElement.querySelector('.dz-size').innerHTML = '';
// add custom button
// Create the remove button
var removeButton = Dropzone.createElement('<i class="fa fa-times-circle-o fa-3x removeButton"></i>');
// Capture the Dropzone instance as closure.
var _this = this;
// Listen to the click event
removeButton.addEventListener("click", function (e) {
// Make sure the button click doesn't submit the form:
e.preventDefault();
e.stopPropagation();
// Remove the file preview.
_this.removeFile(file);
});
// Add the button to the file preview element.
file.previewElement.appendChild(removeButton);
});
this.on("success", function (file, serverFileName) {
file.previewElement.querySelector('.dz-filename').innerHTML = '<span data-dz-name>'+serverFileName+'</span>';
});
this.on("removedfile", function (file) {
//var rmvFile = "";
//for (f = 0; f < fileList.length; f++) {
// if (fileList[f].fileName == file.name) {
// rmvFile = fileList[f].serverFileName;
// fileListCounter--;
// }
//}
//if (rmvFile) {
// $.ajax({
// url: "deletephoto.cshtml",
// type: "POST",
// data: { "fileList": rmvFile }
// });
//}
});
}
});
$('#photoDropzone').sortable({
items: '.dz-preview',
cursor: 'move',
opacity: 0.5,
containment: "parent",
distance: 10,
tolerance: 'pointer',
sort: function (event, ui) {
var $target = $(event.target);
if (!/html|body/i.test($target.offsetParent()[0].tagName)) {
var top = event.pageY - $target.offsetParent().offset().top - (ui.helper.outerHeight(true) / 2);
ui.helper.css({ 'top': top + 'px' });
}
},
update: function (e, ui) {
// do what you want
}
});
if (jsphotos.length > 0) {
var tmpSplit = jsphotos.split(',');
for (i = 0; i < tmpSplit.length; i++) {
if (tmpSplit[i].length > 0) {
mockFiles.push(tmpSplit[i]);
}
}
}
for (i = 0; i < mockFiles.length; i++) {
// Create the mock file:
var mockFile = { name: mockFiles[i]};
// Call the default addedfile event handler
photoDropzone.emit("addedfile", mockFile);
photoDropzone.emit("success", mockFile, mockFile.name);
// And optionally show the thumbnail of the file:
//photoDropzone.emit("thumbnail", mockFile, '#Globals.tempUploadFolderURL' + mockFile.name);
// Or if the file on your server is not yet in the right
// size, you can let Dropzone download and resize it
// callback and crossOrigin are optional.
photoDropzone.createThumbnailFromUrl(mockFile, '#Globals.tempUploadFolderURL' + mockFile.name);
// Make sure that there is no progress bar, etc...
photoDropzone.emit("complete", mockFile);
// If you use the maxFiles option, make sure you adjust it to the
// correct amount:
//var existingFileCount = 1; // The number of files already uploaded
//Dropzone.options.maxFiles = myDropzone.options.maxFiles - existingFileCount;
}
//photoDropzone.files.length = mockFiles.length;
After attempting to code a solution that monitored the count manually and modified the value of the default text, I didn't want a hack to modify class names to 'fool' the dropzone into thinking there were files. So I added this
photoDropzone.files.push(mockFile);
just below
photoDropzone.emit("complete", mockFile);
and now dropzone knows how many files it has, and everything functions appropriately. Files pushed into the array do not get resubmitted, it's the same as adding the mock preview originally.

Enable copy and paste files in dropzone.js

I am using dropzone.js. I want to implement the "Copy & Paste" feature in it.
What I tried is:
Inside dropzone.js:
paste: function(e) {
Dropzone.prototype.emit("paste");
}
Dropzone.prototype.paste = function(e) {
var items, _ref;
if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) {
return;
}
this.emit("paste", e);
items = e.clipboardData.items;
if (items.length) {
return this._addFilesFromItems(items);
}
};
Page level script:
<script>
var dropZone = Dropzone.forElement('#dropzone1');
dropZone.paste();
</script>
The above is not calling paste:function(e){..}
How to rectify it?
If you don't want to use other JS libraries, you can integrate dropzone with a paste event fairly easily by retrieving the data as a file from the paste event:
// create dropzone however you wish
const myDropzone = new Dropzone("div#element", { url: "/path/to/upload"});
// add paste event listener to the page
document.onpaste = function(event){
const items = (event.clipboardData || event.originalEvent.clipboardData).items;
items.forEach((item) => {
if (item.kind === 'file') {
// adds the file to your dropzone instance
myDropzone.addFile(item.getAsFile())
}
})
}
This worked for me. It uses the FileReaderJS wrapper.
As I am not creating the dropzone programatically, I had to store it at runtime with the init() method.
See here for the FileReaderJS part.
var myDropzone;
function checkUploadFile(filename) {
//do some input checking here, if you want
return true;
}
Dropzone.options.FileDropUploadZone = {
paramName: "myDiv",
maxFilesize: 3, // MB
uploadMultiple: true,
addRemoveLinks: true,
acceptedFiles: 'image/*',
maxFiles: 10,
accept: function(file, done) {
if (!checkUploadFile(file.name)) {
done('Invalid file');
myDropzone.removeFile(file);
}
else { done(); }
},
init: function() {
myDropzone = this;
}
};
$(document).ready(function () {
FileReaderJS.setupClipboard(document.body, {
accept: {
'image/*': 'DataURL'
},
on: {
load: function(e, file) {
myDropzone.addFile(file);
}
}
});
});
var myDropzone = new Dropzone(".dropzone", { });
document.onpaste = function(event){
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
for (index in items) {
var item = items[index];
if (item.kind === 'file') {
// adds the file to your dropzone instance
myDropzone.addFile(item.getAsFile())
}
}
}
Just add this code. Do not declare URL because URL also declared in PHP or coding file, paste this code in view file (HTML, PHP, etc).

Jquery how clean formData object in my own upload plugin

I tried to create my own plugin for upload files via ajax.
If the page where there is the input file is reloaded after upload It seems to work good.
If the page where there is the input file is NOT reloaded after upload (because was reloaded only ajax content) There are problems with IE and Chrome because the files to upload are appended to previous just uploaded (with firefox is ok).
I tried to fix it by cleaning the input file after the first upload but in this way then with IE and Chrome I can no longer upload other files.
MY FIX
complete: function () {
defaults.onFinish.call(this);
// If page where is the input file not reloaded
// after upload files IE and Chrome not working
$this.replaceWith($this.val('').clone(true));
$this.val('');
}
In truth I would clean the formData object after every upload but I haven't been able to do it
MY PLUGIN
;(function ($, window, document, undefined) {
// Function-level strict mode syntax
'use strict';
$.fn.ajaxUpload = function(options) {
var defaults = {
num_files : 0,
max_files : 2,
max_concurrent : 10,
max_filesize : 1024 * 4096,
php_max_size : 1024 * 8192,
allowed_types : ['jpeg','jpg'],
ajax_url : 'action.php',
var_name : 'file',
extra_fields : {},
onFinish : function() {}
};
var options = $.extend(defaults, options);
return this.each(function() {
var $this = $(this);
$this.on('change', function() {
var files = $this[0].files;
var len = files.length;
var items = 0;
var diff_files = parseInt(defaults.max_files - defaults.num_files - len);
if(diff_files < 0) {
return false;
}
if(!maxUploadFiles(len, defaults.max_concurrent)) {
return false;
}
var formdata = new FormData();
jQuery.each(files, function(i, file) {
if(!isOverSized(file, defaults.max_filesize)) {
return false;
}
if(!isAllowedTypes(file, defaults.allowed_types)) {
return false;
}
if(!totalFilesSize(file, defaults.php_max_size)) {
return false;
}
formdata.append(defaults.var_name + '['+i+']', file);
items++;
});
// Append extra data to formdata
$.each(defaults.extra_fields, function(name, value) {
formdata.append(name, value);
});
// Check that files have passed all test
if (len != items) { return false; }
$.ajax({
url: defaults.ajax_url,
data: formdata,
cache: false,
contentType: false,
processData: false,
type: 'POST',
beforeSend: function () {
},
success: function(data) {
totalSize = 0;
},
complete: function () {
defaults.onFinish.call(this);
// If page where is the input file not reloaded
// after upload files IE and Chrome not working
//$this.replaceWith($this.val('').clone(true));
//$this.val('');
}
});
});
});
};
var totalSize = 0;
function totalFilesSize(file, php_max_size) {
totalSize += file.size;
if(totalSize > php_max_size) {
totalSize = 0;
return false;
}
return true;
}
function maxUploadFiles(len, max_concurrent) {
if(len > max_concurrent) {
return false;
}
return true;
}
function isAllowedTypes(file, allowed_types) {
var ext = file.name.split('.').pop().toLowerCase();
if(jQuery.inArray(ext, allowed_types) < 0) {
return false;
}
return true;
}
function isOverSized(file, max_filesize) {
if(file.size > max_filesize) {
return false;
}
return true;
}
})(jQuery, window, document);
According to you that changes should I do to solve my problem?
Thank you
EDIT
I add this line on complete, and It seems to work
$this.val('');
$this.wrap('<form>').parent('form').trigger('reset');
$this.unwrap();
$this.replaceWith($this.clone());
The problem with your plugin is that you keep a reference to the original input with $this and then tried to replace it with a clone. Because you are cloning is better to get a new reference each time so you should unbind and bind .
(function ($, window, document, undefined) {
// Function-level strict mode syntax
'use strict';
$.fn.ajaxUpload = function (options) {
var defaults = {
num_files: 0,
max_files: 2,
max_concurrent: 10,
max_filesize: 1024 * 4096,
php_max_size: 1024 * 8192,
allowed_types: ['jpeg', 'jpg'],
ajax_url: 'action.php',
var_name: 'file',
extra_fields: {},
onFinish: function () {}
};
var options = $.extend(defaults, options);
var bindInput = function (elem) {
var element = $(elem),
bindFunc = function (evt) {
var files = evt.currentTarget.files;
var len = files.length;
var items = 0;
var diff_files = parseInt(defaults.max_files - defaults.num_files - len);
if (diff_files < 0) {
return false;
}
if (!maxUploadFiles(len, defaults.max_concurrent)) {
return false;
}
var formdata = new FormData();
jQuery.each(files, function (i, file) {
if (!isOverSized(file, defaults.max_filesize)) {
return false;
}
if (!isAllowedTypes(file, defaults.allowed_types)) {
return false;
}
if (!totalFilesSize(file, defaults.php_max_size)) {
return false;
}
formdata.append(defaults.var_name + '[' + i + ']', file);
items++;
});
// Append extra data to formdata
$.each(defaults.extra_fields, function (name, value) {
formdata.append(name, value);
});
// Check that files have passed all test
if (len != items) {
return false;
}
$.ajax({
url: defaults.ajax_url,
data: formdata,
cache: false,
contentType: false,
processData: false,
type: 'POST',
beforeSend: function () {},
success: function (data) {
totalSize = 0;
},
complete: function () {
defaults.onFinish.call(this);
var previous = $(evt.currentTarget);
previous.off('change', bindFunc);
var newElem = previous.val('').clone(true)
previous.replaceWith(newElem);
bindInput(newElem);
}
});
};
element.on('change', bindFunc);
};
return this.each(function () {
bindInput(this)
});
};
var totalSize = 0;
function totalFilesSize(file, php_max_size) {
totalSize += file.size;
if (totalSize > php_max_size) {
totalSize = 0;
return false;
}
return true;
}
function maxUploadFiles(len, max_concurrent) {
if (len > max_concurrent) {
return false;
}
return true;
}
function isAllowedTypes(file, allowed_types) {
var ext = file.name.split('.').pop().toLowerCase();
if (jQuery.inArray(ext, allowed_types) < 0) {
return false;
}
return true;
}
function isOverSized(file, max_filesize) {
if (file.size > max_filesize) {
return false;
}
return true;
}
})(jQuery, window, document);
{Edit}
The problem that originate your question is the nightmare of every file upload plugin developer. As you are developing a plugin you should be aware that the input tag may contain other styles and event handlers set by the consumer of the plugin that you must preserve or you will break existing functionality.
For security reasons the value of the input type file cannot be changed with javascript. There are a lot of answers in SO about that. Search for clear+input+file and see for yourself, the most remarkable is this Clearing <input type='file' /> using jQuery
As you can see there are basically two choices:
Clone the input and call val('') before cloning (calling jQuery $(input).val('') is not the same that calling input.value = '').
The problems of this approach is for example that in IE this event is called twice when clearing the file input and you must be carefull about releasing memory and references to the input being replaced while preserving current styles and event handlers that were not set by your plugin
The second is better but has issues as well. Wrap your input in a form tag and call the form's reset method.
input.wrap('<form>').parent('form').trigger('reset');
input.unwrap();
Check the docs about the sintax of the form tag and you will see the following quote
Note: It's strictly forbidden to nest a form inside another form. Doing so can behave in an unpredictable way that will depend on which browser the user is using.
The main reasoning behind that is that your plugin can be applied to an input tag that is already inside a form leaving you with invalid html so you must wrap the form call the reset method and remove this form right away. Also remember that forms may have visual styles applied to them breaking the user interface if you leave them around.
In the second alternative is easier to fix your code. Just change the complete callback like this. No cloning is needed in this case.
complete: function () {
defaults.onFinish.call(this);
$this.wrap('<form>').parent('form').trigger('reset');
$this.unwrap();
}
This changes should happen so fast that the users will not notice them. I tested with 1000 elements around and no visual glitches were visible.

Dropzone.js remove files after an event is fired

so heres my code:
Dropzone.options.myDropzone = {
// Prevents Dropzone from uploading dropped files immediately
autoProcessQueue: false,
init: function() {
var submitButton = document.querySelector("#submit-all")
myDropzone = this; // closure
submitButton.addEventListener("click", function() {
myDropzone.processQueue(); // Tell Dropzone to process all queued files.
myDropzone.removeAllFiles();
console.log("a");
});
// You might want to show the submit button only when
// files are dropped here:
this.on("addedfile", function() {
// Show submit button here and/or inform user to click it.
});
}
};
how can I add removeAllfiles after clicking the upload button. thanks
This should work:
Dropzone.options.myDropzone = {
autoProcessQueue: false,
init: function() {
var submitButton = document.querySelector("#submit-all")
myDropzone = this;
submitButton.addEventListener("click", function() {
myDropzone.processQueue();
});
// Execute when file uploads are complete
this.on("complete", function() {
// If all files have been uploaded
if (this.getQueuedFiles().length == 0 && this.getUploadingFiles().length == 0) {
var _this = this;
// Remove all files
_this.removeAllFiles();
}
});
}
};
By using this.on("complete", function() { //Code to be executed }); you are able to execute your code once the files have been uploaded. In your case, you can remove all of the files.

Categories

Resources