Is it possible to simulate/fake the drop event using javascript only? How to test this type of event?
Take for example this dnd upload sample page , is it possible to trigger the "drop" event with a file without actually dropping a file there? Let's say clicking on a button?
I have started writing a Sukuli script that can control the mouse and do the trick but I was looking for a better solution.
EDIT
#kol answer is a good way to get rid of the drag and drop event but I still have to manually select a file from my computer. This is the bit I am interested in simulating. Is there a way to create a file variable programatically?
var fileInput = document.getElementById('fileInput'),
file = fileInput.files[0];
1. Dropping image selected by the user
I've made a jsfiddle. It's a stripped-down version of the html5demos.com page you've referred to, but:
I added an <input type="file"> tag which can be used to select an image file from the local computer, and
I also added an <input type="button"> tag with an onclick handler, which simulates the "drop file" event by directly calling the ondrop event handler of the DND-target div tag.
The ondrop handler looks like this:
holder.ondrop = function (e) {
this.className = '';
e.preventDefault();
readfiles(e.dataTransfer.files);
}
That is, we have to pass an argument to ondrop, which
has a dataTransfer field with a files array subfield, which contains the selected File, and
has a preventDefault method (a function with no body will do).
So the onclick handler of the "Simulate drop" button is the following:
function simulateDrop() {
var fileInput = document.getElementById('fileInput'),
file = fileInput.files[0];
holder.ondrop({
dataTransfer: { files: [ file ] },
preventDefault: function () {}
});
}
Test
Select an image file (png, jpeg, or gif)
Click on the "Simulate drop" button
Result
2. Dropping autogenerated test files without user interaction (GOOGLE CHROME ONLY!!!)
I've made another jsfiddle. When the page is loaded, a function gets called, which:
creates a text file into the temporary file system, and
loads and drops this text file into the target <div>; then
creates an image file into the temporary file system, and
loads and drops this image file into the target <div>.
The code of this drop-simulator function call is the following:
(function () {
var fileErrorHandler = function (e) {
var msg = "";
switch (e.code) {
case FileError.QUOTA_EXCEEDED_ERR:
msg = "QUOTA_EXCEEDED_ERR";
break;
case FileError.NOT_FOUND_ERR:
msg = "NOT_FOUND_ERR";
break;
case FileError.SECURITY_ERR:
msg = "SECURITY_ERR";
break;
case FileError.INVALID_MODIFICATION_ERR:
msg = "INVALID_MODIFICATION_ERR";
break;
case FileError.INVALID_STATE_ERR:
msg = "INVALID_STATE_ERR";
break;
default:
msg = "Unknown Error";
break;
};
console.log("Error: " + msg);
},
requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem,
dropFile = function (file) {
holder.ondrop({
dataTransfer: { files: [ file ] },
preventDefault: function () {}
});
};
if (!requestFileSystem) {
console.log("FileSystem API is not supported");
return;
}
requestFileSystem(
window.TEMPORARY,
1024 * 1024,
function (fileSystem) {
var textFile = {
name: "test.txt",
content: "hello, world",
contentType: "text/plain"
},
imageFile = {
name: "test.png",
content: "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",
contentType: "image/png",
contentBytes: function () {
var byteCharacters = atob(this.content),
byteArrays = [], offset, sliceSize = 512, slice, byteNumbers, i, byteArray;
for (offset = 0; offset < byteCharacters.length; offset += sliceSize) {
slice = byteCharacters.slice(offset, offset + sliceSize);
byteNumbers = new Array(slice.length);
for (i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return byteArrays;
}
};
// Create and drop text file
fileSystem.root.getFile(
textFile.name,
{ create: true },
function (fileEntry) {
fileEntry.createWriter(
function (fileWriter) {
fileWriter.onwriteend = function(e) {
console.log("Write completed (" + textFile.name + ")");
fileSystem.root.getFile(
textFile.name,
{},
function (fileEntry) {
fileEntry.file(
function (file) {
dropFile(file);
},
fileErrorHandler
);
},
fileErrorHandler
);
};
fileWriter.onerror = function(e) {
console.log("Write failed (" + textFile.name + "): " + e.toString());
};
fileWriter.write(new Blob([ textFile.content ], { type: textFile.contentType }));
},
fileErrorHandler
);
},
fileErrorHandler
);
// Create and drop image file
fileSystem.root.getFile(
imageFile.name,
{ create: true },
function (fileEntry) {
fileEntry.createWriter(
function (fileWriter) {
fileWriter.onwriteend = function(e) {
console.log("Write completed (" + imageFile.name + ")");
fileSystem.root.getFile(
imageFile.name,
{},
function (fileEntry) {
fileEntry.file(
function (file) {
dropFile(file);
},
fileErrorHandler
);
},
fileErrorHandler
);
};
fileWriter.onerror = function(e) {
console.log("Write failed (" + imageFile.name + "): " + e.toString());
};
fileWriter.write(new Blob(imageFile.contentBytes(), { type: imageFile.contentType }));
},
fileErrorHandler
);
},
fileErrorHandler
);
},
fileErrorHandler
);
})();
The content of the auto-generated text file is given as a string, and the content of the image file is given as a base64-encoded string. These are easy to change. For example, the test text file can contain not just plain text, but HTML too. In this case, don't forget to change the textFile.contentType field from text/plain to text/html, and to add this content type to the acceptedTypes array and to the previewfile function. The test image can also be changed easily, you just need an image-to-base64 converter.
I had to extend the drop handler code to handle text files in addition to images:
acceptedTypes = {
'text/plain': true, // <-- I added this
'image/png': true,
'image/jpeg': true,
'image/gif': true
},
...
function previewfile(file) {
if (tests.filereader === true && acceptedTypes[file.type] === true) {
var reader = new FileReader();
if (file.type === 'text/plain') { // <-- I added this branch
reader.onload = function (event) {
var p = document.createElement("p");
p.innerText = event.target.result;
holder.appendChild(p);
}
reader.readAsText(file);
} else {
reader.onload = function (event) {
var image = new Image();
image.src = event.target.result;
image.width = 250; // a fake resize
holder.appendChild(image);
};
reader.readAsDataURL(file);
}
} else {
holder.innerHTML += '<p>Uploaded ' + file.name + ', ' + file.size + ' B, ' + file.type;
console.log(file);
}
}
Note that after loading the jsfiddle, the autogenerated files can be listed for debugging purposes:
Result
The screenshot shows that the simulated drop inserted the content of the autogenerated text file before the autogenerated image. The HTML code of the DND-target <div> looks like this:
<div id="holder" class="">
<p>hello, world</p>
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggkFBTzlUWEwwWTRPSHdBQUFBQkpSVTVFcmtKZ2dnPT0=" width="250">
</div>
#kol answer is a good way to get rid of the drag and drop event but I
still have to manually select a file from my computer. This is the bit
I am interested in simulating. Is there a way to create a file
variable programatically? -caiocpricci2
Try this
function createFile() {
var create = ["<!doctype html><div>file</div>"];
var blob = new Blob([create], {"type" : "text/html"});
return ( blob.size > 0 ? blob : "file creation error" )
};
createFile()
Related
I have an action class that runs across the entire app which handles file (images) uploads:
class UploadImageAction implements UploadImageContract
{
public function handle(Request $request, $imageProperty, $image, $imageDir)
{
if ($request->hasFile($imageProperty)) {
// Handle uploading lf_image
if (!is_null($image) && Storage::exists($image)) {
// Throw exceptions here
Storage::delete($image);
}
// Throw exceptions here
return $request->file($imageProperty)->store($imageDir);
}
}
}
And I resolve() this class withing the Service class:
public function handleAttachments($request, $report)
{
// Handle Attachments
$uploadImageAction = resolve(UploadImageAction::class);
// Handle attachment action
if($request->hasFile('attachment')) {
$report->attachment = $uploadImageAction->handle($request, 'attachment', $report->attachment, 'reports');
}
return $report;
}
Then passing it to the controller like so:
public function store(ReportsRequest $request, ReportService $reportService)
{
try
{
$reportService->storeReport($request);
return redirect('data-entry/reports')->with('success', 'Report Added Successfully');
}
catch (ImageUploadException $exception)
{
}
Reason for not calling handleAttachment() in the store() is because it's already passed with the validation within storeReport() method in Service class:
$report->fill($request->validated());
$report = $this->handleAttachments($request, $report);
$report->save();
This functionality works, but sinsce I tried adding Dropzone, that's where the issue happened.
the url of the dropzone is set like so: url: "{{ route('data-entry.reports.create') }}",. Also tried reports.store instead of .create
This is what I get in laravel debugbar:
and in the dev tools:
JS code:
// set the dropzone container id
const id = "#kt_dropzonejs_example_2";
const dropzone = document.querySelector(id);
// set the preview element template
var previewNode = dropzone.querySelector(".dropzone-item");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
var myDropzone = new Dropzone(id, { // Make the whole body a dropzone
url: "{{ route('data-entry.reports.create') }}", // Set the url for your upload script location
parallelUploads: 20,
previewTemplate: previewTemplate,
maxFilesize: 1, // Max filesize in MB
autoQueue: false, // Make sure the files aren't queued until manually added
previewsContainer: id + " .dropzone-items", // Define the container to display the previews
clickable: id + " .dropzone-select" // Define the element that should be used as click trigger to select files.
});
myDropzone.on("addedfile", function (file) {
// Hookup the start button
file.previewElement.querySelector(id + " .dropzone-start").onclick = function () { myDropzone.enqueueFile(file); };
const dropzoneItems = dropzone.querySelectorAll('.dropzone-item');
dropzoneItems.forEach(dropzoneItem => {
dropzoneItem.style.display = '';
});
dropzone.querySelector('.dropzone-upload').style.display = "inline-block";
dropzone.querySelector('.dropzone-remove-all').style.display = "inline-block";
});
// Update the total progress bar
myDropzone.on("totaluploadprogress", function (progress) {
const progressBars = dropzone.querySelectorAll('.progress-bar');
progressBars.forEach(progressBar => {
progressBar.style.width = progress + "%";
});
});
myDropzone.on("sending", function (file) {
// Show the total progress bar when upload starts
const progressBars = dropzone.querySelectorAll('.progress-bar');
progressBars.forEach(progressBar => {
progressBar.style.opacity = "1";
});
// And disable the start button
file.previewElement.querySelector(id + " .dropzone-start").setAttribute("disabled", "disabled");
});
// Hide the total progress bar when nothing's uploading anymore
myDropzone.on("complete", function (progress) {
const progressBars = dropzone.querySelectorAll('.dz-complete');
setTimeout(function () {
progressBars.forEach(progressBar => {
progressBar.querySelector('.progress-bar').style.opacity = "0";
progressBar.querySelector('.progress').style.opacity = "0";
progressBar.querySelector('.dropzone-start').style.opacity = "0";
});
}, 300);
});
// Setup the buttons for all transfers
dropzone.querySelector(".dropzone-upload").addEventListener('click', function () {
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
});
// Setup the button for remove all files
dropzone.querySelector(".dropzone-remove-all").addEventListener('click', function () {
dropzone.querySelector('.dropzone-upload').style.display = "none";
dropzone.querySelector('.dropzone-remove-all').style.display = "none";
myDropzone.removeAllFiles(true);
});
// On all files completed upload
myDropzone.on("queuecomplete", function (progress) {
const uploadIcons = dropzone.querySelectorAll('.dropzone-upload');
uploadIcons.forEach(uploadIcon => {
uploadIcon.style.display = "none";
});
});
// On all files removed
myDropzone.on("removedfile", function (file) {
if (myDropzone.files.length < 1) {
dropzone.querySelector('.dropzone-upload').style.display = "none";
dropzone.querySelector('.dropzone-remove-all').style.display = "none";
}
});
As set in your route file (in the comment) the post route is named 'data-entry.reports.store'
So change the route:
var myDropzone = new Dropzone(id, { // Make the whole body a dropzone
url: "{{ route('data-entry.reports.store') }}", // Set the url for your upload script location
parallelUploads: 20,
previewTemplate: previewTemplate,
maxFilesize: 1, // Max filesize in MB
autoQueue: false, // Make sure the files aren't queued until manually added
previewsContainer: id + " .dropzone-items", // Define the container to display the previews
clickable: id + " .dropzone-select" // Define the element that should be used as click trigger to select files.
});
make sure to clear your route cache using php artisan route:clear
I figured out the issue
Since the image upload field is required, as well as the rest of the form, Dropzone doesn't read the uploaded file since there are some required fields haven't been filled!
Dropzone actually have a documentation about this:
https://docs.dropzone.dev/configuration/tutorials/combine-form-data-with-files
Since the files are combined with data in the Service class, I need to set autoProcessQueue to false and trigger it with the submit button like myDropzone.processQueue(); once all of the fields are filled to send everything to DB at once.
I have a drag and drop container for uploading images. Something like the option that stackoverflow has in the editor. As you know, it works in two ways:
drag and drop an image
click on the container and then a window will be opened to choose an image
Now I'm exactly doing something like that:
// click
$('.upload_image').on('change', function () {
file = $(this)[0].files;
frm = $(this).closest('form');
addImageToInput();
return false;
});
// drag and drop
$(".container").on('drop dragdrop', function (e) {
file = e.originalEvent.dataTransfer.files;
frm = $(this).closest('form');
addImageToInput();
return false;
});
Also I have one more function for making a preview:
function addImageToInput() {
if ( file !== "" || frm !== "" ) {
let uploadFormData = new FormData(frm[0]);
uploadFormData.append("imageToUpload", file[0]);
readURL(frm.find(".upload_image")[0]);
formData = uploadFormData;
} else {
alert('something went wrong');
}
}
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('.modal-dropzone-img').html("<img src='" + e.target.result + "' class='upload_image_preview_img'/>");
}
reader.readAsDataURL(input.files[0]);
}
}
Anyway, the preview part works well when I attach an image by using "click" (browse) the image, and the preview part doesn't word (even no error throws) when I use drag and drop approach.
After some tests, I figured out, these aren't equal:
file = $(this)[0].files; // click approach
file = e.originalEvent.dataTransfer.files; // drag and drop approach
Any idea how can I make them equal? (in other word, I have to make the second one like the first one, because the first one is the working one)
I have modified the readURL method little bit to accept a file only, it can be drag drop or uploaded . Also addImageToInput() is changed accordingly
function addImageToInput() {
if ( file !== "" || frm !== "" ) {
let uploadFormData = new FormData(frm[0]);
uploadFormData.append("imageToUpload", file[0]);
readURL(file[0]);
formData = uploadFormData;
} else {
alert('something went wrong');
}
}
function readURL(input) {
if (input) {
var reader = new FileReader();
reader.onload = function(e) {
$('.modal-dropzone-img').html("<img src='" + e.target.result + "' class='upload_image_preview_img'/>");
}
reader.readAsDataURL(input);
}
}
here is a working fiddle
https://jsfiddle.net/153dp05q/
I'm working on hybrid mobile app using html5/js. It has a function download zip file then unzip them. The download function is not problem but I don't know how to unzip file (using javascript).
Many people refer to zip.js but it seems only reading zip file (not unzip/extract to new folder)
Very appreciate if someone could help me !!!
Have a look at zip.js documentation and demo page. Also notice the use of JavaScript filesystem API to read/write files and create temporary files.
If the zip file contains multiple entries, you could read the zip file entries and display a table of links to download each individual file as in the demo above.
If you look the source of the demo page, you see the following code (code pasted from Github demo page for zip.js) (I've added comments to explain):
function(obj) {
//Request fileSystemObject from JavaScript library for native support
var requestFileSystem = obj.webkitRequestFileSystem || obj.mozRequestFileSystem || obj.requestFileSystem;
function onerror(message) {
alert(message);
}
//Create a data model to handle unzipping and downloading
var model = (function() {
var URL = obj.webkitURL || obj.mozURL || obj.URL;
return {
getEntries : function(file, onend) {
zip.createReader(new zip.BlobReader(file), function(zipReader) {
zipReader.getEntries(onend);
}, onerror);
},
getEntryFile : function(entry, creationMethod, onend, onprogress) {
var writer, zipFileEntry;
function getData() {
entry.getData(writer, function(blob) {
var blobURL = creationMethod == "Blob" ? URL.createObjectURL(blob) : zipFileEntry.toURL();
onend(blobURL);
}, onprogress);
}
//Write the entire file as a blob
if (creationMethod == "Blob") {
writer = new zip.BlobWriter();
getData();
} else {
//Use the file writer to write the file clicked by user.
createTempFile(function(fileEntry) {
zipFileEntry = fileEntry;
writer = new zip.FileWriter(zipFileEntry);
getData();
});
}
}
};
})();
(function() {
var fileInput = document.getElementById("file-input");
var unzipProgress = document.createElement("progress");
var fileList = document.getElementById("file-list");
var creationMethodInput = document.getElementById("creation-method-input");
//The download function here gets called when the user clicks on the download link for each file.
function download(entry, li, a) {
model.getEntryFile(entry, creationMethodInput.value, function(blobURL) {
var clickEvent = document.createEvent("MouseEvent");
if (unzipProgress.parentNode)
unzipProgress.parentNode.removeChild(unzipProgress);
unzipProgress.value = 0;
unzipProgress.max = 0;
clickEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
a.href = blobURL;
a.download = entry.filename;
a.dispatchEvent(clickEvent);
}, function(current, total) {
unzipProgress.value = current;
unzipProgress.max = total;
li.appendChild(unzipProgress);
});
}
if (typeof requestFileSystem == "undefined")
creationMethodInput.options.length = 1;
fileInput.addEventListener('change', function() {
fileInput.disabled = true;
//Create a list of anchor links to display to download files on the web page
model.getEntries(fileInput.files[0], function(entries) {
fileList.innerHTML = "";
entries.forEach(function(entry) {
var li = document.createElement("li");
var a = document.createElement("a");
a.textContent = entry.filename;
a.href = "#";
//Click event handler
a.addEventListener("click", function(event) {
if (!a.download) {
download(entry, li, a);
event.preventDefault();
return false;
}
}, false);
li.appendChild(a);
fileList.appendChild(li);
});
});
}, false);
})();
})(this);
==== UPDATED QUESTION ====
I have control over onComplete state. That's not the case. The problem is that I don't know how to remove currently uploaded item's Progress Bar. Pls, check the screenshot.
I am using a jQuery plugin for multiupload with the support of HTML5 File API located on this website named damnUploader.
File upload works fine, but I'm stuck at the point where I need to hide the uploading progress bar once the upload is finished, but do not know how to do it without any special key to tell to remove progress bar from that element.
==== UPDATED QUESTION ====
To clarify my question, here is a screenshot. 5th and 6th images are at the uploading state. 6th image is about to be finished, so once it's successfully uploaded, I want to hide that progress bar which is below that image, but without touching the other progress bars on the other items.
Here is the javascript code (just search the function where is console.log(this._id); line:
var announcements = function () {
/*** ******************** ***/
/*** 1.1 MAIN INIT METHOD ***/
function _init() {
// Main inits on document ready state
}
/*** ********************* ***/
/*** 1.2 PRIVATE FUNCTIONS ***/
function _form_upload(){
// Main form for fallbacks
var $form_form = $('#form');
// Standard input file
var $form_file_input = $('#file_uploader');
// File POST field name (for ex., it will be used as key in $_FILES array, if you using PHP)
var $form_file_fieldName = 'image-file';
// Upload url
var $form_file_url = '/announcements/form_file_upload/' + $form_file_fieldName;
// List of available thumbnail previews based on selected files
var $form_file_list = $('#form_file_list');
// File upload progress
var $form_file_progress = $('#form_file_progress');
// Settings
var $form_file_autostartOn = true;
var $form_file_previewsOn = true;
// Misc
var isImgFile = function(file) {
return file.type.match(/image.*/);
};
var imagesCount = $form_file_list.length + 1;
var templateProgress = $form_file_list.find('div.progress').remove().wrap('<div/>').parent().html()
var template = $form_file_list.html()
// File uploader init
$form_file_input.damnUploader({
// URL of server-side upload handler
url: $form_file_url,
// File POST field name
fieldName: $form_file_fieldName,
// Container for handling drag&drops (not required)
dropBox: $('html'),
// Expected response type ('text' or 'json')
dataType: 'JSON',
// Multiple selection
multiple: false
});
// Creates queue table row with file information and upload status
var createRowFromUploadItem = function(ui) {
var $row = $('<div class="col-xs-4"/>').appendTo($form_file_list);
var $progressBar = $('<div/>').addClass('progress-bar progress-bar-success').css('width', '0%').attr('aria-valuemin', 0).attr('aria-valuemax', 100);
var $pbWrapper = $('<div/>').addClass('progress').append($progressBar);
// Defining cancel button & its handler
/*
var $cancelBtn = $('<a/>').attr('href', 'javascript:').append(
$('<span/>').addClass('glyphicon glyphicon-remove')
).on('click', function() {
var $statusCell = $pbWrapper.parent();
$statusCell.empty().html('<i>cancelled</i>');
ui.cancel();
console.log((ui.file.name || "[custom-data]") + " canceled");
});
*/
// Generating preview
var $preview;
if ($form_file_previewsOn) {
if (isImgFile(ui.file)) {
// image preview (note: might work slow with large images)
$preview = $('<img/>').attr('width', 120);
ui.readAs('DataURL', function(e) {
$preview.attr('src', e.target.result);
});
} else {
// plain text preview
$preview = $('<i/>');
ui.readAs('Text', function(e) {
$preview.text(e.target.result.substr(0, 15) + '...');
});
}
} else {
$preview = $('<i class="fa fa-image"></i>');
}
// Constructing thumbnails markup
$('<div class="thumbnail"/>').append($preview).appendTo($row);
$row.find('.thumbnail').append('<button type="button" name="formImageRemove" value="imageRemove" class="btn btn-danger btn-xs" role="button" />');
$row.find('.thumbnail').prepend(loading);
$row.find('.uploading').append($pbWrapper);
$row.find('button').append('<i class="fa fa-fw fa-trash-o" />');
return $progressBar;
};
// File adding handler
var fileAddHandler = function(e) {
// e.uploadItem represents uploader task as special object,
// that allows us to define complete & progress callbacks as well as some another parameters
// for every single upload
var ui = e.uploadItem;
var filename = ui.file.name || ""; // Filename property may be absent when adding custom data
// We can replace original filename if needed
if (!filename.length) {
ui.replaceName = "custom-data";
} else if (filename.length > 14) {
ui.replaceName = filename.substr(0, 10) + "_" + filename.substr(filename.lastIndexOf('.'));
}
// Show info and response when upload completed
var $progressBar = createRowFromUploadItem(ui);
ui.completeCallback = function(success, data, errorCode) {
// Original filename
// console.log((this.file.name || "[custom-data]"));
if (success) {
// Add animation class for fadeout
$(this).find('.loading').addClass('animated fadeOutDown');
console.log(this._id);
console.log(ui);
// Add some data to POST in upload request once upload finished and new filename retrieved
ui.addPostData($form_form.serializeArray()); // from array
ui.addPostData('images[]', JSON.parse(data).file_name); // .. or as field/value pair
} else {
console.log('uploading failed. Response code is:', errorCode);
}
};
// Updating progress bar value in progress callback
ui.progressCallback = function(percent) {
$progressBar.css('width', Math.round(percent) + '%');
};
// To start uploading immediately as soon as added
$form_file_autostartOn && ui.upload();
};
var loading = function(){
return '<div class="loading">\n\t<div class="uploading animated fadeInUp">\n\t\t<img src="/assets/img/loaders/ajax-loader.gif" />\n\t</div>\n</div>';
}
// File Uploader events
$form_file_input.on({
'du.add' : fileAddHandler,
'du.limit' : function() {
console.error("File upload limit exceeded!");
},
'du.completed' : function() {
console.info('******');
console.info("All uploads completed!");
}
});
}
/*** ************************************************** ***/
/*** 1.3 MAKE PRIVATE FUNCTIONS ACCESSIBLE FROM OUTSIDE ***/
return {
init: function () {
_init();
},
form_upload:function(){
_form_upload();
}
};
}();
$(document).ready(function () {
announcements.init();
});
Make a custom event and trigger it with Jquery:
$( "#hide_loading" ).on( "done", function() {
( "#hide_loading" ).animate({
opacity: 0
}, 5000);
});
if ( success ) {
$( ".hide_loading").trigger( "loadingfade" );
}
and if you completely want to remove it from the DOM structure after the animation:
$( "#hide_loading" ).on( "loadingfade", function() {
$( ".hide_loading" ).animate({
//put animations here (don't forget cross browser compatibility)
opacity: 0,
}, 5000, function() { //this function is called when the animation is completed
$( "#hide_loading" ).remove();
});
});
(now just add the class hide_loading to your loading elements)
I'm maintaining an existing app (cannot change server-side code, only client-side js) and was asked to add the capability to upload files from clipboard.
At present moment there is a standard file-selection form
<form id="file_form" name="file_form" enctype="multipart/form-data" method="post" action="/upload">
<label for="selector">
File Location
</label>
<input type="file" id="selector" name="selector" title="Choose file">
<input type="submit" id="submit" value="ОК">
<input type="button" id="cancel" onclick="cancel()" value="Cancel">
</form>
So what I need is a way to fill input#selector with the file from clipboard. I don't need progress bars, preview, image crop, etc... as simple as possible, but remember that I cannot change anything on the server.
Is there solution that would work in Chrome, FF and IE?
Most things I googled were either full of excessive functionality and required a lot of external js or server-side code changes or didn't work in anything other than Chrome...
Your can refere to this site: https://www.pastefile.com
the core code paste.js such as
(function ($) {
'use strict';
var readImagesFromEditable = function (element, callback) {
setTimeout(function () {
$(element).find('img').each(function (i, img) {
getImageData(img.src, callback);
});
}, 1);
};
var getImageData = function (src, callback) {
var loader = new Image();
loader.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = loader.width;
canvas.height = loader.height;
var context = canvas.getContext('2d');
context.drawImage(loader, 0, 0, canvas.width, canvas.height);
try {
var dataURL = canvas.toDataURL('image/png');
if (dataURL) {
callback({
dataURL: dataURL
});
}
} catch (err) {}
};
loader.src = src;
};
$.paste = function () {
var handler = function (e) {
var pasteBoard = $(this);
var trigger = function (event, data) {
if (arguments.length > 1)
return pasteBoard.trigger(event, data);
return function (data) {
return pasteBoard.trigger(event, data);
};
};
var clipboardData, text;
if (e.originalEvent) {
clipboardData = e.originalEvent.clipboardData;
if (clipboardData.items) {
var items = clipboardData.items;
// Copy-paste on OSX
if (items.length === 2) {
// If a user pastes image data, there are 2 items: the file name (at index 0) and the file (at index 1)
// but if the user pastes plain text or HTML, /index 0/ is the data with markup and /index 1/ is the plain, unadorned text.
if (items[0].kind === 'string' && items[1].kind === 'file' && items[1].type.match(/^image/)) {
// If the user copied a file from Finder (OS X) and pasted it in the window, this is the result. This is also the result if a user takes a screenshot and pastes it.
// Unfortunately, you can't copy & paste a file from the desktop. It just returns the file's icon image data & filename (on OS X).
} else if (items[0].kind === 'string' && items[1].kind === 'string') {
// Get the plain text
items[0].getAsString(trigger('pasteText'));
}
} else {
var item = items[0];
if (!item) return;
if (item.type.match(/^image\//)) {
trigger('pasteImage', item.getAsFile());
} else if (item.type === 'text/plain') {
item.getAsString(trigger('pasteText'));
}
}
} else {
if (clipboardData.types.length) {
text = clipboardData.getData('Text');
trigger('pasteText', text);
} else {
readImagesFromEditable(pasteBoard, trigger('pasteImage'));
}
}
} else if ((clipboardData = window.clipboardData)) {
text = clipboardData.getData('Text');
if (text) {
trigger('pasteText', text);
} else {
readImagesFromEditable(pasteBoard, trigger('pasteImage'));
}
}
setTimeout(function() {
pasteBoard.empty();
}, 1);
};
return $('<div/>')
.prop('contentEditable', true)
.css({
width: 1,
height: 1,
position: 'fixed',
left: -10000,
overflow: 'hidden'
})
.on('paste', handler);
};
})(jQuery);
it is not so hard to understand.