I'm having some trouble with using Dropzone.js within a standard html form. With the code I have, everything is working as it should, I can click the area to add an image, I can only add one image at a time, and the image is only uploaded when the submit button is pressed.
However, nothing is actually sent when submit is pressed. I know I need to manually process the queue, but this doesn't seem to be working at all. The rest of the form data is sent however, it's only the image which isn't.
I'm using the following simplified code. (Assume that this works other than no file being sent.)
HTML
<form action='upload.php' method="post" class="dropzone" id="mydz">
<input type='submit' name='submitimage' value='Save' style='float:left;'/>
JAVASCRIPT
Dropzone.options.mydz = {
autoProcessQueue: false,
maxFiles: 1,
init: function() {
var submitButton = document.querySelector("#submitimage");
mydz = this; // closure
submitButton.addEventListener("click", function() {
mydz.processQueue(); // Tell Dropzone to process all queued files.
});
this.on('addedfile', function(file){ if(this.files.length > 1) { this.removeFile(this.files[0]); } });
}
}
I've been trying to solve this all day now, and no amount of searching online has revealed anything useful to me. Can any of you help?? :)
Bingo!!! With some help from the author of the github post i linked to earlier, this issue has now been resolved!
The code I posted earlier works as it is, however inside the dropzone.js file, I added these two lines this.hiddenFileInput.setAttribute("name", _this.options.paramName);
$("form.dropzone").append(_this.hiddenFileInput);
after document.body.appendChild(_this.hiddenFileInput); and all is working as it should!
Related
I am trying to incorporate this code
var timeoutId;
$('textarea').keypress(function () {
if (timeoutId) clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
$.ajax({
url: '/savecomment',
data: { comment: $(this).val() }
});
}, 750);
});
from the tutorial here to implement auto-save in my web app. However, I am confused about two things.
Where exactly is the code being saved in this example? When I reload the page, the text I wrote is no longer there.
I tried to incorporate their example of this implementation into my code, but it did not work. The text box and the gray "no change" text above it appears fine, but this text does not change when I type. How could this be if I copied the HTML, CSS, and JS exactly as they are in the example?
Sorry for the elementary questions and thanks in advance.
The short answer is: Because you probably did not implement the server-side, e.g. the /savecomment endpoint for the $.ajax() call.
I would argue that this is quite an over-engineered example and could easily be solved with localStorage, could be as simple as this:
// check if we have something to restore on page-load
$(window).on('load', function() {
if ( localStorage.getItem('text') ) {
$('textarea').val(localStorage.getItem('text'));
}
});
$('textarea').on('input', function () {
localStorage.setItem('text', $(this).val());
// in a real browser you could verify it by
// uncommenting the following line, does not work
// in the sandbox this snippet runs in...
console.log('Saved text: ', localStorage.getItem('text'));
});
$('form').on('submit', function() {
alert('Actually save the text to the server via AJAX call');
// you should then clear the saved text after you successfully saved
// the content on the server
localStorage.removeItem('text');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="/savecomment">
<textarea name="sometext"></textarea>
<button type="submit">Save To Server</button>
</form>
then, when the user is actually done, have a "Save" button that can be clicked, that actually sends the finished text to the server.
Where is it saved?
It is saved in the app which runs in the /savecomment path. You need to implement this endpoint.
Is it sufficient to produce html, css and js?
Not sufficient. You need to implement the server app which saves the comment too.
I try to make a copy to clipboard button but I don't know why I can't make it.
I load my page with ajax so I call a function to add the zclip to my button when I mouseOver the button. But when I click on it, nothing is happening.
Here are my codes:
JS :
<script type="text/javascript" src="<?php echo JS_DIR?>zclip.min.js"></script>
<script type="text/javascript">
function mouseOver(){
$('.copyMails').each(function (k,n) {
console.log("test");
var copyMails = $(this);
$(this).zclip({
path: '<?php echo JS_DIR?>ZeroClipboard.swf',
copy: function () {
var val = $(copyMails).attr('data-clipboard-text');
return val;
},
afterCopy: function () { console.log($(copyMails).data('clipboard-text') + " was copied to clipboard"); }
});
});
}
</script>
And my button:
<button onmouseover="mouseOver()" data-clipboard-text="<?php echo implode(',', $emails); ?>" class="copyMails" title="Copier les adresses emails">
Copier les adresses emails
</button>
Thanks in advance.
I could not get this to work on my server, I downloaded the ZeroClipboard.swf from zclips website and would not work. I noticed that the swf on zclips website in not the one that they use for their examples. So I created a hyperlink to http://www.steamdev.com/zclip/js/ZeroClipboard.swf and clicked "save link as" compared the size to the one I had downloaded originally and it was bigger. So I put the new one from the link above onto my server and it worked perfectly.
I think if you downloaded the swf from zclips website directly from their download link, this is your problem as it was mine. Try saving my link as a file and then uploading it to your server.
There is an error in your example, at least with what's provided. Trying it in a fiddle prouces your mouseOver function being undefined.
I assume your intent is to copy the data to the clipboard when they click the button, and setup the clipboard when the mouseover event is triggered, correct? If that's the case, your best bet would be to create a single event for this, delegating it to your class of button(s). This way, it's not continuing to configure the clipboard plugin, every time an element is hovered over, for all elements matching your selector.
Here's an example of the code, but I don't believe you can include the SWF path as an external resource within the fiddle so it's not fully functional. So I have put together a version of the code I feel is close. Please give it a try.
JSFiddle: http://jsfiddle.net/adx93ave/3/
$(function () {
$(document).on("mouseover", ".copyMails", function (evt) {
var $btn = $(this);
$btn.zclip({
path: 'http://www.steamdev.com/zclip/js/ZeroClipboard.swf',
copy: $btn.data("clipboard-text"),
afterCopy: function () {
console.log($btn.data('clipboard-text') + " was copied to clipboard");
}
});
});
});
I have using dropzone.js in mvc by following this tutorial for uploading images but after uploading the image the thumbnail image still showing and I need it to be removed after every time I upload an image.
I have tried to replace the generated HTML after uploading the image using jQuery but it not showing correctly as the first time I need to refresh the page to show correctly but I don't want to do that.
$("#ImageUpload").replaceWith('<form action="/Products/SaveUploadedFile" method="post" enctype="multipart/form-data" class="dropzone dz-clickable" id="dropzoneForm">'
+'<div class="fallback">'
+'<input name="file" type="file" multiple />'
+'<input type="submit" value="Upload" />'
+'</div>');
You can try this:
myDropzone.on("complete", function(file) {
myDropzone.removeFile(file);
});
More information here:
http://www.dropzonejs.com/#dropzone-methods
removeAllFiles() and removeFile() will trigger the server-side removal too, if you hooked Dropzone to remove files as well.
The solution to clear it only client-side, remove the file preview, and if you had a blank state message, remove the dz-started class to prevent the Dropzone CSS from hiding it:
$('.dropzone')[0].dropzone.files.forEach(function(file) {
file.previewElement.remove();
});
$('.dropzone').removeClass('dz-started');
Another option (similar to answer of Giraldi, but then when all files are completed):
myDropzone.on("queuecomplete", function () {
this.removeAllFiles();
});
it was actually an easy thing to do but some time it go hard so i just delete the dropzone generated code using jquery and add a button with 'id = btnCreate' then
$('#btnCreate').click(function () {
$('div.dz-success').remove();
});
and when i upload the thumbnail image removed after i click the button
Just an fyi...
The method removeAllFiles is not necessarily the prime choice. Which is the same as removeFile(file).
I have an event handler for dropZone's removedfile event... I'm using it to send a server message to delete the respective file from the server (should a user delete the thumbnail after it's been uploaded). Using the method removeAllFiles (as well as the individualized removeFile(file)) fires the event removedfile which deletes the uploaded images in addition to clearing the thumbnails.
So one could add some finessing around this but in the reality of it the method as mentioned in the primary answer on this thread is not correct.
Looking through the api for Dropzone I am not seeing an API call to simply reset or clear the thumbnails... The method disable() will clear the stored file names and what not but does not clear the thumbnails... Seems dropzoneJS is actually missing a critical API call to be honest.
My work around is to manually reset the containing div for dropzone:
document.getElementById("divNameWhereDropzoneClassIs").innerHTML = ""
This clears the thumbnails without firing off the event removedfile which is supposed to be used for deleting an image from the server...
docsDropzone.on('complete', function (response)
{
$(".dz-preview").remove();
});
Above works for me
try this on your library dropzone dropzone.js; but set time out to auto close 2500
success: function(file) {
if (file.previewElement) {
return file.previewElement.classList.add("dz-success"),
$(function(){
setTimeout(function(){
$('.dz-success').fadeOut('slow');
},2500);
});
}
},
It is very simple if you listen complete event in your dropzone options:
const dropZoneOptions = {
url: ...,
// complete event
complete: function(file) {
setTimeout(() => {
this.removeFile(file); // right here after 3 seconds you can clear
}, 3000);
},
}
Another way of clear those thumbnails
Dropzone.prototype.removeThumbnail = function () {
$(".dz-preview").fadeOut('slow');
$(".dz-preview:hidden").remove();
};
then you call it like this:
{your_dropzone}.removeThumbnail();
I have a page which has a droppable element a1, as well as a specific element a2 which is sortable. Files dropped into a1 are read and deposited into a sortable list in a2. The upload and sortable scripts are not included in my code below as they are not relevant to the issue.
The problem is that if any file is dropped anywhere into other than a1, the browser will attempt to open the file for display in the browser. This is quite evident with image files..
I have tried to disable everything but a1 with the following code, but this still does not appear to have worked, I'm still getting the unwanted redirect...
I've Googled my butt off here, but it seems there's a lot about adding drag and drop, but very little with respect to preventing drag and drop...
Can someone please tell me what I am doing wrong here with the following code?
<div id="a1"></div>
<div id="a2"></div>
<script>
drop = $("not(#a1)");
drop.droppable("option",{disabled:true, tolerance:"pointer"});
drop.droppable("disable");
drop.on("drop",function(e){
e.preventDefault();
}
</script>
Many thanks in advance!
I created a simple JsFiddle to make it work. Basically you can cancel the event with a handler on the document itself, without worrying about where the file was dropped:
$("#a1").on('drop', function() {
// your logic here
alert('dropped on a1!');
});
$(document).on('drop dragover', function(e) {
e.preventDefault();
});
If you are using an older version of jQuery, you might have to replace the on function with live.
You have used wrong jQuery selector for not.
Try this
drop = $("div").not("#a1");
After enough tinkering I managed to come up with a more suitable solution...
Seeing I'm only really focusing on the prevention of files being dropped into sortable area, I decided to focus on determining the nature of the item being dropped...
drop = $(".all-slides");
drop.on('dragover', function(e){
e.preventDefault();
});
drop.on('dragenter', function(e){
e.preventDefault();
});
drop.on('drop', function(e){
e.preventDefault();
dt = e.originalEvent.dataTransfer;
if(dt.types != null && (dt.types.indexOf ? dt.types.indexOf('Files') != -1 : dt.types.contains('application/x-moz-file'))) {
alert('You cannot upload images here. \nIf you wish to upload files, \nclick on the "Upload Images" button.');
}
});
Put simply, the drop event listens for any possibility of data transfer, and if there is no data transfer possible, we know it's a DOM element... Otherwise we know it's a file, and we throw the alert...
I am trying to pop up a confirmation modal when the user presses the delete button on the edit form. The modal pops up fine, but when jQuery should be submitting the form, it's not doing anything. I have delete as a type="button", because when it is of type submit the modal function does not hold up the process and it just deletes the user right away.
The HTML ...
-- EDIT --
(I added the <form> tags)
<form action="/admin/edit-user" enctype="application/x-www-form-urlencoded" method="post" name="edit_user_form" id="edit_user_form">
...
<p><input type="submit" value="Save" name="submit" id="submit"/></p>
<p><input type="submit" value="Cancel" name="cancel" id="cancel"/></p>
<p><input type="button" value="Delete User" name="delete_btn" id="delete_btn" onclick="confirmDeleteUser();"/></p>
...
</form>
...
<div id="dialog-modal" title="Confirm Delete User">
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 0 0;"></span> Are you sure you wish to delete this user?</p>
<p>To continue editing, click cancel.</p>
</div>
The Javascript:
function confirmDeleteUser()
{
$('#dialog-modal').dialog({
autoOpen: false,
width: 400,
modal: true,
resizable: false,
buttons: {
"Cancel": function() {
$(this).dialog("close");
return false;
},
"Delete User": function() {
var self = $(this);
var form = $('#edit_user_form');
tmpElm = $('<input type="hidden" />');
tmpElm.attr('name', 'delete');
tmpElm.attr('id', 'delete');
tmpElm.val(true);
tmpElm.appendTo(form);
form.submit();
return true;
}
}
});
$('#dialog-modal').dialog('open');
}
When I inspect the source, I'm seeing that the code is properly appending the new hidden element, but the submit just doesn't seem to want to fire. What step am I missing?
Try it a different way.
HTML
Your html has the following: onclick="confirmDeleteUser();"
Why? jQuery is supposed to make this easier for you, not harder.
Your HTML should be pure and not calling functions (with the exception of ultra-extreme circumstances you are very unlikely to encounter). Why not use the jQuery library to bind the event to the element, rather than mix javascript function calls into your HTML? You should be doing something like this in the <script> tags, after a document ready statement.
$("#delete_btn").click(function(e){
/*Code that runs on click of the "delete_btn" ID tag*/
});
If you're unfamiliar with jQuery selectors and events then start reading here.
You can find all the events here.
You can find all the selectors here
The other reason you should do this is in the event the document isn't correctly/fully loaded in order to prevent it from breaking on your users.
CSS
You've also done this: style="float:left; margin:0 7px 0 0;" in an HTML tag? That's evil, dude. Just evil. How am I going to maintain this code in five months?
Instead, use CSS.
In your tags, or CSS file, you need an entry such as:
.dialogAdjust {
float: left;
margin: 0 7px 0 0;
}
Then in your HTML you would say:
<span class="ui-icon ui-icon-alert dialogAdjust"></span>
And now you can tweak the thing to your heart's content. It's better if you can make the class on the dialog div, rather than individual HTML elements, and in this case you absolutely can.
JavaScript
Hokay, so, here's your function:
function confirmDeleteUser()
{
$('#dialog-modal').dialog({
autoOpen: false,
width: 400,
modal: true,
resizable: false,
buttons: {
"Cancel": function() {
$(this).dialog("close");
return false;
},
"Delete User": function() {
var self = $(this);
var form = $('#edit_user_form');
tmpElm = $('<input type="hidden" />');
tmpElm.prop('name', 'delete');
tmpElm.prop('id', 'delete');
tmpElm.val(true);
tmpElm.appendTo(form);
form.submit();
return true;
}
}
});
$('#dialog-modal').dialog('open');
}
What's going on here? First step, you should try and use a tool to measure code quality. Two popular ones are JSHint and JSLint. You don't need to follow things they say like it's the only way to write your code, but it's immensely helpful in finding bugs due to small mistakes. I like JSHint, so we're going to run it through that.
And here's the output:
Errors:
Line 17 tmpElm = $('<input type="hidden" />');
'tmpElm' is not defined.
Line 18 tmpElm.attr('name', 'delete');
'tmpElm' is not defined.
Line 19 tmpElm.attr('id', 'delete');
'tmpElm' is not defined.
Line 20 tmpElm.val(true);
'tmpElm' is not defined.
Line 21 tmpElm.appendTo(form);
'tmpElm' is not defined.
Oops. Looks like you've got an undefined variable in there, meaning it's now global. Global variables are bad, they break scope and can make your code function in strange ways.
We need to fix that. You should always declare local variables in local scope. That means putting a var tempElm; at the top of the "Delete User" function.
Do away with that function wrapper, you won't need it. Your code should create the dialog object and code when the document is done loading, and open the dialog when it's clicked. What is happening in your original code both creating the dialog and opening it every time you click that button. What's the problem with that? You keep creating the object, even though it's created. You're creating the same object again and again and again. In this implementation, you won't notice it, but your design will carry over to places it will unless you take notice of this now.
So, what does that look like? In your <head> tag you should see something like this:
<script>
/*
This makes all the code inside
run when the window is done loading,
not before, which may cause issues.
*/
$(window).load(function(){
/*
This sets up the dialog
as you've described before
*/
$('#dialog-modal').dialog({
autoOpen: false,
width: 400,
modal: true,
resizable: false,
buttons: {
"Cancel": function() {
$(this).dialog("close");
return false;
},
"Delete User": function() {
var self = $(this);
var form = $('#edit_user_form');
//We've added the var infront of tepElem
var tmpElm = $('<input type="hidden" />');
tmpElm.prop('name', 'delete');
tmpElm.prop('id', 'delete');
tmpElm.val(true);
tmpElm.appendTo(form);
form.submit();
return true;
}
}
});
/*
This is the part where I talked
about selectors and events in the HTML
*/
$("#delete_btn").click(function(e){
$('#dialog-modal').dialog('open');
});
});
</script>
When asking for help, use a tool like jsFiddle to post JavaScript in to make it easier for other people to help you.
Here's a jsFiddle of the revisions we've made so far. Spend a bit of time learning how to use it if you're doing a lot of work in JavaScript and want to test something really quickly.
Here's why I wanted you to learn jsFiddle:
You didn't give us enough code to work with successfully, thus leading to me writing this huge post about code quality and how to ask questions, doubly so when you post a bounty.
If you want help, don't make people work really hard for it. You won't get good help unless someone is totally insane.
jsFiddle requires you post actual working code (or non-working code) that lets us see if there's a problem with form.submit(), such as any strange attributes or properties on the form element, or any number of other issues that could be kicking around that you excluded.
So let's look at what's breaking your "Delete User" function.
function() {
var self = $(this);
var form = $('#edit_user_form');
tmpElm = $('<input type="hidden" />');
tmpElm.prop('name', 'delete');
tmpElm.prop('id', 'delete');
tmpElm.val(true);
tmpElm.appendTo(form);
form.submit();
return true;
}
Why have you declared self? You never use it once. Lets get rid of that.
You could use something called chaining, it's really up to you. Some people hate it.
You append a whole new input to the form for something that looks like a choice, I'm not sure this is wise. I'd suggest changing the value of a normal input, or using another pattern, this could lead to a lot of issues, but for the sake of the question I'll imagine it's done for all the right reasons. Be careful however, if someone double clicks submit, that input's in there two times.
form is a word reserved by used in the DOM, you should avoid using that one to avoid confusion between your variable and the DOM API.
Which form submission button are we clicking here? You have a lot, and jQuery isn't going to guess and hope for the best.
How forms should look:
The w3 explains what forms are and the purpose of things.
Key points:
Names are paired with values
The submit button clicked is sent, the submit buttons not clicked are not.
The DOM is can be navigated based on NAME and ID attributes
Something weird is going on in your form.
Here's a form that javascript understands how to submit:
http://jsfiddle.net/YS8uW/2/
Here's javascript attempting to submit your form (stripped down to bare-bones):
http://jsfiddle.net/LfDXh/
What's different here?
You have IDs all over the place.
You use keywords for names
Lets look at something you've done, given an ID of submit to something:
http://jsfiddle.net/fdLfC/
And what happens when we don't use that as an ID?
http://jsfiddle.net/fdLfC/1/
Ahh. So that's weird.
It's like giving it an id of submit won't let you call submit. A proper explanation is, you've re-written it because the dom did it when you assigned that ID and Name, it's trying to call the element.
You can see this if you open up a debugger or something, it gives you an alert to the effect of:
TypeError: Property 'submit' of object # is not a function
Keep away from using keywords to mean something else and you won't fall into these weird traps.
A big thank you to #MattMcDonald for linking me to this resource, which explains how to deal with, and why, NAME and ID attributes over-write the built-in HTML DOM methods.
Do the other stuff I said too. Disclaimer: Everyone's going to wage war on me saying it's not absolute that you should be doing all those things, I agree, but I think this post is long enough, and we'll all agree that doing these things is a step forward in code quality, not backwards. It's up to you at the end, but try avoiding mixing things together into a huge messy pot. Think about the execution of your code and how it's happening also.
If you are sure it appends the hidden input, then the problem must be in using duplicate ID.
The button and the hidden input have the same ID. Make them different and try again.
Dont ask me the reason why it worked, all i can tell you is after doing this and that and tearing each part of your code, finally i made it work. click below link to see the demo
http://jsfiddle.net/praveen_prasad/KaK5A/4/
The changes i made are: removed id and name attributes from submit buttons from form
Example:
<input type="submit" value="Save" name="submit" id="submit"/>
changed above to below
<input type="submit" value="Save" />
Note For JsFiddle Demo: when you will click delete user on modal, form will submit. jsfiddle will say "Error 404", as it wont find the link you are posting your form. Open firebug and see that its actually posting to correct url.
"Delete User": function() {
var self = $(this);
var form = $('#edit_user_form');
tmpElm = $('<input type="hidden" />');
tmpElm.attr('name', 'delete');
tmpElm.attr('id', 'delete');
tmpElm.val(true); // HERE ----------------
tmpElm.appendTo(form);
form.submit();
return true;
}
At the designated location, shouldn't it be :
tmpElm.value(true);
or
tmpElm.attr('value', 'true');
I find it less confusing to handle my form submits upon confirms via jQuery ajax with serialized form values. It has the added benefit of avoiding unwanted form submits from buttons inside the <form> tags. So, it would look something like this:
<form id="edit_user_form">
...
<button id="submit_btn">Submit</button><br />
<button id="cancel_btn">Cancel</button><br />
<button id="delete_btn">Delete</button>
...
</form>
And then the javascript:
$('#delete_btn').click(function() {
$('#dialog-modal').dialog({
autoOpen: false,
width: 400,
modal: true,
resizable: false,
buttons: {
"Cancel": function() {
$(this).dialog("close");
return false;
},
"Delete User": function() {
$.ajax({
url: "/admin/edit-user",
type: "POST",
data: $('#edit_user_form).serialize(),
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("An error has occurred: " + errorThrown);
},
success: function(){
//Notify of success, redirect, etc.
}
});
}
}
});
});
So, it still submits via a POST. It now can happen asynchronously (or not) You can "do things" on success without changing the page, or alternatively redirect as you might need. I use a "dispatcher" page to submit to my object oriented framework, which then returns the output back to the PHP dispatcher to be json_encoded and echoed as a string for the AJAX call to use on success. Using this pattern, I only have to have one page that spits out plain text and the rest can reside in my OO Classes, which can't be called directly by ajax without doing some serious clooging (by using xajax)