/*!
* Imageuploadify - jQuery plugin
* Allow to change input file to a box allowing drag'n drop and preview images before
* updloading them.
*/
// Semi-colon to protect against concatened scripts, etc...
// Ensure that $ is referencing to jQuery.
// window and document to slightly quicken the process.
// To be sure that undefined is truly undefined (For ES3)
;(function($, window, document, undefined) {
// Prevent issues about browser opening file by dropping it.
window.addEventListener("dragover", function(e) {
e = e || event;
e.preventDefault();
}, false);
window.addEventListener("drop", function(e) {
e = e || event;
e.preventDefault();
}, false);
const compareMimeType = (mimeTypes, fileType, formatFile) => {
// If accept is defined as *.
if (mimeTypes.length < 2 && mimeTypes[0] === "*") {
return true;
}
// Checking all types written in accept.
for (let index = 1; index < mimeTypes.length; index+=3) {
// image/*, audio/*, video/*
if (mimeTypes[index + 1] === "*" &&
fileType.search(new RegExp(mimeTypes[index])) != -1) {
return true;
}
// application/vnd.ms-excel, application/vnd.ms-powerpoint
else if (mimeTypes[index + 1] && mimeTypes[index + 1] != "*" &&
fileType.search(new RegExp("\\*" + mimeTypes[index + 1] + "\\*")) != -1) {
return true;
}
// application/pdf, image/jpg
else if (mimeTypes[index + 1] && mimeTypes[index + 1] != "*" &&
fileType.search(new RegExp(mimeTypes[index + 1])) != -1) {
return true;
}
// .jpg, .pdf .png
else if (mimeTypes[index + 1] === "" &&
(fileType.search(new RegExp(mimeTypes[index])) != -1 || formatFile.search(new RegExp(mimeTypes[index])) != -1)) {
return true;
}
}
return false;
}
// Define the plugin imageuploadify.
$.fn.imageuploadify = function(opts) {
// Override default option with user's if exist.
const settings = $.extend( {}, $.fn.imageuploadify.defaults, opts);
// let totalFiles = []; // Moved totalFiles outside of each() to make it globally accessible
// Initialize every element.
this.each(function() {
// Save the current element to self to avoid conflict.
const self = this;
// Apply on input file having "multiple" attribute only.
// if (!$(self).attr("multiple")) {
// return;
// }
// Save accept files
let accept = $(self).attr("accept") ? $(self).attr("accept").replace(/\s/g, "").split(",") : null;
let result = [];
// Loop the array of accept files to split all part of mimetype or format.
accept.forEach((item) => {
let regexp;
// Select the regexp according to the result (mimetype or format)
if (item.search(/\//) != -1) {
regexp = new RegExp("([A-Za-z-.]*)\/([A-Za-z-*.]*)", "g");
}
else {
regexp = new RegExp("\.([A-Za-z-]*)()", "g");
}
// Exec the regexp and then
const r = regexp.exec(item);
result = result.concat(r);
});
// Array containing all files add by dialog box or drag'n drop.
// let totalFiles = []; // Moved totalFiles outside of each() to make it globally accessible
// Count the number of time a "dragenter" enter the box.
let counter = 0;
// Define the dragbox layout.
let dragbox = $(`
Upload your receipt for verification
`);
// Save all elements of the dragbox.
let overlay = dragbox.find(".imageuploadify-overlay");
let uploadIcon = dragbox.find(".imageuploadify-overlay i");
let imagesList = dragbox.find(".imageuploadify-images-list");
let addIcon = dragbox.find(".imageuploadify-images-list i");
let addMsg = dragbox.find(".imageuploadify-images-list span");
let button = dragbox.find(".imageuploadify-images-list button");
/** FUNCTIONS **/
// Function to read and store files.
const retrieveFiles = (files) => {
totalFiles = [];
imagesList.find('.imageuploadify-container').remove();
for (let index = 0; index < files.length; ++index) {
if (!accept || compareMimeType(result, files[index].type, /(?:\.([^.]+))?$/.exec(files[index].name)[1])) {
const id = Math.random().toString(36).substr(2, 9);
new Compressor(files[index], {
quality: 0.2,
success(result) {
const compressedFile = new File([result], files[index].name, {
type: result.type,
lastModified: Date.now()
});
readingFile(id, compressedFile);
totalFiles.push({
id: id,
file: compressedFile
});
const dataTransfer = new DataTransfer();
totalFiles.forEach(file => dataTransfer.items.add(file.file));
self.files = dataTransfer.files;
},
error(err) {
console.log(err.message);
},
});
}
}
// console.log('Files after compression:', totalFiles);
};
// Function to read a file.
const readingFile = (id, file) => {
const fReader = new FileReader();
// Compute the number of box that could fit in the dragbox and the
// margin according to it.
const width = dragbox.width();
const boxesNb = Math.floor(width / 100);
const marginSize = Math.floor((width - (boxesNb * 100)) / (boxesNb + 1));
// Create the preview file container box.
let container = $(`
${file.name}${file.type}${file.size}
`);
let details = container.find(".imageuploadify-details");
let deleteBtn = container.find("button");
// Preview file container box CSS
// container.css("margin-left", marginSize + "px");
// Manage display/hidding details about preview files.
details.hover(function() {
$(this).css("opacity", "1");
})
.mouseleave(function() {
$(this).css("opacity", "0");
});
// If the given file in the parameter is an image.
if (file.type && file.type.search(/image/) != -1) {
// Associated function to a ending load
fReader.onloadend = function (e) {
// Create the image tag for preview.
let image = $("");
// Paste the image source to display the image preview.
image.attr("src", e.target.result);
// Append the image to its container and then the container to the
// list of files.
container.append(image);
imagesList.append(container);
// Apply left margin to first container of each row and right to last.
// imagesList.find(".imageuploadify-container:nth-child(" + boxesNb + "n+4)").css("margin-left", marginSize + "px");
// imagesList.find(".imageuploadify-container:nth-child(" + boxesNb + "n+3)").css("margin-right", marginSize + "px");
};
}
else if (file.type) {
// Create the generic icon for unknown type file.
let type = "";
// If the file is an audio file, replace the icon by an audio file icon.
if (file.type.search(/audio/) != -1) {
type = "";
}
// If the file is an video file, replace the icon by an video file icon.
else if (file.type.search(/video/) != -1) {
type = "";
}
// Associated function to a ending load
fReader.onloadend = function (e) {
// Create the span tag for the file type.
let span = $("" + type + "");
// Span CSS.
span.css("font-size", "5em");
// Append the span to its container and then the container to the
// list of files.
container.append(span);
imagesList.append(container);
// Apply left margin to first container of each row and right to last.
imagesList.find(".imageuploadify-container:nth-child(" + boxesNb + "n+4)").css("margin-left", marginSize + "px");
imagesList.find(".imageuploadify-container:nth-child(" + boxesNb + "n+3)").css("margin-right", marginSize + "px");
};
}
// Delete the file from the list.
deleteBtn.on("click", function() {
$(this.parentElement).remove();
for (let index = 0; totalFiles.length > index; ++index) {
if (totalFiles[index].id === id) {
totalFiles.splice(index, 1);
break;
}
}
});
// Use the FileReader to read the content of a File.
fReader.readAsDataURL(file);
};
const disableMouseEvents = () => {
// Display the overlay and change the dragbox border color.
overlay.css("display", "flex");
dragbox.css("border-color", "#1b86dc");
// Disable pointer events to avoid miscapture dragexit children's events.
button.css("pointer-events", "none");
addMsg.css("pointer-events", "none");
addIcon.css("pointer-events", "none");
imagesList.css("pointer-events", "none");
}
const enableMouseEvents = () => {
// Hide the overlay and put back the dragbox border color.
overlay.css("display", "none");
dragbox.css("border-color", "rgb(210, 210, 210)");
// Enable back pointer events to capture click, hover...
button.css("pointer-events", "initial");
addMsg.css("pointer-events", "initial");
addIcon.css("pointer-events", "initial");
imagesList.css("pointer-events", "initial");
}
/** EVENTS */
// Change the color background of the button according to the mouse.
button.mouseenter(function onMouseEnter(event) {
button.css("background", "#1b86dc").css("color", "white");
}).mouseleave(function onMouseLeave() {
button.css("background", "white").css("color", "#1b86dc");
});
// When click on the button, simulate click on the original input.
button.on("click", function onClick(event) {
event.stopPropagation();
event.preventDefault();
$(self).click();
});
// Manage events to display an overlay when dragover files.
dragbox.on("dragenter", function onDragenter(event) {
event.stopPropagation();
event.preventDefault();
// Increment the counter.
counter++;
disableMouseEvents();
});
// Manage events to hide the overlay when dragout files.
dragbox.on("dragleave", function onDragLeave(event) {
event.stopPropagation();
event.preventDefault();
// Decrease the counter.
counter--;
// If the counter is equal to 0 (means that the files are entirely out
// of the dragbox).
if (counter === 0) {
enableMouseEvents();
}
});
// Manage events when dropping files.
dragbox.on("drop", function onDrop(event) {
event.stopPropagation();
event.preventDefault();
enableMouseEvents();
// Retrieve the dragged files.
const files = event.originalEvent.dataTransfer.files;
// Read all files (to add them to the preview and push them to the files
// list to submit).
retrieveFiles(files);
});
// Binding resize event to the window.
$(window).bind("resize", function(e) {
window.resizeEvt;
$(window).resize(function () {
// Delete the timeout as long as the window is still resizing.
clearTimeout(window.resizeEvt);
// Compute and change the margin according to the size of the window after
// 0.5 seconds after resizing.
window.resizeEvt = setTimeout(function() {
// Compute the number of box that could fit in the dragbox and the
// margin according to it.
const width = dragbox.width();
const boxesNb = Math.floor(width / 100);
const marginSize = Math.floor((width - (boxesNb * 100)) / (boxesNb + 1));
// Reset all margins of containers boxes.
let containers = imagesList.find(".imageuploadify-container");
for (let index = 0; index < containers.length; ++index) {
$(containers[index]).css("margin-right", "0px");
$(containers[index]).css("margin-left", marginSize + "px");
}
// Apply left margin to first container of each row and right to last.
imagesList.find(".imageuploadify-container:nth-child(" + boxesNb + "n+4)").css("margin-left", marginSize + "px");
imagesList.find(".imageuploadify-container:nth-child(" + boxesNb + "n+3)").css("margin-right", marginSize + "px");
}, 500);
});
})
// Detect when adding files through the dialog box to preview those files
// and add them to the array.
$(self).on("change", function onChange() {
const files = this.files;
retrieveFiles(files);
});
// Hide the original input.
$(self).hide();
// Insert the dragbox after the original hidden input.
dragbox.insertAfter(this);
});
// Return "this" to ensure that chaining methods can be called.
return this;
};
// Default configuraiton of the plugin.
$.fn.imageuploadify.defaults = {
};
}(jQuery, window, document));