Dropzone remove previous image - javascript

I'm needing help with an answer to a previous question
How to limit the number of dropzone.js files uploaded?
where there was a solution to use
Dropzone.options.myAwesomeDropzone = {
accept: function(file, done) {
console.log("uploaded");
done();
},
init: function() {
this.on("addedfile", function() {
if (this.files[1]!=null){
this.removeFile(this.files[0]);
}
});
}
};
But being a js numpty, I don't know where to put this. I assume that my form must have the id myAwesomeDropzone and that the code above needs to be slotted into the dropzone.js document, but where? if you could provide a 'after' and 'before' or replace answer please.
If someone could give me some pointer it'd be great.
My reputation is less than 50 so I couldn't comment on the original thread. If me posting this as a new thread is wrong, please admins don't just chastise me and close it, but move it or do whatever to allow people to provide help accrodingly.
Cheers
Andy

Your html form should be like below. Notice that the
class="dropzone"
and
id="my-dropzone"
The "my-dropzone" ID is important , DropZone takes this as "myDropzone" , ( hyphen removed and camelcased ). So when you refer to this id in DropZone.options , it should be "myDropzone". This is very important.
<div>
<form action="/file-upload" class="dropzone" id="my-dropzone" style="border:2px dotted #337ab7">
<div class="dz-message">
Drag n drop photos here or click to upload.
<br />
<span class="note">(The photos are uploaded to twitter only when the tweet is sent.)</span>
</div>
</form>
</div>
Your should link the css and js file in your html page like so
<script src="./js/dropzone.min.js"></script>
<link href="./css/dropzone.min.css" rel="stylesheet" type="text/css">
On the page load , you should init the dropzone configuration in your JS code for your page as below. I am restricting dropzone to accept only one file and its size should not exceed 5MB.
self.options.maxFilesize = 5; self.options.maxFiles = 1;
Dropzone.autoDiscover = false;
Dropzone.options.myDropzone = {
init: function() {
var self = this;
// config
self.options.addRemoveLinks = true;
self.options.autoProcessQueue = false;
self.options.maxFilesize = 5;
self.options.maxFiles = 1;
self.options.dictFileTooBig =
"Twitter do not allow files greater than 5MB.";
//New file added
self.on("addedfile", function(file) {
console.log('new file added ', file.path);
});
self.on("maxfilesexceeded", function(file) {
alert(
"Only one photo can be attached with the tweet."
);
});
}
};
Now when your page loads , you will see the form & get the drag n drop functionality in your div.
To access the files you can do like below in the javascript on some button click event.
// to get queued files
var myDropzone = Dropzone.forElement("#my-dropzone");
var files = myDropzone.getQueuedFiles();

Related

Why are my Filepond uploads not working on Android devices only?

I am currently using Filepond to upload images to an S3 bucket. This functionality works great on a computer or on iOS devices but refuses to work on Android devices and I'm having the time of my life figuring out the root cause. It should upload just fine across all devices. Has anyone experienced any issues similar to this on an Android device using Filepond? I've also attached below the relevant Filepond code. I don't see any issues with it, but of course, I may be missing something. If anyone could offer a pointer or any kind of advice it would be greatly appreciated or if I left anything out please let me know. Thanks!
JS
<!-- Load FilePond library -->
<script src="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.js"></script>
<script src="https://unpkg.com/filepond/dist/filepond.js"></script>
<script src="//cdn.jsdelivr.net/npm/sweetalert2#10"></script>
<!-- include FilePond jQuery adapter -->
<script src="https://unpkg.com/jquery-filepond/filepond.jquery.js"></script>
<script type="application/javascript">
let tags = [];
let folderOpen = false;
let currentTag = "Uncategorized";
let imageUploadUrl = "{{ url_for('testing_jobs.job_image_upload', id=job.id) }}";
// Page init code
$( document ).ready(() => {
// Select Fields
$(".select2").select2();
// Setup FilePond inputs
$.fn.filepond.registerPlugin(FilePondPluginImagePreview);
// Turn input element into a pond
$('.filepond').filepond();
// Set FilePond properties
$('.filepond').filepond('allowMultiple', true);
$('.filepond').filepond('instantUpload', true);
$('.filepond').filepond('server', {
url: imageUploadUrl,
process: {
onload: (res) => {
// Select the response field to use as a unique ID
let image = JSON.parse(res).image;
if (folderOpen) {
getJobImages(currentTag);
} else {
alert("Image added")
}
return image.id;
}
}
});
// Listen for addfile event
$('.filepond').on('FilePond:addfile', function(e) {
console.log('file added event', e);
// Set the current tag for the image
e.detail.file.setMetadata("tag",currentTag);
});
// Listen for processfile event
$('.filepond').on('FilePond:processfile', function(e) {
console.log('file process event', e);
setTimeout(() => {
e.detail.pond.removeFile();
}, 2000);
});
Html for submitting
<div class="card">
<div class="card-header">
<h4>Upload Images</h4>
</div>
<div class="card-body">
<input type="file" class="filepond">
</div>
</div>
The issue turned out to be the image attachments on my Android device. Set up some checks for checking the file types and now it all works.

Change reductive search to search submit

After having a few small wins with JS (still very much a learner) I have now inherited a task which is to change a reductive search of sorts.
Users now want to have the search work from a submit button, instead of a keyup after 3rd character. I have completed submit forms before where the form would post, but I have never come across something as complex as this before.
I have had a look through the large JS file, and located the search function which contains the keyup function.
F.initSearch = function(opts){
if(!opts || !opts.ele){
return;
}
if(!opts.start_length){
this.opts.search.start_length = 2
}
this.$search_ele = $(this.opts.search.ele);
if(this.$search_ele.length){
this.has_search = true;
this.searchFn = this.buildSearchFn(opts.fields);
this.bindEvent(opts.ele, 'keyup');
}
};
However, I am having difficulty with changing over from keyup to button click.
This is what I have done:
I have updated the form to include the button
<form>
<div class="searchBox">
<input type="text" id="search" class="search__text-input" placeholder="Search"/>
</div>
<div class="formBox">
<button id="searchbtn">Search</button>
</div>
</form>
I have tried to update the script with some jquery which follows the same pattern
$( "#searchbtn" ).this.bindEvent(opts.ele, 'click');
Lastly, I have attempted to then update the existing - which is now leaving me somewhat defeated:
F.initSearch = function(opts) {
if(!opts || !opts.ele) {
return;
}
if(!opts.start_length) {
this.opts.search.start_length = 2
}
this.$search_ele = $(this.opts.search.ele);
if(this.$search_ele.length) {
this.has_search = true;
this.searchFn = this.buildSearchFn(opts.fields);
// this.bindEvent(opts.ele, 'keyup');
/* Trying to swap keyup for button click */
$( "#searchbtn" ).this.bindEvent(opts.ele, 'click');
}
};
Link to JSFiddle: https://jsfiddle.net/mcmacca002/bo0y3u7p/2/
Clearly I am approaching this wrong, and some guidance would be greatly appreciated.

Pagination works but doesn't reattach javascript / css class on reload

Im building a new personal blog and I'm using ajax to post back to a C# Controller to get the results for pagination.
Page 2 loads with the results however, none of the javascript is reloaded because, I believe, when I partially reload the pagination part of the page, it destroys everything in the DOM and because the full page doesn't reload, the javascript isn't invoked.
So I'm looking for a bit of help on working out how to get the external javascript to run again. What it does is adds css classes, gives some fade effects etc.
success: function (data) {
if (data != null) {
var page = data
$('#blogsContainer').empty();
$('#blogsContainer').replaceWith(page);
So the success works, I clear out the blogsContainer with the new data.
I'm guessing I need to add a function after the replace to then apply everything that is in an external main.js file.
The main.js file looks like this
(function($) {
var contentWayPoint = function() {
var i = 0;
$('.ftco-animate').waypoint( function( direction ) {
if( direction === 'down' && !$(this.element).hasClass('ftco-animated') ) {
i++;
$(this.element).addClass('item-animate');
setTimeout(function(){
$('body .ftco-animate.item-animate').each(function(k){
var el = $(this);
setTimeout( function () {
var effect = el.data('animate-effect');
if ( effect === 'fadeIn') {
el.addClass('fadeIn ftco-animated');
} else if ( effect === 'fadeInLeft') {
el.addClass('fadeInLeft ftco-animated');
} else if ( effect === 'fadeInRight') {
el.addClass('fadeInRight ftco-animated');
} else {
el.addClass('fadeInUp ftco-animated');
}
el.removeClass('item-animate');
}, k * 50, 'easeInOutExpo' );
});
}, 100);
}
} , { offset: '95%' } );
};
contentWayPoint();
}
The first page has the following applied to it on page load:
<div class="col-md-4 d-flex ftco-animate fadeInUp ftco-animated">
<div class="blog-entry justify-content-end">
...
</div>
</div>
But as you can see, when I press page 2, the div is missing some key css
<div class="col-md-4 d-flex ftco-animate">
<div class="blog-entry justify-content-end">
</div>
</div>
How would I apply the missing css after the partial reload with ajax?
I hope this is clear what I am trying to do but if not, please just ask.
I think the solution may be to re-execute the contentWayPoint() function at the end of the success callback. However, its likely out of scope by then. There are two simple ways to ensure its not :
The cleanest would be to ensure that the code that sets up your pagination is inside the same (function($) {}) block in main.js - that way it will "capture" the function.
The other, dirtier way, would be to change var contentWaypoint= function... to window.contentWaypoint = function - then use window.contentWaypoint() whenever you need to invoke it. THere are much better ways to doing this, but that might get you going.

How can I validate the file type selected from an input element of type file

I am trying to allow users to upload an image by using the html below
<input class="file-upload" id="imagepath" name="imagepath" type="file" accept="image/x-png,image/jpeg" />
Is there any way to show a validation message if a user selects a file that is not of the correct type using JS/JQuery?
I understand that the 'accept' attribute restricts what a user will see when they are viewing the file explorer however this can be changed using the drop down, to 'All files'.
You can fetch the extension of an uploaded file.
var files = event.target.files;
var filename = files[0].name;
var extension = files[0].type;
And apply the check and allow whichever file type you wanted to allow. Say for images stuff.
if(extension == "jpeg" || extension == "jpg") {
//do you code
} else {
//display an error
}
I think J D already gave you a solid answer on how to check the file type.
I looked around and found an example on MDN which I modified a bit. It exists of a list of accepted file types, like the one in your accept attribute and a function which will check if the type of a file matches the ones in your accept attribute.
The isValidFileType accepts a File and and array as arguments which then will check if the File.type is present in the types array. If it is it will return true and not it will return false.
Same principles as J D described but with a functional programming approach.
// The input element.
const imagePath = document.getElementById('imagepath');
// List of accepted file types, gotten from your input's accept property.
const acceptedFileTypes = imagePath.accept.split(','); // ['image/jpeg', 'image/x-png']
// Check if file has the correct type.
const isValidFileType = (file, types) => types.some(type => type === file.type);
So on your form element you should attach a change event listener. And in that listener loop over all of the files and check if they have the correct extension.
imagePath.addEventListener('change', (event) => {
// Check if every file has the accepted extension.
const filesAccepted = event.target.files.every(file =>
isValidFileType(file, acceptedFiles)
);
if (filesAccepted) {
// Files are accepted
} else {
// Files are not accepted.
}
});
Although J D's example is a lot more compact and to the point, this example provides reusability and prevents you from writing the same code twice, or more. Also extending the list of accepted types is as easy as adding them to the accept attribute of the HTML element.
Thanks For the help guys,
This is the solution I went with in the end and works perfectly
<!--HTML-->
<div id="fileErrorMessage" class="hide" >file type is not suuported</div>
<input class="some-class" id="imagepath" name="imagepath" type="file" accept="image/x-png,image/jpeg" />
/*css*/
#fileErrorMessage {
color: red;
font-weight: bold;
}
.hide {
display: none;
}
//JavaScript
$('#imagepath').on('change', function (event) {
var files = event.target.files;
Array.from(files).forEach(x => {
if (!x.type.includes("jpeg") && !x.type.includes("jpg") && !x.type.includes("png")) {
$("#fileErrorMessage").removeClass("hide");
$('#imagepath').val('');
}
else if (!$("#fileErrorMessage").hasClass("hide")) {
$("#fileErrorMessage").addClass("hide");
}
});
});

How do I pass a value out of a Wordpress Thickbox?

I am currently working on a custom Wordpress plugin which requires the user to create a list in a form, and so to help them populate their list, I have implemented the Wordpress Thickbox. I have made the Thickbox display, with the content I would like, however what I am struggling to do is pass the data back to the original form.
The Original Form is like this:
<input name="input_that_wants_data" id="input_for_data" type="text" />
Click Here for Modal
Just like you would expect any form to be. Basically I want the information from the modal to pass my string back to the input_for_data
The code inside the modal has multiple table rows like this:
<td><input type="checkbox" class="modal_checkbox_class" value="'.$data->value.'"></td>
Basically what I would like to do is build an array of the values of each clicked checkbox, and then use the split function of Javascript to turn it into a string which I would return to the input field outside of the modal.
Any and all help is greatly appreciated. I would prefer a Javascript/JQuery solution to this
I used this tutorial to do something that you want:
https://code.tutsplus.com/tutorials/getting-started-with-the-wordpress-media-uploader--cms-22011
My code looks like this:
function renderMediaUploader() {
'use strict';
var file_frame, image_data;
/**
* If an instance of file_frame already exists, then we can open it
* rather than creating a new instance.
*/
if ( undefined !== file_frame ) {
file_frame.open();
return;
}
/**
* If we're this far, then an instance does not exist, so we need to
* create our own.
*
* Here, use the wp.media library to define the settings of the Media
* Uploader. We're opting to use the 'post' frame which is a template
* defined in WordPress core and are initializing the file frame
* with the 'insert' state.
*
* We're also not allowing the user to select more than one image.
*/
file_frame = wp.media.frames.file_frame = wp.media({
title: 'Select or Upload Media Of Your Chosen Persuasion',
button: {
text: 'Use this media'
},
multiple: true
});
//add items from thickbox to table
file_frame.on( 'select', function() {
var attachment = file_frame.state().get('selection').toJSON();
jQuery.each(attachment, function(i, val){
jQuery('table').show();
jQuery('table tbody').append('<tr class="table_row"><td class="col-sm-2"><img class="img-responsive" src="'+val.url+'"></td><td class="col-sm-8"><input style=" display: block;" type="text" name="entry[url][]" value="'+ val.url +'"></td></tr>');
});
});
// Now display the actual file_frame
file_frame.open();
}
(function( $ ) {
'use strict';
$(function() {
$( '#set-footer-thumbnail' ).on( 'click', function( evt ) {
// Stop the anchor's default behavior
evt.preventDefault();
// Display the media uploader
renderMediaUploader();
});
});
})( jQuery );

Categories