How do I change the default text in dropzone.js? - javascript

I am using dropzone.js to upload files. However, I'm having difficulty changing the default text.
I've tried instantiating the dropzone class:
$(document).ready(function(){
$(".foo").dropzone({ dictDefaultMessage: "hello" });
});
With this markup:
<div class="span4">
<form action="http://localhost/post" method="post" accept-charset="utf-8" id="drop3" class="foo" enctype="multipart/form-data"> </form>
</div>
<div class="span4">
<form action="http://localhost/post" method="post" accept-charset="utf-8" id="drop4" class="foo" enctype="multipart/form-data"> </form>
</div>
This certainly gives me the ability to upload files but the default text is blank.
I tested the following:
$(".foo").dropzone();
and I appear to get the same result - no default text. So.. how do I change the default text?

Add an element within your dropzone form as follows:
<div class="dz-message" data-dz-message><span>Your Custom Message</span></div>

You can change all default messages with this:
Dropzone.prototype.defaultOptions.dictDefaultMessage = "Drop files here to upload";
Dropzone.prototype.defaultOptions.dictFallbackMessage = "Your browser does not support drag'n'drop file uploads.";
Dropzone.prototype.defaultOptions.dictFallbackText = "Please use the fallback form below to upload your files like in the olden days.";
Dropzone.prototype.defaultOptions.dictFileTooBig = "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.";
Dropzone.prototype.defaultOptions.dictInvalidFileType = "You can't upload files of this type.";
Dropzone.prototype.defaultOptions.dictResponseError = "Server responded with {{statusCode}} code.";
Dropzone.prototype.defaultOptions.dictCancelUpload = "Cancel upload";
Dropzone.prototype.defaultOptions.dictCancelUploadConfirmation = "Are you sure you want to cancel this upload?";
Dropzone.prototype.defaultOptions.dictRemoveFile = "Remove file";
Dropzone.prototype.defaultOptions.dictMaxFilesExceeded = "You can not upload any more files.";

When creating the dropzone you can set the default message like this.
var dropzone = new Dropzone("form.dropzone", {
dictDefaultMessage: "Put your custom message here"
});
Then
$('div.dz-default.dz-message > span').show(); // Show message span
$('div.dz-default.dz-message').css({'opacity':1, 'background-image': 'none'});

First add an id to your form, say mydz, then add this js:
Dropzone.options.mydz = {
dictDefaultMessage: "your custom message"
};
The whole page (index.php in this case):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="dropzone.js"></script>
<link rel="stylesheet" type="text/css" href="./dropzone.css">
<title></title>
</head>
<body>
<form action="upload.php" class="dropzone" id="mydz"></form>
<script type="text/javascript">
Dropzone.options.mydz = {
dictDefaultMessage: "Put your custom message here"
};
</script>
</body>
</html>

this text is in dropzone's default config, You can overwrite like this:
Dropzone.prototype.defaultOptions.dictDefaultMessage = "Your text";

myDropzonePhotos = new Dropzone('#dropzone-test',
{
url : 'upload_usuario.php?id_usuario=' + id_usuario,
maxFiles : 1,
thumbnailWidth : 1200,
thumbnailHeight : 300,
dictDefaultMessage : 'Change the text here!',
init: function()
{
....

I fiddled with this for hours.
For some reason, these 3 things needed to be done:
My dropzone tags could not be on the same page I was using dropzone on. I had to reference them on the template page
The element you are turning into a dropzone has to have a class of 'dropzone'
You have to add the following to the top of the js file for the page i was working on.
Dropzone.autoDiscover = false;
To Initialize:
var myDropzone = new Dropzone("#id-upload-dropzone", {
url: "/home/Upload",
dictDefaultMessage: 'Drop image here (or click) to capture/upload'
});
Once I had all 3 in order, the dictDefaultMessage option worked.

For localizing Dropzone in Asp.Net Razor Pages I use the below method to avoid decoded chars :
Create HTML element for all messages
<!-- localization elements -->
<div class="modal" aria-hidden="true">
<span id="dictDefaultMessage">#_localizer["Drop files here or click to upload."]</span>
<span id="dictFallbackMessage">#_localizer["Your browser does not support drag'n'drop file uploads."]</span>
<span id="dictFallbackText">#_localizer["Please use the fallback form below to upload your files like in the olden days."]</span>
<span id="dictFileTooBig">#_localizer["File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB."]</span>
<span id="dictInvalidFileType">#_localizer["You can't upload files of this type."]</span>
<span id="dictResponseError">#_localizer["Server responded with {{statusCode}} code."]</span>
<span id="dictCancelUpload">#_localizer["Cancel upload"]</span>
<span id="dictCancelUploadConfirmation">#_localizer["Are you sure you want to cancel this upload?"]</span>
<span id="dictUploadCanceled">#_localizer["Upload canceled."]</span>
<span id="dictRemoveFile">#_localizer["Delete"]</span>
<span id="dictRemoveFileConfirmation">#_localizer["Are you sure you want to delete this file?"]</span>
<span id="dictMaxFilesExceeded">#_localizer["You can not upload any more files."]</span>
<span id="dictFileSizeUnits_TB">#_localizer["TB"]</span>
<span id="dictFileSizeUnits_GB">#_localizer["GB"]</span>
<span id="dictFileSizeUnits_MB">#_localizer["MB"]</span>
<span id="dictFileSizeUnits_KB">#_localizer["KB"]</span>
<span id="dictFileSizeUnits_b">#_localizer["b"]</span>
</div>
Then bind messages to Dropzone element:
<script>
// get elements for localization
with (Dropzone.prototype.defaultOptions) {
dictDefaultMessage = document.getElementById("dictDefaultMessage").innerText;
dictFallbackMessage = document.getElementById("dictFallbackMessage").innerText;
dictFallbackText = document.getElementById("dictFallbackText").innerText;
dictFileTooBig = document.getElementById("dictFileTooBig").innerText;
dictInvalidFileType = document.getElementById("dictInvalidFileType").innerText;
dictResponseError = document.getElementById("dictResponseError").innerText;
dictCancelUpload = document.getElementById("dictCancelUpload").innerText;
dictCancelUploadConfirmation = document.getElementById("dictCancelUploadConfirmation").innerText;
dictUploadCanceled = document.getElementById("dictUploadCanceled").innerText;
dictRemoveFile = document.getElementById("dictRemoveFile").innerText;
dictRemoveFileConfirmation = document.getElementById("dictRemoveFileConfirmation").innerText; // if this is null, the user will not be prompted when deleting file.
dictMaxFilesExceeded = document.getElementById("dictMaxFilesExceeded").innerText;
dictFileSizeUnits = {
tb: document.getElementById("dictFileSizeUnits_TB").innerText,
gb: document.getElementById("dictFileSizeUnits_GB").innerText,
mb: document.getElementById("dictFileSizeUnits_MB").innerText,
kb: document.getElementById("dictFileSizeUnits_KB").innerText,
b: document.getElementById("dictFileSizeUnits_b").innerText
};
};
</script>
for a complete drag-drop file upload sample using Dropzone see this GitHub repository : https://github.com/LazZiya/FileUpload

If you aren't adverse to JQuery, this will hide the default image:
$('form.dropzone').find('div.default.message').css('background-image','none');
and, this will show the default span which you can change to be whatever you want:
$('form.dropzone').find('div.default.message').find('span').show();
$('form.dropzone').find('div.default.message').find('span').empty();
$('form.dropzone').find('div.default.message').find('span').append('Drop files here or click here to upload an image.');

in the css of dropzone look for
.dropzone .dz-default.dz-message
in this class delete
background-image: url("../images/spritemap.png");
the next thing to do is search this class
.dropzone .dz-default.dz-message span {
display: none;
}
and change it to display:block

If you are creating Dropzones Programmatically then you have to set your options like below:
Dropzone.autoDiscover = false;
profilePicture = new Dropzone('#profile-picture', {
url: "/uploadPicture.php",
// if you are using laravel ..., you dont need to put csrf in meta tag
headers: {
'X-CSRF-TOKEN': "{{ csrf_token() }}"
},
dictDefaultMessage: "Your default message Will work 100%",
/other options
paramName: "profile_picture",
addRemoveLinks: true,
maxFilesize: 1,
maxFiles: 10,
dictRemoveFile: "Remove",
});
If you are using it like this, It wont work ...
let myDropzone = new Dropzone("#profile-picture", {
url: "/uploadPicture.php",
// if you are using laravel ..., you dont need to put csrf in meta tag
headers: {
'X-CSRF-TOKEN': "{{ csrf_token() }}"
},
});
myDropzone.options.profilePicture = {
dictDefaultMessage: "This message not gonna work",
paramName: "profile_picture",
};

Related

Ho can get values from Quill editor form for my php code? [duplicate]

I have what I think is a very common scenario. I would normally have this form:
<form method="post">
<textarea name="text"></textarea>
<input type="submit" value="Save" />
</form>
Then with PHP I would capture the data from the form ($_POST['text']) and I could use that in another variable.
Now, I'd like to use Quill so users have a nice rich text editor instead. Quill seems very well suited for this and the documentation is very detailed. However, for some reason I can not find how I can "post" the data to the form. There is one single sample page that sort of does what I want, but I am unable to fully implement this in my sample, and in the quick start guide this rather fundamental (to me) topic is not discussed, and I can not find this in the documentation either.
Is Quill supposed to be used like this? Am I overseeing something? Is there a recommended way to make this work?
This is what I currently have:
<!doctype html>
<html>
<head>
<title>Test</title>
<meta charset="UTF-8" />
<link href="https://cdn.quilljs.com/1.0.0/quill.snow.css" rel="stylesheet">
</head>
<body>
<form method="post">
<!-- Create the toolbar container -->
<div id="toolbar">
<button class="ql-bold">Bold</button>
<button class="ql-italic">Italic</button>
</div>
<form method="post">
<!-- Create the editor container -->
<div id="editor">
<p>Hello World!</p>
</div>
<input type="submit" value="Save" />
</form>
<!-- Include the Quill library -->
<script src="https://cdn.quilljs.com/1.0.0/quill.js"></script>
<!-- Initialize Quill editor -->
<script>
var editor = new Quill('#editor', {
modules: { toolbar: '#toolbar' },
theme: 'snow'
});
</script>
</body>
</html>
<form method="post" id="identifier">
<div id="quillArea"></div>
<textarea name="text" style="display:none" id="hiddenArea"></textarea>
<input type="submit" value="Save" />
</form>
If you give the form an identifier, then using jQuery you can do the following:
var quill = new Quill ({...}) //definition of the quill
$("#identifier").on("submit",function() {
$("#hiddenArea").val($("#quillArea").html());
})
Instead of the HTML you could use quill.getContents() to get the delta.
You can check related discussion about it https://github.com/quilljs/quill/issues/87
While this is not an ideal solution :
var myEditor = document.querySelector('#editor')
var html = myEditor.children[0].innerHTML
Here's the code I used to do this:
$(document).ready(function(){
$("#theform").on("submit", function () {
var hvalue = $('.ql-editor').html();
$(this).append("<textarea name='content' style='display:none'>"+hvalue+"</textarea>");
});
});
Basically, what it does is to add a hidden textarea to your form and copy the content of the "ql-editor" container (This is automatically made by Quill Editor in the container div) to it. The textarea will then be submitted with the form. You need to change the IDs used in the code to the id of your container tags.
I'm doing this:
var quill = new Quill('.quill-textarea', {
placeholder: 'Enter Detail',
theme: 'snow',
modules: {
toolbar: [
['bold', 'italic', 'underline', 'strike'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'indent': '-1'}, { 'indent': '+1' }]
]
}
});
quill.on('text-change', function(delta, oldDelta, source) {
console.log(quill.container.firstChild.innerHTML)
$('#detail').val(quill.container.firstChild.innerHTML);
});
Somewhere on the form:
<div class="quill-textarea"></div>
<textarea style="display: none" id="detail" name="detail"></textarea>
A solution I came up with was to make a wrapper class.
class QuillWrapper {
/**
* #param targetDivId { string } The id of the div the editor will be in.
* #param targetInputId { string } The id of the hidden input
* #param quillOptions { any } The options for quill
*/
constructor(targetDivId, targetInputId, quillOptions) {
//Validate target div existence
this.targetDiv = document.getElementById(targetDivId);
if (!this.targetDiv) throw "Target div id was invalid";
//Validate target input existence
this.targetInput = document.getElementById(targetInputId);
if (!this.targetInput) throw "Target input id was invalid";
//Init Quill
this.quill = new Quill("#" + targetDivId, quillOptions);
//Bind the two containers together by listening to the on-change event
this.quill.on('text-change',
() => {
this.targetInput.value = this.targetDiv.children[0].innerHTML;
});
}
}
Simply include the class somewhere on your page and then use the following to initilize it:
let scopeEditor = new QuillWrapper("ScopeEditor", "Scope", { theme: "snow" });
Your html would look roughly like this:
<div class="form-group">
<label asp-for="Scope" class="control-label col-md-2"></label>
<div id="ScopeEditor"></div>
<input type="hidden" asp-for="Scope" class="form-control" />
</div>
I know this problem has already been resolved, but I would like to add a little more information. To obtain the data present in Quill, You don't need jQuery, or a different trick. I recommend looking at this answer:
https://stackoverflow.com/a/42541886/2910546
I should also make a note here: The author's question was asked at least 2 years ago. So, today, I believe this is to be the most viable way to address the question.
For more information on Quill, with case study examples, and common questions with answers, please kindly visit the following link:
https://github.com/loagit/Quill-Examples-and-FAQ
this is what i use, all you have to do is to provide data-name attribute to your editor tag. this will create a hidden input as sibling to your editor tag and put the html contents inside. you can get other formats of your contents, i leaved unused variables if you need to know how to get them.
html:
<div class="field editor" data-name="experience"></div>
js:
let quill_element = document.querySelector('.editor')
let quill = new Quill(quill_element, {
modules: {
toolbar: '#toolbar'
},
placeholder: document.querySelector('.editor').getAttribute('data-placeholder'),
theme: 'bubble',
});
let hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = quill_element.getAttribute('data-name');
quill_element.parentElement.appendChild(hiddenInput);
quill.on('text-change', function () {
let justHtml = quill.root.innerHTML;
hiddenInput.value = justHtml;
// other formats if you like to use..
var delta = editor.getContents();
var text = editor.getText();
});
Solved here
How to save Quill.js values to Database Laravel 5.6
Add a hidden input :
<input type="hidden" name="body"/>
Js code :
var form = document.getElementById("FormId");
form.onsubmit = function() {
var name = document.querySelector('input[name=body]');
name.value = JSON.stringify(quill.getContents());
return true; // submit form
}
To set contents to quill do this :
quill.setContents({!! $post->body !!});
I found that prevoius solutions on the page also copied a lot of quiill markup html at the end of the field when copied to a hidden field.
The solution described on this page seems to recitfy that:
https://lucidar.me/en/rich-content-editor/how-to-get-html-content-from-quill-rich-editor/
Basically, access the pure HTML with:
var html = quil.root.innerHTML
document.getElementById("descriptionHidden").value = html;
Try this:
<!-- Include the Quill library -->
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
<!-- Initialize Quill editor -->
<script>
var quill = new Quill('#editor', {
modules: {
toolbar: [
['bold', 'italic'],
['link', 'blockquote', 'code-block', 'image'],
[{
list: 'ordered'
}, {
list: 'bullet'
}]
]
},
placeholder: 'Compose an epic...',
theme: 'snow'
});
$("#form").submit(function() {
$("#description").val(quill.getContents());
});
</script>
this solution works fine for me:
<script type="text/javascript">
$(document).ready(function(){
$("#emailForm").on("submit", function () {
var hvalue = $('.editor').text();
$(this).append("<textarea name='message' style='display:none'>"+hvalue+"</textarea>");
});
});
</script>
I solved this problem as follows.
In the element that will be the editor's container, I set a like attribute, data-input-name="something"
and after instantiating the editor I just made a simple code that assigns the internal value of the quill to hidden input
quill.on('text-change', function() {
const content = quill.root.innerHTML.trim();
const targetId = quill.container.dataset.inputName
document.querySelector(`#${targetId}`).setAttribute("value", content);
});
Checkout this repo, it might be helpful. It's easy to install.
https://github.com/tangien/quilljs-textarea
AutoInitialize Quilljs simply by adding the attribute data-quilljs to the textarea element and the rest the plugin will take care of it.
Thats it!
Link CSS:
<!-- CSS Implementing Plugins -->
<link rel="stylesheet" href="https://htmlstream.com/preview/front-v4.2/html/assets/css/vendor.min.css">
<link rel="stylesheet" href="https://htmlstream.com/preview/front-v4.2/html/assets/vendor/bootstrap-icons/font/bootstrap-icons.css">
<!-- CSS Front Template -->
<link rel="stylesheet" href="https://htmlstream.com/preview/front-v4.2/html/assets/css/theme.min.css?v=1.0">
Link JS:
<!-- JS Implementing Plugins -->
<script src="https://htmlstream.com/preview/front-v4.2/html/assets/js/vendor.min.js"></script>
<!-- JS Front -->
<script src="https://htmlstream.com/preview/front-v4.2/html/assets/js/theme.min.js"></script>
En mi html:
<form id="form-perfil" name="form-perfil" method="POST">
<!-- Form Group -->
<div class="row form-group">
<label class="col-sm-3 col-form-label input-label">BIO</label>
<div class="col-sm-9">
<!-- Quill -->
<div class="quill-custom">
<div
class="js-quill"
style="min-height: 15rem;"
data-hs-quill-options='{
"placeholder": "Type your message...",
"modules": {
"toolbar": [
["bold", "italic", "underline", "strike", "link", "image", "blockquote", "code", {"list": "bullet"}]
]
}
}'
>
Creative mind at Htmlstream
</div>
</div>
<!-- End Quill -->
<textarea name="text_quill" style="display: none;" id="text_quill"></textarea>
</div>
</div>
<!-- End Form Group -->
<button type="submit" class="mt-3 float-right btn btn-primary">Enviar formulario</button>
<!-- End Form Group -->
</form>
En mi JS:
// INITIALIZATION OF QUILLJS EDITOR
// =======================================================
var quill = $.HSCore.components.HSQuill.init('.js-quill');
// =======================================================
$("#form-perfil").on("submit", function (e) {
e.preventDefault(); //No se activará la acción predeterminada del evento
$("#text_quill").val($(".ql-editor").html());
var formData = new FormData($("#form-perfil")[0]);
$.ajax({
url: "ajax/pago_administrador.php",
type: "POST",
data: formData,
contentType: false,
processData: false,
success: function (datos) { },
});
});

Wordpress custom image upload

I need to use custom image field in wp plugin, everything works fine with upload/set function but have problem, when changing image:
Problem:
When i already have a image and need to replace i pick up new image from media library and submit, old one image stay visible so i have two images in view.
I asume that problem is with select function and append part, obviously i'm using wrong logic here, bellow are jquery+html of my code and screenshot of problem:
Problem(two images):
First one should replaced with new selection image (second image)
Two images screenshot
This is my code:
$('#btn-upload-image').on('click', function(e) {
e.preventDefault();
var button = $(this);
var figure = button.siblings("figure");
var custom_uploader = wp.media({
title: 'Insert image',
library: { type : 'image' },
button: { text: 'Use this image' },
id: 'library-' + (Math.random() * 10),
multiple: false
}).on('select', function() {
var attachment = custom_uploader.state().get('selection').first().toJSON();
figure.append( $('<img/>', { 'src': attachment.url }) );
inputImage.val(attachment.url);
inputImageId.val(attachment.id);
})
.open();
});
and html:
<div class="form-group">
<label>Image</label>
<figure></figure>
<button type="button" class="btn btn-primary" id="btn-upload-image">Upload Image</button>
<input type="hidden" name="image" id="input-image" />
<input type="hidden" name="image_id" id="input-image-id" />
</div>
Here's the problem:
figure.append( $('<img/>', { 'src': attachment.url }) );
append inserts content at the end of the target element, maintaining existing content in place. What you want in this case is to replace whatever is in there with new content (the new image), so:
figure.html( $('<img/>', { 'src': attachment.url }) );
html replaces any content that was in the targeted element(s) with the new one.
Hope that helps!

MultiValueDictKeyError when using DropzoneJS with Django

I'm currently making a profile picture feature for a website, I started using DropzoneJS but I'm having an issue submitting the file. The picture will drop into the zone fine, but it appears with an "X" over it, and when I hover over the picture I can see the MultiValueDictKeyError error. Which is the same error I get when I click the submit button without selecting a file. So I assume the issue is that the file isn't being submitted by the button? How do I do that?
HTML/JS:
<script type='text/javascript'>
Dropzone.options.myDropzone = {
init : function() {
var submitButton = document.querySelector("#submitBtn")
myDropzone = this;
submitButton.addEventListener("click", function() {
myDropzone.processQueue();
});
this.on("addedfile", function() {
document.getElementById('submitBtn').style.visibility = "visible";
});
this.on('addedfile', function(){
if (this.files[1]!=null){
this.removeFile(this.files[0]);
}
});
}
};
Dropzone.options.myAwesomeDropzone = {
accept: function(file, done) {
console.log("uploaded");
},
init: function() {
this.on("addedfile", function() {
if (this.files[1]!=null){
this.removeFile(this.files[0]);
//document.getElementById('submitBtn').style.visibility = "visible";
}
});
}
};
</script>
<!-- Modal -->
<div id="picModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close"></span>
<form action="{% url 'profile_test' %}" method='POST' enctype="multipart/form-data" class="dropzone" id="my-dropzone">{% csrf_token %}
<button id='submitBtn' type='submit' style='visibility: hidden;'> Submit </button>
<input id='submit-all' type='file' name='uploaded_image'/>
{{form}}
</form>
</div>
</div>
</body>
EDIT
I added autoProcessQueue: false, to myDropzone. I'm not getting the issue when I hover over the picture anymore. Instead now when I press submit it just takes me to the MultiValueDictKeyError error page
*EDIT 2**
views.py
def profile_test(request):
#going to use this view to display the profile page, and test alterations to it
form = ImageUploadForm(request.POST, request.FILES)
user = User.objects.get(id=request.user.id)
if request.method == "POST":
print 'valid'
user.userprofile.img = request.POST.get('uploaded_image', False)
user.userprofile.save()
return HttpResponseRedirect(reverse("profile_test"))
else:
print 'invalid'
form = ImageUploadForm()
return render(request, 'profile_test.html', {form:'form', user: 'user'})
I used to have user.userprofile.img = request.FILES["uploaded_image"] but changed it, it seemed to maek things better. Now the image will drop into the zone, and when I hover over it I won't see that error. But now when I submit it the dropzone disappears and the profile pic doesnt change.
I expect that img attribute is FileField. right?
user.userprofile.img = request.POST.get('uploaded_image', False)
please try this.
user.userprofile.img = request.FILES.get('uploaded_image')
# if you have multiple files to upload
user.userprofile.img = request.FILES.getlist('uploaded_image')

Select File. Submit. Cannot select file again

I have a form with different fields and with input type="file". I use fileupload jQuery library.
Select file
Call
$('#some_id').fileupload().fileupload(
'send',
{
files: file,
url: widget.options.saveVideoUrl,
}
).success(
//...
(first fileupload called for init)
Try again to select file. Got: No files selected, clear console, etc..
Upd.1
The problem appear in E-commerce framework Magento2 in admin area.
The described form appear in such entity like 'slide-out panel'. It means that there is div block and this block wrapped in aside block using javascript.
<button onclick="jQuery('#new').modal('openModal')" .... >
<span>New</span>
</button>
Here is demo example:
Admin URL: https://iwdagency.com/magento2/admin
Username: admin
Password: admin123
Open Products / Catalog / select any product / click on New category
You should see following panel:
On such panel I've added by php constructor fields:
<div class="admin__field field field-new_video_screenshot " data-ui-id="product-tabs-tab-google-experiment-fieldset-element-form-field-new-video-screenshot">
<label class="label admin__field-label" for="..." data-ui-id="product-tabs-tab-google-experiment-fieldset-element-file-image-label"><span>Preview Image</span></label>
<div class="admin__field-control control">
<input id="...." name="image" data-ui-id="product-tabs-tab-google-experiment-fieldset-element-file-image" value="" title="Preview Image" type="file">
</div>
</div>
Script:
define([
'jquery',
'jquery/ui',
'Magento_Ui/js/modal/modal',
'mage/translate',
'mage/backend/tree-suggest',
'mage/backend/validation'
], function ($) {
'use strict';
$.widget('mage.newDialog', {
_create: function () {
var widget = this;
var newVideoForm = $('#new');
this.element.modal({
type: 'slide',
modalClass: 'mage-new-dialog form-inline',
title: $.mage.__('Create'),
buttons: [{
text: $.mage.__('Create'),
class: 'action-primary',
click: function (e) {
var file = $('#new_screenshot').get(0).files[0];
var result = $('#new_screenshot').fileupload().fileupload(
'send',
{
files: file,
url: widget.options.saveUrl,
}
).success(
function(result, textStatus, jqXHR)
{
var data = JSON.parse(result);
data['url'] = $('#new_url').val();
data['name'] = $('#new_name').val();
data['description'] = $('#new_description').val();
$('#media_gallery_content').trigger('addItem', data);
$('#new').modal('closeModal')
}
);
}
}],
});
}
});
return $.mage.newDialog;
});
I found the problem.
In my case the problem appear after initialization fileUpload library.
When I selected input:file, the library wasn't initialized (read as infected). When I pressed the button, initialization ran and any operations with this input become unavailable.
Solution is following: clone our input before it become infected, than do our operations and at the end replace existing infected input with its healthy copy, created before.

How to upload multiple images in Django using Dropzone for multiple image fields

I am working on a project where the functionality is the user can upload his multiple images with a drag-n-drop feature. I am developing using the Django-python. I have implemented the functionality of drag-n-drop in django template, but I am getting error for images while submitting the form data.
My Html template code is :
<form id="newUserForm" name="newUserForm" data-abide action="{% url 'saveNewUserInfo'%}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="section"></div>
some input fields
<!-- The div for uploading the images -->
<div class="dropzone" style="border: 1px solid red;"></div>
<input type="submit" value="save">
</form>
I am using a dropzone.js for implementing the drag-drop-and sortable
The error is coming as MultiValueDictKeyError at /saveNewUserInfo/, Exception Value: "'file'"
My Model is :
class CustomerProfile(models.Model):
customer_id = models.CharField(db_column='customer_id', primary_key=True, max_length=20)
first_name = models.CharField(db_column='first_name', max_length=30, blank=True, null=True)
last_name = models.CharField(db_column='last_name', max_length=30,blank=True,null=True)
user_name = models.CharField(db_column='user_name', max_length=50,unique=True)
phone_number = models.CharField(db_column='phone_number', max_length=15,blank=True,null=True)
email_id = models.EmailField(db_column='email_id', max_length=50,blank=True, null=True)
user_image1 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image1', max_length=100)
user_image2 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image2', max_length=100)
user_image3 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image3', max_length=100)
user_image4 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image4', max_length=100)
user_image5 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image5', max_length=100)
forms.py
class CustomerInfoForm(forms.ModelForm):
class Meta:
model = CustomerProfile
Please suggest how to store the dropzone multiple images into these image fields. Appreciate for suggestions..
I am glad that you have solved it. I have spent a few hours on this this is how I solved it:
The main issue with using dropzone is that as soon as files being droped in it, it will start to upload. So the images will not upload along with the rest of the form data.
To deal with this, I had to create the dropzone object programmatically with the following settings:
$(document).ready(function(){
var list_of_files = new Array();
Dropzone.autoDiscover = false; //prevent dropzone to automatically discover the dropzone object in your html
$("div#dropzone").dropzone({
uploadMultiple: true, // allow multiple upload
autoProcessQueue: false, // prevent dropzone from uploading automatically
url: "/", //dropzone needs a url attribute or it complains, what value you put here does not really matter. It is only purpose is to prevent a javascript error message from chrome console
maxFiles: 5, //set max uploads to 5 since you only have 5 image files in your model
init: function(){
//everytime a file is uploaded, save the file object
//for later use
this.on("addedfile", function(file)
{
if (list_of_files.length < 5)
{
list_of_files.push(file)
console.log("file added");
}
});
}
});
// the following function override the "submit" button in the form
$(document).on("click", "button", function(e){
e.preventDefault() //prevent the form from submitting
console.log('num of files: ' + list_of_files.length);
var formData = new FormData(); // construct our own upload data
var inputs = $("#newUserForm input");
//get all of the data from textboxes
$.each(inputs, function(obj, v){
var name = $(v).attr("name")
var val = $(v).val();
console.log('name: ' + name + ' value: ' + val);
formData.append(name, val);
});
//get the file object from dropzone and put it into our formdata
for(i=0;i<list_of_files.length;i++)
{
formData.append('user_image'+(i+1), list_of_files[i]);
}
var request = new XMLHttpRequest();
request.open("POST", "/"); //config your post url here
request.send(formData); //send the post request to server
});
});
Here is the template file:
<form id="newUserForm" name="newUserForm" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% if form %}
{% for field in form %}
<p>{{ field.label_tag }} {{ field }}</p>
{% endfor %}
{% endif %}
<!-- The div for uploading the images -->
<div id="dropzone" class="dropzone"></div>
<button id='save'> save </button>
</form>
I also added exclude to forms.py (so that these fields will not show up in our template, we have dropzone to replace them):
class CustomerInfoForm(forms.ModelForm):
class Meta:
model = CustomerProfile
exclude=('user_image1','user_image2','user_image3','user_image4','user_image5')
All of the code above does is to submit the data from each text box with the images to your views.py together in one step
Here is the views.py:
def index(request):
if request.method == 'POST':
form = CustomerInfoForm(request.POST)
if (form.is_valid()):
instance = form.save(commit=False)
#request.FILES contains all of the uploaded images
#key is 'user_image1', 'user_image2', value is the image file in memory
for key, value in request.FILES.iteritems():
a_path = '/a/b'
save_uploadfile_to_disk(a_path, file)
setattr(instance, key, a_path) //I made up the path here
form.save() //save the form for real
#do not forget to return a response
else:
print form.errors #for debugging only
else:
form = CustomerInfoForm()
context = {'form': form}
return render(request, 'test_dropzone/index.html', context)
def save_uploadfile_to_disk(full_path, file):
with open(full_path, 'w+') as destination:
for chunk in file.chunks():
destination.write(chunk)
I tested this solution using Django 1.8 and it works. I checked the database and the path has been written to the record correctly.
Now, to reflect upon this solution, it kind of defeated the purpose of using dropzone. Because users cannot upload the photos as soon as a file has been selected.
Since you have also solved this problem. Please post your solution and I am looking forward to learn something new from yours :)
Small upgrade on previous post overriding submit, I would like to add options:selected looping.
$('option:selected').each(function(){
var name = $(this).parent().attr('name')
if ($(this).val()) {
var val = $(this).val()
console.log('name: ' + name + ' value: ' + val);
formData.append(name, val);
}
else {
var val = ""
console.log('name: ' + name + ' value: ' + val);
formData.append(name, val);
}
});

Categories